Guias · atualizado em · 5 min de leitura · Equipe apipj

CNPJ alfanumérico: o que mudou e como validar no seu sistema

Desde 31 de julho de 2026 a Receita Federal emite CNPJ com letras. O número continua com 14 posições, mas as 12 primeiras podem ter letras maiúsculas, e os dois dígitos verificadores continuam numéricos. Os CNPJs já existentes não mudam. Quem guarda CNPJ como número, valida com uma expressão que só aceita dígitos ou calcula o dígito verificador com parseInt vai rejeitar empresas novas.

Teste um CNPJ agora

O validador abaixo roda só no seu navegador: nada sai desta página. Ele mostra o cálculo dos dígitos verificadores, útil para conferir a sua implementação.

Exemplos:

O que a Receita mudou

A mudança foi instituída pela Instrução Normativa RFB nº 2.229, de 15 de outubro de 2024 (publicada no Diário Oficial da União em 16/10/2024), que alterou a IN RFB nº 2.119/2022.

PosiçõesParteAntesAgora
1 a 8Raiz (identifica a empresa)só dígitosletras maiúsculas e dígitos
9 a 12Ordem (matriz 0001, filiais)só dígitosletras maiúsculas e dígitos
13 e 14Dígitos verificadoresdígitoscontinuam só dígitos
  • Só inscrições novas recebem o formato. Nenhum CNPJ existente foi trocado, e a emissão alfanumérica é gradual.
  • A máscara continua a mesma: 12.ABC.345/01DE-35.
  • Letras são sempre maiúsculas. Normalize a entrada (12abc... vira 12ABC...) antes de validar e de gravar.

Na carga de dados abertos de setembro de 2026, a primeira com CNPJs emitidos depois da mudança, havia 1 estabelecimento com CNPJ alfanumérico entre 73.366.147. A tendência é crescer a cada mês, porque toda abertura nova passa a poder receber letras.

Como calcular o dígito verificador

O algoritmo é o mesmo módulo 11 de sempre. A única novidade é como cada caractere vira número: valor = código ASCII − 48. Para os dígitos nada muda ('0' = 0 … '9' = 9). As letras vão de A = 17 a Z = 42.

Caractere0–9ABCDE…Z
Valor0–91718192021…42
  1. Primeiro dígito: multiplique os 12 primeiros valores pelos pesos 5 4 3 2 9 8 7 6 5 4 3 2 e some.
  2. Divida a soma por 11. Se o resto for 0 ou 1, o dígito é 0; senão, é 11 − resto.
  3. Segundo dígito: repita com os 13 valores (os 12 mais o primeiro dígito) e os pesos 6 5 4 3 2 9 8 7 6 5 4 3 2.

Exemplo oficial, 12.ABC.345/01DE:

12ABC34501DE
Valor12171819345012021
Peso543298765432
Produto585136171242830046042
  • Soma = 459; 459 ÷ 11 deixa resto 8; primeiro dígito = 11 − 8 = 3.
  • Com o 3 no fim e os pesos de 6 a 2, a soma é 424; resto 6; segundo dígito = 11 − 6 = 5.
  • CNPJ completo: 12.ABC.345/01DE-35.

A mesma conta funciona para os CNPJs antigos, só numéricos: não é preciso manter duas implementações.

Código de validação

Todas as versões abaixo foram executadas com os mesmos casos de teste (numérico válido, alfanumérico válido, com e sem máscara, minúsculas, dígito errado e formato errado) antes de publicar: Node.js 18 e 24, Python 3.12, PHP 8.3 e .NET 8.

const PESOS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];

export function cnpjValido(cnpj) {
  const c = String(cnpj).replace(/[^0-9A-Za-z]/g, '').toUpperCase();
  if (!/^[A-Z0-9]{12}[0-9]{2}$/.test(c)) return false;
  const v = [...c].map((ch) => ch.charCodeAt(0) - 48);
  const dv = (n) => {
    let soma = 0;
    for (let i = 0; i < n; i++) soma += v[i] * PESOS[i + 13 - n];
    const resto = soma % 11;
    return resto < 2 ? 0 : 11 - resto;
  };
  return v[12] === dv(12) && v[13] === dv(13);
}
import re

PESOS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]

def cnpj_valido(cnpj: str) -> bool:
    c = re.sub(r"[^0-9A-Za-z]", "", cnpj).upper()
    if not re.fullmatch(r"[A-Z0-9]{12}[0-9]{2}", c):
        return False
    v = [ord(ch) - 48 for ch in c]

    def dv(n: int) -> int:
        resto = sum(v[i] * PESOS[i + 13 - n] for i in range(n)) % 11
        return 0 if resto < 2 else 11 - resto

    return v[12] == dv(12) and v[13] == dv(13)
