2

CNPJ alfanumérico chega em julho — sua validação já está preparada?

CNPJ alfanumérico chega em julho — sua validação já está preparada?

A Receita Federal mudou o formato do CNPJ. A partir de julho de 2026, os novos CNPJs vão começar a sair com letras (alfanumérico). O algoritmo dos dígitos verificadores também mudou.

Se seu sistema valida, armazena ou exibe CNPJ, isso vai te afetar mais cedo ou mais tarde.


O que mudou de verdade

O formato antigo continua valendo:

11.222.333/0001-81

Mas os novos podem vir assim:

12.ABC.345/01DE-35

Mesma máscara, mas agora as 12 primeiras posições aceitam letras. E o cálculo dos dígitos verificadores mudou: em vez de só número, agora considera o valor ASCII do caractere (menos 48).

Tem um vetor oficial da própria Receita que vira o santo graal pra testar:

Input: 12ABC34501DE → DV1: 3, DV2: 5 → 12.ABC.345/01DE-35


O problema com as libs atuais

Testei várias libs populares de CNPJ no npm antes de começar a minha. Quase todas quebram com letra:

  • Usam parseInt, Number() ou convertem pra número
  • Regex que só aceita [0-9]
  • Armazenam como number no banco (o que já era ruim e agora vai ser pior)

Resumo: a grande maioria ainda não está preparada pro novo formato.


Como validar corretamente (algoritmo oficial)

Aqui vai a implementação baseada na documentação da Receita/SERPRO:

function calcDv(cnpjBase: string): [number, number] {
  const toValue = (c: string) =>
    /\d/.test(c) ? parseInt(c, 10) : c.charCodeAt(0) - 48

  const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
  const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]

  const chars = cnpjBase.split('')

  const sum1 = chars.reduce((acc, c, i) => acc + toValue(c) * weights1[i], 0)
  const dv1 = sum1 % 11 < 2 ? 0 : 11 - (sum1 % 11)

  const sum2 = [...chars, String(dv1)].reduce(
    (acc, c, i) => acc + toValue(c) * weights2[i], 0
  )
  const dv2 = sum2 % 11 < 2 ? 0 : 11 - (sum2 % 11)

  return [dv1, dv2]
}

Testa com o vetor oficial pra ver se tá certo:

  • 12ABC34501DE35 → deve validar
  • 11.222.333/0001-81 → deve continuar validando

Dica de ouro: se você ainda guarda CNPJ como INT, BIGINT ou CHAR(14) no banco, migra pra VARCHAR(14) o quanto antes.


O que eu fiz

Criei a @br-validators/core exatamente pra resolver isso de forma definitiva.

É uma lib TypeScript open source (MIT), zero dependência, tree-shakeable e que já nasceu com suporte completo ao CNPJ alfanumérico.

npm install @br-validators/core

Uso bem simples:

import { validateCnpj, formatCnpj } from '@br-validators/core/cnpj'

validateCnpj('11.222.333/0001-81')
// { ok: true, value: '11222333000181', format: 'numeric' }

validateCnpj('12ABC34501DE35')
// { ok: true, value: '12ABC34501DE35', format: 'alphanumeric' }

formatCnpj('12ABC34501DE35')
// { ok: true, formatted: '12.ABC.345/01DE-35' }

Ela nunca joga exceção. Sempre retorna { ok: true/false, ... }.

Além do CNPJ, a lib já tem validação/formatação pra 18 documentos brasileiros (CPF, CEP, Placa Mercosul, RENAVAM, Inscrição Estadual, etc) + adapters pro Zod e React Hook Form.


O que você deveria fazer agora (mesmo que não use a lib)

  1. Auditar colunas de CNPJ no banco (migra pra VARCHAR)
  2. Testar seu validador atual com 12ABC34501DE35
  3. Revisar APIs que recebem CNPJ de terceiros

Se quiser contribuir, testar ou só dar feedback, o repo tá aberto:

GitHub: github.com/AlexandreZanata/br-validators

Qualquer sugestão de melhoria na lib é bem-vinda. Sou dev solo do interior do Mato Grosso '-'

Carregando publicação patrocinada...
1

A validação ficou muito boa.

Um detalhe que percebi, é que na função toValue não precisa fazer o teste pra retornar parseInt se for número. Pode sempre fazer a conta do c.charCodeAt(0) - 48, pois os números ficarão com o valor correto. Do ponto de vista performance não sei se influencia em algo.

E vale lembrar que as letras precisam estar em maiúscula, pois o ASCII das minúsculas dariam conta errada. Mas aí, se a pessoa tentou validar com minúscula, tem que dar erro mesmo.

1

Vlw , quaquer coisa abre uma issue la, eu fiz pensando mais em usar apenas para min nos meus projetos pessoais, mas acabei ficando empolgado, to pensando em ampliar bastante