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.

  1. 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.
  2. Some os resultados e calcule o resto da divisão por 11.
  3. Se o resto for 0 ou 1, o dígito é 0. Senão, o dígito é 11 menos o resto.
  4. 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) ou VARCHAR(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.ToInt64 ou comparam CNPJ como número. Todos quebram com letra.
  • Maiúsculas: normalize para maiúsculas antes de gravar e de comparar, para que 12abc34501de35 e 12ABC34501DE35 sejam 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}) responde 422;
  • na consulta de CNPJ com ?incluir=ie, a resposta traz os dados do CNPJ com InscricoesEstaduais: null e InscricoesEstaduaisErro: "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