function cnpj_valido(string $cnpj): bool
{
    $c = strtoupper(preg_replace('/[^0-9A-Za-z]/', '', $cnpj));
    if (!preg_match('/^[A-Z0-9]{12}[0-9]{2}$/', $c)) {
        return false;
    }
    $pesos = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
    $v = array_map(fn ($ch) => ord($ch) - 48, str_split($c));
    $dv = function (int $n) use ($v, $pesos): int {
        $soma = 0;
        for ($i = 0; $i < $n; $i++) {
            $soma += $v[$i] * $pesos[$i + 13 - $n];
        }
        $resto = $soma % 11;
        return $resto < 2 ? 0 : 11 - $resto;
    };
    return $v[12] === $dv(12) && $v[13] === $dv(13);
}
using System.Text.RegularExpressions;

public static partial class Cnpj
{
    static readonly int[] Pesos = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];

    [GeneratedRegex("[^0-9A-Za-z]")] private static partial Regex NaoAlfanumerico();
    [GeneratedRegex("^[A-Z0-9]{12}[0-9]{2}$")] private static partial Regex Formato();

    public static bool Valido(string cnpj)
    {
        var c = NaoAlfanumerico().Replace(cnpj, "").ToUpperInvariant();
        if (!Formato().IsMatch(c)) return false;
        var v = c.Select(ch => ch - 48).ToArray();
        int Dv(int n)
        {
            var soma = 0;
            for (var i = 0; i < n; i++) soma += v[i] * Pesos[i + 13 - n];
            var resto = soma % 11;
            return resto < 2 ? 0 : 11 - resto;
        }
        return v[12] == Dv(12) && v[13] == Dv(13);
    }
}

O truque do índice PESOS[i + 13 - n] usa uma só lista de pesos para os dois dígitos: com n = 12 começa no segundo peso (5) e com n = 13 no primeiro (6).

Checklist de adequação

  • Banco de dados. Coluna de CNPJ como texto de 14 posições (CHAR(14) ou VARCHAR(14)), nunca INT ou BIGINT. Migre os dados existentes com zeros à esquerda (00000000000191, não 191).
  • Formulários. Aceite letras no campo, converta para maiúsculas e mantenha a máscara 00.000.000/0000-00 com posições alfanuméricas. Teclado numérico no celular deixa de servir.
  • Validação. Troque expressões como ^\d{14}$ por ^[A-Z0-9]{12}\d{2}$ e use o cálculo acima.
  • Comparação e ordenação. Compare como texto. Ordenação numérica e conversões para número quebram.
  • Planilhas. Excel interpreta coluna numérica e come zeros à esquerda; importe a coluna como texto.
  • Integrações. Confira com cada parceiro (bancos, emissores de nota, ERPs) se o campo de CNPJ já aceita letras. Documentos fiscais eletrônicos tiveram notas técnicas próprias de adequação.
  • Testes. Inclua o exemplo oficial 12.ABC.345/01DE-35 na sua suíte, junto de um CNPJ numérico real e de um com dígito errado.

Como a apipj trata o CNPJ alfanumérico

  • GET /v1/valida/{cnpj} valida formato e dígitos, numérico ou alfanumérico. É aberto, não exige conta e não consome cota:
curl -s https://apipj.com.br/v1/valida/12.ABC.345%2F01DE-35
{"cnpj":"12ABC34501DE35","valido":true,"formatado":"12.ABC.345/01DE-35","alfanumerico":true,"erro":null}
  • GET /v1/cnpj/{cnpj} aceita os dois formatos, com ou sem máscara e em minúsculas, e devolve os dados cadastrais quando o CNPJ está na carga do mês. Veja a API de CNPJ e a documentação.

Perguntas frequentes

Meu CNPJ vai mudar?

Não. CNPJs já emitidos continuam iguais. Só inscrições novas podem receber letras.

Os dígitos verificadores podem ter letras?

Não. As posições 13 e 14 continuam só numéricas, calculadas pelo módulo 11 descrito acima.

Preciso de uma função para o CNPJ antigo e outra para o novo?

Não. Com valor = código ASCII − 48, os dígitos continuam valendo 0 a 9, então a mesma função valida os dois.

Um dígito verificador válido prova que a empresa existe?

Não. Prova só que o número está bem formado. Para saber se a inscrição existe e está ativa, consulte os dados cadastrais.