Como validar CNPJ alfanumérico em Python
Função pronta em Python 3 para validar o novo CNPJ alfanumérico e calcular os dígitos verificadores, com uso em Django, Flask, pandas e teste com pytest.
Quer validar o novo CNPJ alfanumérico em Python sem depender de biblioteca externa? Este tutorial traz uma função pronta para checar o CNPJ e calcular os dígitos verificadores em Python 3, com notas de uso em Django, Flask e pandas, além de um teste rápido com pytest.
O que muda no CNPJ alfanumérico
A partir de julho de 2026, a Receita Federal passa a emitir o CNPJ alfanumérico (Instrução Normativa RFB nº 2.229/2024). Ele mantém as 14 posições e a mesma máscara XX.XXX.XXX/XXXX-DD, mas as 12 primeiras posições (raiz + ordem) passam a aceitar letras maiúsculas A–Z e dígitos 0–9. Os dois dígitos verificadores continuam numéricos. Os CNPJs numéricos atuais não mudam e seguem válidos, convivendo com os novos — seu código precisa aceitar os dois formatos. Veja o panorama completo no nosso guia de implementação do CNPJ alfanumérico.
Validando CNPJ alfanumérico em Python
A função abaixo é autossuficiente: usa apenas o módulo re da biblioteca padrão. Ela normaliza a entrada (remove máscara e força maiúsculas), confere o formato (12 posições alfanuméricas + 2 dígitos), descarta a base zerada e compara os dígitos verificadores calculados com os informados. Copie como está:
import re
PESO1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
PESO2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
def normalizar(s: str) -> str:
return re.sub(r'[^A-Z0-9]', '', (s or '').upper())
def _digito(base: str, pesos: list[int]) -> int:
soma = sum((ord(base[i]) - 48) * pesos[i] for i in range(len(base)))
resto = soma % 11
return 0 if resto < 2 else 11 - resto
def calcular_dv(base12: str) -> str:
d1 = _digito(base12, PESO1)
d2 = _digito(base12 + str(d1), PESO2)
return f'{d1}{d2}'
def validar_cnpj(cnpj: str) -> bool:
c = normalizar(cnpj)
if not re.match(r'^[A-Z0-9]{12}[0-9]{2}$', c):
return False
if re.match(r'^0{12}', c):
return False
return calcular_dv(c[:12]) == c[12:]
# validar_cnpj('12.ABC.345/01DE-35') # TrueRepare que validar_cnpj aceita a entrada com ou sem máscara, porque normalizar remove tudo que não for letra ou número antes de checar o formato.
Calculando os dígitos verificadores
Se você precisa gerar o CNPJ (e não só validar), use calcular_dv diretamente, passando as 12 primeiras posições. O primeiro dígito sai do peso PESO1 sobre as 12 posições; o segundo sai do PESO2 sobre as 12 posições mais o primeiro dígito. A regra do resto é a clássica do módulo 11: resto = soma % 11 e dv = 0 se resto < 2, senão 11 - resto. Veja em ação:
>>> calcular_dv('12ABC34501DE')
'35'
>>> validar_cnpj('12.ABC.345/01DE-35')
True
>>> validar_cnpj('11.222.333/0001-81') # numérico antigo, ainda válido
True
>>> validar_cnpj('12.ABC.345/01DE-34') # DV errado
FalseUsando em Django, Flask e pandas
Em Django, embrulhe a função em um validador de campo, levantando ValidationError quando validar_cnpj retornar False; aplique-o em models.CharField(validators=[...]) — nunca use campo inteiro para guardar CNPJ. Em Flask, chame validar_cnpj no handler ou num validador do WTForms antes de persistir. Para pandas, dá para limpar e checar uma coluna inteira de uma vez:
import pandas as pd
df['cnpj_limpo'] = df['cnpj'].map(normalizar)
df['cnpj_valido'] = df['cnpj'].map(validar_cnpj)
# só as linhas com CNPJ inválido
invalidos = df[~df['cnpj_valido']]Como testar
- Copie as funções
normalizar,_digito,calcular_dvevalidar_cnpjpara um módulo do seu projeto. - Valide com e sem máscara — a normalização cuida disso.
- Confirme com os vetores oficiais abaixo (válidos e inválidos).
- Gere massa de teste com o nosso gerador de CNPJ alfanumérico e confira no validador de CNPJ alfanumérico.
| CNPJ | Tipo | Esperado |
|---|---|---|
12.ABC.345/01DE-35 | Alfanumérico (filial) | Válido |
XP.TO1.234/0001-20 | Alfanumérico (matriz) | Válido |
9F.8E7.D6C/0001-36 | Alfanumérico (matriz) | Válido |
A1.B2C.3D4/E5F6-68 | Alfanumérico (filial) | Válido |
ZZ.ZZ0.001/AAAA-41 | Alfanumérico | Válido |
2W.7H9.KQ5/R3T8-19 | Alfanumérico | Válido |
11.222.333/0001-81 | Numérico clássico | Válido |
12.ABC.345/01DE-34 | DV errado | Inválido |
Para automatizar, um teste curto com pytest resolve:
import pytest
from cnpj import validar_cnpj, calcular_dv
@pytest.mark.parametrize('cnpj', [
'12.ABC.345/01DE-35',
'XP.TO1.234/0001-20',
'9F.8E7.D6C/0001-36',
'A1.B2C.3D4/E5F6-68',
'ZZ.ZZ0.001/AAAA-41',
'2W.7H9.KQ5/R3T8-19',
'11.222.333/0001-81',
])
def test_validos(cnpj):
assert validar_cnpj(cnpj) is True
def test_dv_errado():
assert validar_cnpj('12.ABC.345/01DE-34') is False
def test_calcular_dv():
assert calcular_dv('12ABC34501DE') == '35'Perguntas frequentes
Preciso de alguma biblioteca para validar CNPJ alfanumérico em Python?
Não. A função usa apenas o módulo re, que já vem na biblioteca padrão do Python 3. Basta copiar o código para o seu projeto.
A mesma função valida os CNPJs numéricos antigos?
Sim. O algoritmo é o mesmo módulo 11, e dígitos numéricos são um caso particular do cálculo com ord(c) - 48. Por isso 11.222.333/0001-81 continua retornando True.
Como integro isso a um formulário Django ou Flask?
Embrulhe validar_cnpj em um validador: no Django, levante ValidationError quando retornar False e use no CharField; no Flask/WTForms, faça a mesma checagem num validador customizado. Guarde sempre como texto em maiúsculas.
Posso validar uma planilha inteira com pandas?
Sim. Use df['cnpj'].map(validar_cnpj) para marcar válidos e inválidos, e df['cnpj'].map(normalizar) para padronizar a coluna. Leia o arquivo com dtype=str para preservar zeros à esquerda.
Veja também as versões em JavaScript e Java deste mesmo algoritmo.
Fontes: Receita Federal (IN RFB 2.229/2024) e nota técnica do Serpro sobre o CNPJ alfanumérico.
Ofertas em destaque
Ver todas →
Shopee
-56%
Calça Pantalona Lanzinha Feminina Cintura Alta Com Elastico De e Bolso Outono / Inverno Promoção
Amazon
-14%
Lenços Umedecidos Huggies Rosto e Corpo Limpeza 4 x 48 Un
Shopee
-60%
Brow Rise Gel Para Sobrancelhas By Ruby Rose Linha Rosa HB-E2503 Hot Sale
Amazon
-27%
Hellmann's Maionese Light 500g
Amazon
-93%
Tramontina Ducha Elétrica 3 Temperaturas 5500 W 127 V Chuveiro Branco
Mercado Livre
-20%
Malbec Pure Gold O Boticário Desodorante Colônia Perfume Masculino Original 100ml
Mercado Livre
Perfume Lattafa Bade'e Al Oud For Glory Edp Spray 100 Ml
Mercado Livre
Jaqueta Masc. Sarja Capuz Broken Rules 510075 Preto M Lisa
Mercado Livre