CNPJ alfanumérico: validar o dígito verificador e consultar pela API
Desde 31/07/2026, a Receita Federal emite CNPJs com letras e números. O primeiro foi uma filial do Banco do Brasil, 00.000.000/E08G-12. A emissão no formato novo é gradual ao longo de 2026: CNPJs novos ainda podem sair só com números, e os CNPJs que já existem continuam válidos, sem troca. Fontes: notícia da Receita Federal e Perguntas e Respostas sobre o CNPJ alfanumérico.
Para quem integra, o que muda é a validação: um sistema que trata CNPJ como número, ou que aceita só dígitos no campo, passa a recusar empresas reais. Este guia mostra o formato, a expressão regular, o cálculo do dígito verificador com código pronto, o cuidado com o banco de dados e a consulta pela API da CNPJAPI, que já aceita o formato novo.
O que muda no formato
O CNPJ continua com 14 caracteres e com a mesma máscara. A diferença é que as 12 primeiras posições podem ter letras maiúsculas, de A a Z:
| Posições | O que é | Pode ter letra? |
|---|---|---|
| 1 a 8 | Raiz (identifica a empresa) | Sim |
| 9 a 12 | Ordem (matriz ou filial) | Sim |
| 13 e 14 | Dígitos verificadores | Não, sempre números |
Com máscara, o exemplo 12ABC34501DE35 fica 12.ABC.345/01DE-35.
Expressão regular
Para conferir só o formato, antes do cálculo do dígito:
- Sem máscara:
^[A-Z0-9]{12}[0-9]{2}$ - Com máscara:
^[A-Z0-9]{2}\.[A-Z0-9]{3}\.[A-Z0-9]{3}\/[A-Z0-9]{4}-[0-9]{2}$
As duas aceitam só maiúsculas: converta a entrada antes ou troque [A-Z0-9] por [A-Za-z0-9]. E a expressão regular sozinha não basta, porque aceita qualquer combinação de 14 caracteres no formato certo. Confira sempre o dígito verificador.
Como calcular o dígito verificador
O cálculo é o mesmo módulo 11 de sempre. A única mudança é o valor de cada caractere: ele vale o código ASCII menos 48. Para os números, isso dá o próprio número (0 vale 0, 9 vale 9). Para as letras, A vale 17, B vale 18, e assim por diante até Z, que vale 42. Por isso um CNPJ só de números tem o mesmo dígito de antes.
- Multiplique cada um dos 12 primeiros caracteres por um peso. Os pesos vão de 2 a 9, da direita para a esquerda, e recomeçam em 2 depois do 9. Da esquerda para a direita, ficam 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2.
- Some os resultados e calcule o resto da divisão por 11.
- Se o resto for 0 ou 1, o dígito é 0. Senão, o dígito é 11 menos o resto.
- Para o segundo dígito, repita com os 13 primeiros caracteres (os 12 mais o primeiro dígito), com os pesos 6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2.
No exemplo 12ABC34501DE, a soma dá 459, o resto é 8 e o primeiro dígito é 3. Com 12ABC34501DE3, a soma dá 424, o resto é 6 e o segundo dígito é 5: 12ABC34501DE35.
Todas as versões abaixo aceitam o CNPJ com ou sem máscara e em minúsculas, recusam caracteres fora de A a Z e 0 a 9 (inclusive letras acentuadas e outros caracteres Unicode), recusam sequências repetidas (como 00000000000000) e conferem os dois dígitos.
Python
import re
def calcular_dv(base: str) -> str:
soma, peso = 0, 2
for c in reversed(base):
soma += (ord(c) - 48) * peso
peso = 2 if peso == 9 else peso + 1
resto = soma % 11
return "0" if resto < 2 else str(11 - resto)
def cnpj_valido(entrada: str) -> bool:
cnpj = re.sub(r"[.\-/\s]", "", entrada, flags=re.ASCII)
if not re.fullmatch(r"[A-Za-z0-9]{12}[0-9]{2}", cnpj):
return False
cnpj = cnpj.upper()
if len(set(cnpj)) == 1:
return False
return calcular_dv(cnpj[:12]) == cnpj[12] and calcular_dv(cnpj[:13]) == cnpj[13]
print(cnpj_valido("12.ABC.345/01DE-35")) # True
Para gerar um CNPJ de teste, sorteie 12 caracteres de A a Z e 0 a 9 e acrescente os dois dígitos: base + calcular_dv(base) dá os 13 primeiros, e o calcular_dv desses 13 dá o último.
JavaScript (Node.js e navegador)
function calcularDv(base) {
let soma = 0;
let peso = 2;
for (let i = base.length - 1; i >= 0; i--) {
soma += (base.charCodeAt(i) - 48) * peso;
peso = peso === 9 ? 2 : peso + 1;
}
const resto = soma % 11;
return resto < 2 ? "0" : String(11 - resto);
}
function cnpjValido(entrada) {
let cnpj = entrada.replace(/[.\-/ \t\r\n]/g, "");
if (!/^[A-Za-z0-9]{12}[0-9]{2}$/.test(cnpj)) return false;
cnpj = cnpj.toUpperCase();
if (new Set(cnpj).size === 1) return false;
return calcularDv(cnpj.slice(0, 12)) === cnpj[12] && calcularDv(cnpj.slice(0, 13)) === cnpj[13];
}
PHP
function calcularDv(string $base): string
{
$soma = 0;
$peso = 2;
for ($i = strlen($base) - 1; $i >= 0; $i--) {
$soma += (ord($base[$i]) - 48) * $peso;
$peso = $peso === 9 ? 2 : $peso + 1;
}
$resto = $soma % 11;
return $resto < 2 ? '0' : (string) (11 - $resto);
}
function cnpjValido(string $entrada): bool
{
$cnpj = preg_replace('/[.\-\/\s]/', '', $entrada);
if (!preg_match('/^[A-Za-z0-9]{12}[0-9]{2}$/', $cnpj)) {
return false;
}
$cnpj = strtoupper($cnpj);
if (count(array_unique(str_split($cnpj))) === 1) {
return false;
}
return calcularDv(substr($cnpj, 0, 12)) === $cnpj[12] && calcularDv(substr($cnpj, 0, 13)) === $cnpj[13];
}
C# / .NET
using System.Linq;
using System.Text.RegularExpressions;
public static class Cnpj
{
public static char CalcularDv(string baseCnpj)
{
int soma = 0, peso = 2;
for (var i = baseCnpj.Length - 1; i >= 0; i--)
{
soma += (baseCnpj[i] - 48) * peso;
peso = peso == 9 ? 2 : peso + 1;
}
var resto = soma % 11;
return resto < 2 ? '0' : (char)('0' + (11 - resto));
}
public static bool Valido(string entrada)
{
var cnpj = Regex.Replace(entrada, @"[.\-/ \t\r\n]", "");
if (!Regex.IsMatch(cnpj, @"^[A-Za-z0-9]{12}[0-9]{2}\z"))
return false;
cnpj = cnpj.ToUpperInvariant();
if (cnpj.Distinct().Count() == 1)
return false;
return CalcularDv(cnpj[..12]) == cnpj[12] && CalcularDv(cnpj[..13]) == cnpj[13];
}
}
Go
package cnpj
import (
"regexp"
"strconv"
"strings"
)
var (
separadores = regexp.MustCompile(`[.\-/\s]`)
formato = regexp.MustCompile(`^[A-Za-z0-9]{12}[0-9]{2}$`)
)
func calcularDV(base string) byte {
soma, peso := 0, 2
for i := len(base) - 1; i >= 0; i-- {
soma += int(base[i]-48) * peso
if peso == 9 {
peso = 2
} else {
peso++
}
}
resto := soma % 11
if resto < 2 {
return '0'
}
return strconv.Itoa(11 - resto)[0]
}
func Valido(entrada string) bool {
cnpj := separadores.ReplaceAllString(entrada, "")
if !formato.MatchString(cnpj) {
return false
}
cnpj = strings.ToUpper(cnpj)
if strings.Count(cnpj, cnpj[:1]) == len(cnpj) {
return false
}
return calcularDV(cnpj[:12]) == cnpj[12] && calcularDV(cnpj[:13]) == cnpj[13]
}
Banco de dados e telas
- Coluna de texto: guarde o CNPJ como
CHAR(14)ouVARCHAR(14), sem máscara. Colunas numéricas (BIGINT,NUMERIC) não comportam letras e já perdiam os zeros à esquerda. Para migrar uma coluna numérica:
-- PostgreSQL: de BIGINT para texto, repondo os zeros à esquerda
ALTER TABLE empresa ALTER COLUMN cnpj TYPE CHAR(14) USING LPAD(cnpj::text, 14, '0');
-- MySQL
ALTER TABLE empresa MODIFY cnpj CHAR(14);
UPDATE empresa SET cnpj = LPAD(cnpj, 14, '0');
- Com máscara: se o sistema grava o CNPJ formatado, a coluna precisa de 18 caracteres.
- Sem conversão para número: procure no código pontos que fazem
int(cnpj),parseInt,Convert.ToInt64ou comparam CNPJ como número. Todos quebram com letra. - Maiúsculas: normalize para maiúsculas antes de gravar e de comparar, para que
12abc34501de35e12ABC34501DE35sejam o mesmo cadastro. Mesmo que o banco compare sem diferenciar maiúsculas e minúsculas, a comparação dentro do sistema e as integrações não fazem isso. - Campos de tela: troque máscaras e teclados só numéricos (como
inputmode="numeric") por campos que aceitem letras.
Consultar o CNPJ alfanumérico pela API
A consulta é a mesma de qualquer CNPJ: GET /{cnpj}, com os 14 caracteres sem máscara. A API aceita maiúsculas e minúsculas e confere o dígito verificador do CNPJ alfanumérico: com o dígito errado, a resposta é 422 (CNPJ inválido). Para CNPJ só de números, nada muda. O mesmo vale para a consulta em lote, onde o CNPJ com o dígito errado volta como item invalido.
Para testar sem criar conta, use a chave pública de testes com o exemplo fictício 12ABC34501DE35 (veja Autenticação). A chave de testes responde só aos CNPJs de exemplo:
curl "https://api.cnpjapi.com.br/12ABC34501DE35" \
-H "Authorization: Bearer cnpj_teste_exemplos"
{
"CNPJ": "12.ABC.345/01DE-35",
"RazaoSocial": "EMPRESA EXEMPLO COM REGISTROS LTDA",
"MatrizFilial": { "Codigo": "1", "Descricao": "Matriz" }
}
Com a sua chave, a consulta vale para os CNPJs alfanuméricos reais da base da Receita, como o 00000000E08G12. O campo CNPJ da resposta vem sempre com máscara.
Inscrição Estadual
A consulta cadastral da SEFAZ ainda não aceita CNPJ alfanumérico. Por isso, para esses CNPJs:
- a consulta de IE (
GET /consulta/ie/{cnpj}) responde422; - na consulta de CNPJ com
?incluir=ie, a resposta traz os dados do CNPJ comInscricoesEstaduais: nulleInscricoesEstaduaisErro: "cnpj_alfanumerico", e a IE não é cobrada. Isso vale mesmo sem IE no seu plano ou com a cota de IE esgotada: a consulta conta como uma consulta de CNPJ comum.
Perguntas frequentes
O que é o CNPJ alfanumérico? É o CNPJ com letras e números nas 12 primeiras posições, que a Receita Federal passou a emitir em 31/07/2026. Ele continua com 14 caracteres e os dois dígitos verificadores são sempre números.
Os CNPJs antigos vão mudar? Não. Os CNPJs que já existem continuam válidos, sem troca. O formato novo vale só para inscrições novas, emitidas de forma gradual ao longo de 2026.
Como calcular o dígito verificador do CNPJ alfanumérico? Com o mesmo módulo 11 de sempre, dando a cada caractere o valor do código ASCII menos 48: os números valem eles mesmos e as letras vão de 17 (A) a 42 (Z).
A API da CNPJAPI aceita CNPJ alfanumérico? Sim. A consulta GET /{cnpj} aceita o formato novo, em maiúsculas ou minúsculas, e confere o dígito verificador.
Dá para consultar a Inscrição Estadual de um CNPJ alfanumérico? Ainda não, porque a consulta cadastral da SEFAZ não aceita o formato novo. Na consulta de CNPJ com a IE, a resposta indica cnpj_alfanumerico no campo de erro da IE, sem cobrar a IE.
Próximos passos
- Consultar um CNPJ: todos os campos da resposta.
- Chave de testes: os CNPJs de exemplo, inclusive o alfanumérico.
- Consultar CNPJ em lote: para revalidar a base de clientes inteira.