Documentos brasileiros10 min de leitura

CNPJ alfanumérico: o que muda no banco, no validador e na interface

O CNPJ passa a aceitar letras nas oito primeiras posições. Veja o que quebra em validações, colunas numéricas, máscaras e integrações — e como calcular o dígito verificador no novo formato.

Publicado em

AL

Por André Leitão

Desenvolvedor de software

Depois de décadas em que CNPJ era, para efeitos práticos, um inteiro de quatorze dígitos, o documento passou a admitir letras. A mudança parece cosmética e não é: ela invalida uma suposição que está espalhada por colunas de banco, expressões regulares, máscaras de formulário, contratos de API e rotinas de importação de praticamente todo sistema brasileiro.

Este artigo mapeia o que efetivamente quebra, mostra o cálculo do dígito verificador no novo formato e propõe uma ordem de migração que não exige parar o sistema.

O que mudou na estrutura

O CNPJ continua com quatorze caracteres, distribuídos da mesma forma. O que muda é o conjunto de caracteres permitido em cada faixa.

Composição do CNPJ no formato alfanumérico
PosiçõesParteCaracteres permitidos
1 a 8Raiz — identifica a empresaLetras de A a Z e dígitos de 0 a 9
9 a 12Ordem — identifica o estabelecimentoLetras de A a Z e dígitos de 0 a 9
13 e 14Dígitos verificadoresApenas dígitos de 0 a 9

A máscara visual não muda: continua sendo 00.000.000/0000-00, agora com a possibilidade de letras nas posições que antes só aceitavam números. Um exemplo estruturalmente válido no novo formato é 12.ABC.345/01DE-35.

O cálculo do dígito verificador

O módulo 11 continua sendo a base. A única adaptação é converter cada caractere em um valor numérico antes de aplicar os pesos, usando o código ASCII do caractere menos 48.

A escolha do 48 não é arbitrária: é o código ASCII do caractere zero. Assim, o dígito 0 vale 0, o dígito 9 vale 9, e a compatibilidade com os CNPJs numéricos antigos é preservada byte a byte. As letras, que começam em 65 na tabela ASCII, passam a valer de 17 (A) a 42 (Z).

Conversão de caracteres para valor numérico
CaractereCódigo ASCIIValor no cálculo
0480
9579
A6517
B6618
Z9042

A partir daí, tudo é como antes: os doze primeiros valores são multiplicados pelos pesos que ciclam de 2 a 9 da direita para a esquerda, somados, e o dígito é 0 quando o resto da divisão por 11 for menor que 2, ou 11 menos o resto caso contrário. O segundo dígito repete o processo incluindo o primeiro.

Validação de CNPJ compatível com numérico e alfanumérico
const PESOS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];

function valorDoCaractere(caractere) {
  return caractere.charCodeAt(0) - 48;
}

function calcularDigito(caracteres) {
  const pesos = PESOS.slice(PESOS.length - caracteres.length);
  const soma = caracteres.reduce(
    (acc, caractere, indice) => acc + valorDoCaractere(caractere) * pesos[indice],
    0
  );
  const resto = soma % 11;
  return resto < 2 ? 0 : 11 - resto;
}

export function validarCnpj(entrada) {
  // Remove pontuação e normaliza: a Receita trabalha com maiúsculas.
  const limpo = String(entrada).toUpperCase().replace(/[^A-Z0-9]/g, "");

  if (limpo.length !== 14) return false;
  if (/^(.)\1{13}$/.test(limpo)) return false;
  // Os dois últimos caracteres continuam sendo obrigatoriamente numéricos.
  if (!/^[A-Z0-9]{12}\d{2}$/.test(limpo)) return false;

  const caracteres = limpo.split("");
  const base = caracteres.slice(0, 12);

  const primeiro = calcularDigito(base);
  if (primeiro !== Number(caracteres[12])) return false;

  const segundo = calcularDigito([...base, String(primeiro)]);
  return segundo === Number(caracteres[13]);
}

O que quebra na sua aplicação

Vale mapear os pontos de falha por camada, porque eles raramente estão todos no mesmo módulo.

Banco de dados

  • Colunas BIGINT, NUMERIC ou INTEGER guardando CNPJ não comportam letras e falham na inserção.
  • Índices e chaves estrangeiras construídos sobre essas colunas precisam ser recriados após a mudança de tipo.
  • Constraints com CHECK numérico ou regex de dígitos rejeitam o novo formato silenciosamente até alguém tentar gravar.
  • Views materializadas e colunas calculadas que fazem cast para número quebram na primeira letra.

Validação e regras

  • Expressões regulares do tipo ^\\d{14}$ rejeitam qualquer CNPJ com letra.
  • Funções que fazem parseInt ou Number sobre o documento produzem NaN ou truncamento.
  • Bibliotecas de validação desatualizadas continuam aplicando a regra antiga; verifique a versão antes de confiar.

