Documentos brasileiros

CNPJ alfanumérico

O CNPJ agora aceita letras nas 12 primeiras posições. Cálculo do dígito verificador (módulo 11, ASCII − 48), tabela dos 36 caracteres, regex e validador online.

O CNPJ passou a aceitar letras nas 12 primeiras posições. Os dois dígitos verificadores continuam numéricos, o tamanho continua 14 e a máscara continua 00.000.000/0000-00. O cálculo do DV é o mesmo módulo 11 de sempre — a única diferença é que o valor de cada caractere passa a ser o código ASCII menos 48.

NotaBase normativa: IN RFB nº 2.229/2024 e Nota Técnica Conjunta 2025.001. Estrutura alfanumérica a partir de julho de 2026. Como cronograma é a parte que mais muda, confirme as datas vigentes no portal da Receita Federal antes de planejar sua migração.

O que mudou, exatamente

AntesAgora
Tamanho14 posições14 posições — igual
Máscara00.000.000/0000-0000.000.000/0000-00 — igual
Posições 1 a 12Apenas 0-90-9 e A-Z
Posições 13 e 14 (DV)Apenas 0-9Apenas 0-9 — igual
Cálculo do DVMódulo 11, pesos 5..2 e 6..2Módulo 11, mesmos pesos
Valor do caractereO próprio dígitoASCII − 48
CNPJs já emitidosContinuam válidos, sem reemissão

A lista de "igual" é maior que a de "mudou", e isso é o ponto mais importante do planejamento: não é uma reescrita, é a remoção de uma premissa. A premissa de que cada posição do CNPJ é um dígito está espalhada pelo seu sistema em tipos de coluna, regex, máscaras de input, parseInt, comparações e contratos de API — e é isso que precisa ser encontrado.

O algoritmo do dígito verificador

  1. Normalize: maiúsculas, sem máscara. Sobram 14 caracteres.
  2. Converta cada um dos 12 primeiros em número: valor = código ASCII − 48.
  3. Multiplique pelos pesos do 1º DV: 5 4 3 2 9 8 7 6 5 4 3 2. Some.
  4. Divida por 11. Se o resto for menor que 2, o DV é 0; senão é 11 − resto.
  5. Repita com as 13 posições (as 12 + o 1º DV) e os pesos do 2º DV: 6 5 4 3 2 9 8 7 6 5 4 3 2.
AtençãoRepare no passo 2: como o ASCII de 0 é 48, os dígitos valem exatamente eles mesmos. É por isso que a rotina nova produz o mesmo DV de sempre para CNPJ numérico — você troca a função por uma só, não mantém duas.

Tabela de conversão: caractere → valor

Valor de cada caractere no cálculo do módulo 11. Os dígitos mantêm o próprio valor; as letras começam em 17.
CaractereASCIIValor
0480
1491
2502
3513
4524
5535
6546
7557
8568
9579
A6517
B6618
C6719
D6820
E6921
F7022
G7123
H7224
I7325
J7426
K7527
L7628
M7729
N7830
O7931
P8032
Q8133
R8234
S8335
T8436
U8537
V8638
W8739
X8840
Y8941
Z9042

Exemplo completo

Base AB12CD34EFGH, calculando o 1º DV. Os valores saem da tabela acima:

CaractereAB12CD34EFGH
Valor17181219203421222324
Peso543298765432
Produto8572341711602124105886948

Soma = 850. 850 ÷ 11 deixa resto 3. Como 3 ≥ 2, o 1º DV é 11 − 3 = 8. Repetindo com 13 posições (AB12CD34EFGH8) e os pesos do 2º DV, chega-se a 3. Resultado: AB.12C.D34/EFGH-83.

Implementação

Uma função só, que atende numérico e alfanumérico. Esta é exatamente a rotina que roda no validador desta página:

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

const valor = (ch) => ch.charCodeAt(0) - 48;   // '0'->0 ... '9'->9, 'A'->17 ... 'Z'->42

function dv(base, pesos) {
  const soma = pesos.reduce((s, p, i) => s + valor(base[i]) * p, 0);
  const resto = soma % 11;
  return resto < 2 ? 0 : 11 - resto;
}

