Ferramentas gratuitas para desenvolvedores. Nenhum dado real de pessoas é consultado ou armazenado.Como funciona o algoritmo do CPF →
Python

Validar, gerar e formatar CNPJ em Python

Funções em Python 3 sem dependências para validar, gerar e formatar CNPJ numérico e alfanumérico, testes com pytest parametrize e uso da API.

Roberto GuerraPublicado em 05 de outubro de 2026Editar no GitHub

Validar CNPJ em Python cabe em poucas linhas da biblioteca padrão, e a mesma função atende o CNPJ numérico e o alfanumérico. A diferença está na conversão de cada caractere: em vez de int(c), que quebra com letras, usa-se ord(c) - 48. Para dígitos o resultado é o mesmo; para letras, A vale 17 e Z vale 42. O módulo abaixo funciona do Python 3.8 em diante e não depende de pacote nenhum. Antes de mexer em produção, vale ler o guia CNPJ alfanumérico: o que muda no seu sistema.

Validar CNPJ em Python (numérico e alfanumérico)

cnpj.py
import re
import secrets

_SEPARADORES = re.compile(r"[./\-\s]")
_PESOS_1 = (5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2)
_PESOS_2 = (6,) + _PESOS_1


def _calcular_digito(base: str, pesos: tuple) -> int:
  soma = sum((ord(c) - 48) * p for c, p in zip(base, pesos))
  resto = soma % 11
  return 0 if resto < 2 else 11 - resto


def validar_cnpj(valor: str) -> bool:
  cnpj = _SEPARADORES.sub("", (valor or "").upper())
  if not re.fullmatch(r"[A-Z0-9]{12}[0-9]{2}", cnpj):
      return False
  if cnpj[:12] == cnpj[0] * 12:
      return False
  base = cnpj[:12]
  dv1 = _calcular_digito(base, _PESOS_1)
  dv2 = _calcular_digito(base + str(dv1), _PESOS_2)
  return cnpj[12:] == f"{dv1}{dv2}"

O que cada parte resolve:

  • .upper() antes da limpeza faz 12.abc.345/01de-35 valer o mesmo que a forma em maiúsculas.
  • [A-Z0-9]{12}[0-9]{2} aceita letras na raiz e na ordem, mas exige dígitos nos verificadores. A classe explícita também recusa dígitos Unicode de outros alfabetos, que \d aceitaria.
  • cnpj[:12] == cnpj[0] * 12 recusa bases repetidas como 00.000.000/0000-00, que fecham a conta, mas não são CNPJs válidos.
  • _PESOS_2 = (6,) + _PESOS_1 monta a segunda sequência de pesos (6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2) sem repetir números.

Fazendo a conta com 11.222.333/0001-81: a primeira soma é 102, o resto é 3 e o dígito é 8; a segunda soma é 120, o resto é 10 e o dígito é 1. Com 12.ABC.345/01DE-35, as somas são 459 e 424, os restos 8 e 6, e os dígitos 3 e 5. A calculadora de dígitos do CNPJ mostra cada produto.

Gerar CNPJ válido em Python

cnpj.py
_DIGITOS = "0123456789"
_ALFANUMERICOS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"


def gerar_cnpj(alfanumerico: bool = False, formatado: bool = False) -> str:
  alfabeto = _ALFANUMERICOS if alfanumerico else _DIGITOS
  while True:
      base = "".join(secrets.choice(alfabeto) for _ in range(12))
      if base != base[0] * 12:
          break
  dv1 = _calcular_digito(base, _PESOS_1)
  dv2 = _calcular_digito(base + str(dv1), _PESOS_2)
  cnpj = f"{base}{dv1}{dv2}"
  return formatar_cnpj(cnpj) if formatado else cnpj

secrets.choice usa o gerador criptográfico do sistema operacional, sem semente previsível. O CNPJ gerado é válido, mas pode coincidir com um CNPJ real por acaso; use-o em fixtures e bancos de teste. Se o teste depende de matriz ou filial, fixe a ordem (0001 é a matriz) e sorteie só a raiz, como explica o guia da estrutura do CNPJ. Para centenas de números sem escrever código, use o gerador de CNPJ em lote.

Formatar e limpar CNPJ em Python

cnpj.py
def limpar_cnpj(valor: str) -> str:
  return re.sub(r"[^A-Z0-9]", "", (valor or "").upper())


def formatar_cnpj(valor: str) -> str:
  c = limpar_cnpj(valor)
  if len(c) != 14:
      raise ValueError(f"CNPJ precisa de 14 caracteres, recebeu {len(c)}")
  return f"{c[:2]}.{c[2:5]}.{c[5:8]}/{c[8:12]}-{c[12:]}"

formatar_cnpj("12abc34501de35") devolve "12.ABC.345/01DE-35", e aplicar a função de novo no resultado não muda nada. limpar_cnpj remove tudo que não for letra ou dígito, o que serve para normalizar antes de gravar, mas não substitui a validação. A formatação recusa tamanhos diferentes de 14 em vez de completar com zeros: se um CNPJ antigo perdeu o zero à esquerda numa coluna numérica, corrija com zfill(14) na migração, onde a origem do dado é conhecida.

Testes

Com pytest, parametrize gera um teste por tupla, e a saída mostra qual caso falhou.

test_cnpj.py
import pytest

from cnpj import formatar_cnpj, gerar_cnpj, limpar_cnpj, validar_cnpj


@pytest.mark.parametrize(
  ("cnpj", "esperado"),
  [
      ("11.222.333/0001-81", True),
      ("12.ABC.345/01DE-35", True),
      ("11.222.333/0001-82", False),
      ("00.000.000/0000-00", False),
  ],
)
def test_validar_cnpj(cnpj, esperado):
  assert validar_cnpj(cnpj) is esperado


@pytest.mark.parametrize("alfanumerico", [False, True])
def test_gerados_sao_validos(alfanumerico):
  assert all(validar_cnpj(gerar_cnpj(alfanumerico)) for _ in range(1000))


def test_formatar_e_limpar():
  assert formatar_cnpj("12abc34501de35") == "12.ABC.345/01DE-35"
  assert formatar_cnpj("12.ABC.345/01DE-35") == "12.ABC.345/01DE-35"
  assert limpar_cnpj("11.222.333/0001-81") == "11222333000181"

Rode com pytest -v. Para ampliar a tabela com letras em outras posições, use os exemplos de CNPJ alfanumérico para teste.

Usar a API em vez de reimplementar

A API do cpf.dev.br valida e gera CNPJs por HTTP, sem chave, com limite de 60 requisições por minuto por IP. Envie o CNPJ sem máscara; se precisar mandar a barra, codifique-a como %2F.

api.py
import requests

r = requests.get("https://www.cpf.dev.br/api/v1/cnpj/validar/12ABC34501DE35", timeout=5)
r.raise_for_status()
print(r.json())
# {'valido': True, 'cnpj': '12ABC34501DE35', 'formatado': '12.ABC.345/01DE-35',
#  'formato': 'alfanumerico', 'raiz': '12ABC345', 'ordem': '01DE', 'matriz': False}

lote = requests.get(
  "https://www.cpf.dev.br/api/v1/cnpj/gerar",
  params={"quantidade": 5, "formato": "alfanumerico", "formatado": "true"},
  timeout=5,
)
print(lote.json()["cnpjs"])

Para validar formulários em Django ou FastAPI, prefira a função local, que não depende de rede. Para conferir um número à mão, use o validador de CNPJ.

Leia também