Pular para o conteúdo
ValidadorCNPJ Gerar CNPJ

Python · código pronto

Validar CNPJ alfanumérico em Python

Validador de CNPJ alfanumérico em Python 3, sem dependências, com validador para Django e Pydantic.

Testar um CNPJ agora Gerar massa de teste

Código Python 3.9+ puro, sem dependências. Abaixo do algoritmo você encontra os plugues prontos para Django e Pydantic, que costumam ser onde a validação de CNPJ realmente mora no projeto.

O algoritmo é sempre o mesmo: cada caractere vale o seu código ASCII menos 48 (0=0 … 9=9, A=17 … Z=42), os pesos vão de 2 a 9 da direita para a esquerda, soma-se tudo, divide-se por 11 e o dígito é 0 quando o resto é menor que 2, ou 11 menos o resto. Ver a conta detalhada.

Código completo

validação de CNPJ alfanumérico em Python
import re

NAO_ALFANUMERICO = re.compile(r"[^0-9A-Z]")
FORMATO = re.compile(r"^[0-9A-Z]{12}\d{2}$")


def limpar_cnpj(valor: str) -> str:
    """Remove máscara e normaliza para maiúsculas."""
    return NAO_ALFANUMERICO.sub("", (valor or "").upper())


def _digito(sequencia: str) -> int:
    """Calcula um dígito do módulo 11 (valor do caractere = ASCII - 48)."""
    soma = 0
    tamanho = len(sequencia)
    for indice, caractere in enumerate(sequencia):
        peso = ((tamanho - 1 - indice) % 8) + 2
        soma += (ord(caractere) - 48) * peso
    resto = soma % 11
    return 0 if resto < 2 else 11 - resto


def calcular_dv(base: str) -> str:
    """Devolve os dois dígitos verificadores da base de 12 caracteres."""
    primeiro = _digito(base)
    segundo = _digito(f"{base}{primeiro}")
    return f"{primeiro}{segundo}"


def validar_cnpj(valor: str) -> bool:
    """Valida CNPJ numérico ou alfanumérico, com ou sem máscara."""
    cnpj = limpar_cnpj(valor)
    if not FORMATO.match(cnpj):
        return False
    if cnpj == cnpj[0] * 14:
        return False
    return calcular_dv(cnpj[:12]) == cnpj[12:]


def formatar_cnpj(valor: str) -> str:
    """Aplica a máscara 00.000.000/0000-00."""
    cnpj = limpar_cnpj(valor)
    if len(cnpj) != 14:
        return cnpj
    return f"{cnpj[:2]}.{cnpj[2:5]}.{cnpj[5:8]}/{cnpj[8:12]}-{cnpj[12:]}"


if __name__ == "__main__":
    assert calcular_dv("12ABC34501DE") == "35"
    assert validar_cnpj("12.ABC.345/01DE-35")
    assert validar_cnpj("11.222.333/0001-81")
    assert not validar_cnpj("11.222.333/0001-82")
    print(formatar_cnpj("12abc34501de35"))  # 12.ABC.345/01DE-35

Testes e integração com o framework

Django e Pydantic
# Django — validador de campo
from django.core.exceptions import ValidationError
from django.db import models


def valida_cnpj(valor):
    if not validar_cnpj(valor):
        raise ValidationError("%(valor)s não é um CNPJ válido", params={"valor": valor})


class Empresa(models.Model):
    # 14 caracteres sem máscara, 18 se você guardar formatado
    cnpj = models.CharField(max_length=14, unique=True, validators=[valida_cnpj])

    def save(self, *args, **kwargs):
        self.cnpj = limpar_cnpj(self.cnpj)
        super().save(*args, **kwargs)


# Pydantic v2 — tipo reutilizável
from typing import Annotated
from pydantic import AfterValidator, BaseModel


def _checa(valor: str) -> str:
    limpo = limpar_cnpj(valor)
    if not validar_cnpj(limpo):
        raise ValueError("CNPJ inválido")
    return limpo


CnpjStr = Annotated[str, AfterValidator(_checa)]


class EmpresaSchema(BaseModel):
    razao_social: str
    cnpj: CnpjStr

Detalhes que costumam quebrar em Python

Casos de teste recomendados

Cubra pelo menos estes cenários — eles pegam praticamente todos os erros de implementação:

EntradaEsperadoO que testa
12.ABC.345/01DE-35válidoexemplo oficial, com máscara
12abc34501de35válidonormalização para maiúsculas
11.222.333/0001-81válidocompatibilidade com o formato numérico
11.222.333/0001-82inválidodígito verificador errado
12ABC34501DEABinválidoletra no dígito verificador
12ABC34501DE3inválidotamanho incorreto
00.000.000/0000-00inválidosequência repetida
"" / nullinválidoentrada vazia sem exceção

Precisa de mais massa de teste? O gerador produz até 500 CNPJs alfanuméricos válidos de uma vez, com opção de baixar em .txt.

O mesmo algoritmo em outras linguagens

Dúvidas sobre CNPJ alfanumérico em Python

Preciso de alguma biblioteca para validar CNPJ alfanumérico em Python?

Não. O código desta página usa apenas a biblioteca padrão de Python — são cerca de 30 linhas. Bibliotecas de terceiros só valem a pena se você também precisa de formatação, geração e validação de outros documentos; e, nesse caso, confira se a versão instalada já suporta o formato alfanumérico.

A mesma função valida CNPJ numérico e alfanumérico em Python?

Sim. Como o valor de cada dígito é o próprio dígito (código ASCII menos 48), o algoritmo alfanumérico produz o mesmo resultado do antigo para números. Você não precisa manter duas funções nem ramificar por formato.

Como testar se a implementação está certa?

Use o exemplo oficial da Receita Federal: a base 12ABC34501DE tem dígitos verificadores 35, formando 12.ABC.345/01DE-35. Confira também um CNPJ numérico conhecido, como 11.222.333/0001-81, e um inválido, como 11.222.333/0001-82.

O que mais precisa mudar além da função de validação?

O tipo da coluna no banco (de numérico para VARCHAR(14)), qualquer conversão para inteiro no caminho do dado, as máscaras de entrada e as regex espalhadas por validações e relatórios. A função de validação costuma ser a parte mais fácil da migração.