export function validarCNPJ(entrada) {
  const s = String(entrada).toUpperCase().replace(/[^0-9A-Z]/g, '');

  // 12 alfanuméricos + 2 dígitos verificadores NUMÉRICOS
  if (!/^[0-9A-Z]{12}[0-9]{2}$/.test(s)) return false;
  if (/^(.)\1{13}$/.test(s)) return false;      // caractere repetido nunca é válido

  const d1 = dv(s, PESOS_DV1);
  const d2 = dv(s.slice(0, 12) + d1, PESOS_DV2);
  return s.slice(12) === `${d1}${d2}`;
}

validarCNPJ('AB.12C.D34/EFGH-83');   // true
validarCNPJ('00.000.000/0001-91');   // true — numérico continua funcionando
NotaComo testar a sua implementação sem depender de nenhum artigo: rode-a contra CNPJs numéricos reais e conhecidos. Se os DVs fecham, seus pesos e sua regra de módulo 11 estão certos, porque foram a Receita que os calculou. Foi assim que validamos a rotina acima — 8 CNPJs reais, mais o vetor alfanumérico do exemplo.

Expressão regular

# Sem máscara, 14 posições
^[0-9A-Z]{12}[0-9]{2}$

# Com máscara opcional
^([0-9A-Z]{2})\.?([0-9A-Z]{3})\.?([0-9A-Z]{3})\/?([0-9A-Z]{4})-?([0-9]{2})$

# O que você provavelmente tem hoje, e que passa a rejeitar CNPJ válido:
^\d{14}$
^[0-9]{2}\.[0-9]{3}\.[0-9]{3}\/[0-9]{4}-[0-9]{2}$

Regex valida formato, nunca dígito verificador. AB12CD34EFGH99 passa em qualquer regex acima e é um CNPJ inválido. Use a regex no input e o cálculo do DV na regra de negócio — os dois, não um.

Checklist de migração

Em ordem de risco. Os três primeiros são os que quebram em produção no dia em que o primeiro CNPJ com letra chega:

OndeO que procurarPara onde ir
Banco de dadosColuna de CNPJ em INT, BIGINT, NUMBER, DECIMALCHAR(14), sem máscara, em maiúsculas
ConversõesparseInt, Number(), CAST, to_number, Integer.parseInt sobre CNPJRemover: CNPJ é identificador, não número
Validação^\\d{14}$, \\d{2}\\.\\d{3}\\.\\d{3}, isDigit, IsNumericAceitar [0-9A-Z] nas 12 primeiras
Máscara de inputComponente que só aceita tecla numéricaAceitar letra e forçar maiúscula
Ordenação e índiceOrdenação numérica de CNPJOrdenação de texto (muda o resultado — combine com o negócio)
Comparaçãocnpj1 == cnpj2 com um lado mascaradoNormalizar antes de comparar, sempre
Contratos de APICampo de CNPJ tipado como integer em OpenAPI/JSON Schemastring com pattern
IntegraçõesLayout posicional, EDI, arquivo de remessaConferir se o campo aceita alfanumérico
Relatórios e exportsCSV/Excel convertendo CNPJ em número e comendo zero à esquerdaForçar texto na exportação
Massa de testeFixtures só com CNPJ numéricoIncluir CNPJ com letra nos testes

Quatro armadilhas

1. Guardar CNPJ em coluna numérica

É a falha mais comum e a mais silenciosa: o sistema funciona perfeitamente até o primeiro cadastro com letra, e aí o erro aparece no ponto mais distante da causa. Vale conferir hoje, não quando acontecer:

-- PostgreSQL: colunas cujo nome sugere CNPJ e cujo tipo é numérico
SELECT table_schema, table_name, column_name, data_type
FROM information_schema.columns
WHERE column_name ILIKE '%cnpj%'
  AND data_type IN ('integer','bigint','numeric','double precision','real','smallint');

-- MySQL / MariaDB
SELECT table_schema, table_name, column_name, column_type
FROM information_schema.columns
WHERE column_name LIKE '%cnpj%'
  AND data_type IN ('int','bigint','decimal','double','float','smallint');