Interface

  • Campos com inputmode numérico abrem teclado sem letras no celular.
  • Máscaras que filtram tudo que não for dígito apagam as letras conforme o usuário digita.
  • Ordenação de listas por CNPJ tratado como número passa a ordenar errado.

Integrações

  • Contratos de API que declaram o campo como integer no OpenAPI precisam virar string com padrão explícito.
  • Layouts de arquivo posicional geralmente já reservam quatorze posições de texto e sofrem menos, mas rotinas de parse que fazem cast numérico quebram.
  • Parceiros que ainda não migraram podem rejeitar os documentos que você enviar — vale combinar a janela de corte antes.

Uma ordem de migração que funciona

A sequência importa. Trocar o tipo da coluna antes de o validador aceitar letras cria uma janela em que o banco aceita o que a aplicação recusa; fazer o contrário cria uma janela em que a aplicação aceita o que o banco recusa, o que é pior porque a falha aparece só na gravação.

  1. 1Inventarie onde o CNPJ aparece: colunas, DTOs, regex, máscaras, contratos e relatórios. Um grep por 'cnpj' costuma revelar mais lugares do que o esperado.
  2. 2Atualize o validador para aceitar os dois formatos, mantendo a rejeição de sequências repetidas e a exigência de dois dígitos numéricos no fim.
  3. 3Cubra o novo formato com testes antes de mexer no banco, incluindo caixa baixa, pontuação e caracteres inválidos.
  4. 4Migre o tipo da coluna para CHAR(14) ou VARCHAR(14), normalizando os valores existentes para dígitos sem pontuação.
  5. 5Afrouxe as máscaras e o inputmode na interface, normalizando para maiúsculas na saída do campo.
  6. 6Atualize os contratos de API e avise os parceiros que consomem o campo.
  7. 7Só então habilite a entrada de documentos alfanuméricos em produção.

Como testar sem depender de documentos reais

Para exercitar todos esses caminhos você precisa de massa nos dois formatos, e usar CNPJs de empresas reais em ambiente de homologação é uma exposição desnecessária. Documentos sintéticos resolvem: eles fecham no módulo 11 e passam por qualquer validação sintática, sem corresponder a uma inscrição existente.

O gerador de CNPJ do Codigio Labs produz os dois formatos, e o validador mostra o resultado da checagem caractere a caractere — útil para conferir sua própria implementação contra um caso conhecido. Ambos rodam no navegador, sem enviar o documento a nenhum servidor.

Resumo

  • Letras podem aparecer nas doze primeiras posições; os dois dígitos verificadores continuam numéricos.
  • A conversão de caractere para valor é o código ASCII menos 48, o que preserva a compatibilidade com o formato numérico.
  • Normalize sempre para maiúsculas antes de calcular, ou o resultado sai errado.
  • Colunas numéricas, regex de dígitos e máscaras restritivas são os três pontos que quebram primeiro.
  • Migre o validador antes do banco, e o banco antes da interface.

Perguntas frequentes

Os CNPJs numéricos existentes deixam de valer?
Não. Os CNPJs já emitidos continuam válidos e com o mesmo número. O formato alfanumérico convive com o numérico, e sua aplicação precisa aceitar os dois indefinidamente. Qualquer migração que reescreva documentos existentes é desnecessária e arriscada.
Onde exatamente podem aparecer letras?
Nas doze primeiras posições — as oito da raiz e as quatro da ordem do estabelecimento. Os dois dígitos verificadores permanecem sempre numéricos, o que mantém o resultado do cálculo compatível com o que os sistemas já esperam nessa posição.
Preciso mudar o tipo da coluna no banco?
Sim, se a coluna for numérica. Uma coluna BIGINT ou NUMERIC não comporta letras. O destino natural é CHAR(14) ou VARCHAR(14) guardando apenas os caracteres sem pontuação, com índice sobre a forma normalizada em maiúsculas.
O cálculo do dígito verificador mudou?
A estrutura do módulo 11 é a mesma. O que muda é a conversão prévia: cada caractere passa a valer o código ASCII menos 48, o que faz os dígitos continuarem valendo 0 a 9 e as letras de A a Z valerem 17 a 42. Os pesos e a soma ponderada permanecem idênticos.
Máscaras de entrada precisam ser reescritas?
Precisam ser afrouxadas. Uma máscara que aceita apenas dígitos nas primeiras posições bloqueia o novo formato. O padrão seguro é aceitar letras e números nas doze primeiras posições e apenas números nas duas últimas, normalizando para maiúsculas na saída.

Ferramentas relacionadas

AL

Sobre o autor

Desenvolvedor de software no Brasil. Mantém o Codigio Labs desde a primeira ferramenta, escreve os artigos do site e revisa os textos quando a informação técnica muda.

Encontrou um erro ou tem uma correção a sugerir? Fale com o Codigio Labs. Correções relevantes são aplicadas com atualização da data de revisão do texto.

Continue lendo