2. Achar que precisa de duas rotinas de validação

Por causa do ASCII − 48, a rotina alfanumérica devolve o mesmo DV que a antiga para qualquer CNPJ numérico. Manter validarCnpjAntigo e validarCnpjNovo em paralelo cria duas fontes de verdade que vão divergir. Substitua por uma.

3. Esquecer a normalização de caixa

O DV é calculado sobre o código ASCII, então a (97) e A (65) dão valores diferentes e o DV não fecha. Um CNPJ digitado em minúsculas é válido para o usuário e inválido para o seu código, se você não normalizar. Faça toUpperCase() na entrada e grave em maiúsculas, para não acabar com o mesmo CNPJ em duas grafias na base.

4. Aceitar letra no dígito verificador

Uma regex frouxa como ^[0-9A-Z]{14}$ aceita AB12CD34EFGHIJ, que não é CNPJ: as duas últimas posições são sempre numéricas. Separe as duas partes no padrão — [0-9A-Z]{12}[0-9]{2} — e você rejeita isso no formato, sem nem chegar ao DV.

Gerar CNPJ alfanumérico para teste

Você vai precisar de massa de teste com letra antes de o primeiro caso real chegar. Sorteie as 12 posições e calcule o DV — nunca invente o DV, senão seus testes passam a validar o bug:

const ALFABETO = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

function gerarCNPJ({ comLetras = true } = {}) {
  const fonte = comLetras ? ALFABETO : '0123456789';
  let base = '';
  for (let i = 0; i < 12; i++) {
    base += fonte[Math.floor(Math.random() * fonte.length)];
  }
  const d1 = dv(base, PESOS_DV1);
  const d2 = dv(base + d1, PESOS_DV2);
  return base + d1 + d2;
}

O validador no topo desta página mostra o cálculo passo a passo, posição por posição — útil para conferir a sua implementação contra a nossa quando o DV não fecha e você não sabe onde.

Perguntas frequentes

Os CNPJs numéricos que já existem vão parar de funcionar?

Não. Os CNPJs já emitidos continuam válidos, não são reemitidos e não mudam. O formato alfanumérico vale para novas inscrições. O que muda no seu sistema é a capacidade de ACEITAR letras — não a de continuar aceitando os números que já estão na base.

O dígito verificador pode ser letra?

Não. As 12 primeiras posições aceitam 0-9 e A-Z; os 2 dígitos verificadores são sempre numéricos. Um "CNPJ" terminando em letra é inválido por definição de formato, antes mesmo de calcular o DV.

Por que o algoritmo é retrocompatível?

Porque o valor de cada caractere é o código ASCII menos 48. Para os dígitos, ASCII de "0" é 48, então "0" vale 0, "9" vale 9 — exatamente os mesmos valores do algoritmo antigo. Os pesos e a regra do módulo 11 não mudaram. Rodar a rotina nova num CNPJ numérico dá o mesmo resultado da rotina antiga, o que significa que você pode substituir a função sem manter duas.

A máscara e o tamanho mudam?

Não. Continuam 14 posições e a máscara 00.000.000/0000-00. O que deixa de valer é a premissa de que cada posição é um dígito: AB.123.CD4/EFGH-83 é um CNPJ bem formado.

Preciso trocar o tipo da coluna no banco de dados?

Sim, se a coluna for numérica. CNPJ guardado em INT, BIGINT, NUMBER ou DECIMAL para de funcionar no dia em que chegar o primeiro com letra. O destino correto é CHAR(14) (ou VARCHAR(14)) guardando apenas os 14 caracteres sem máscara, em maiúsculas. Guardar com máscara desperdiça 4 bytes por linha e cria duas representações do mesmo dado.

Letra minúscula é válida?

A representação oficial é em maiúsculas. Como o cálculo do DV usa o código ASCII, minúscula produz outro valor ("a" é 97, não 65) e o DV não fecharia. Normalize a entrada para maiúsculas antes de validar, e guarde em maiúsculas.

O CPF também vai ter letras?

Não. A mudança anunciada é do CNPJ. O CPF continua com 11 dígitos numéricos e o mesmo cálculo de DV.

Ferramentas relacionadas