Normadata API vs. expressões regulares (regex)
Quando uma regex é suficiente para validar um identificador fiscal e quando você precisa de uma API?
A resposta honesta: às vezes a regex é suficiente. Se você só precisa validar um CPF em um projeto pessoal com uma verificação básica de comprimento, uma regex simples é perfeitamente razoável. Mas há cenários em que a regex vai falhar de formas silenciosas e custosas. Este guia explica a diferença com exemplos reais do contexto brasileiro.
Comparação rápida
| Aspecto | Regex (artesanal) | Normadata API |
|---|---|---|
| Custo | Gratuito | Gratuito em beta; precificação pós-beta não anunciada |
| Verifica dígito verificador? | Não (regex não consegue calcular módulo 11) | Sim — algoritmo completo por país |
| Multi-país? | Você precisa de uma regex por país (e mantê-la) | Sim — um endpoint, cobertura multi-país |
| Normaliza o formato? | Não | Sim — retorna forma canônica |
| Detecta prefixos inválidos (ex. CNPJ)? | Apenas se a regex contempla explicitamente | Sim — regras de prefixo inclusas |
| Manutenção quando o padrão muda? | Sua responsabilidade | Responsabilidade do Normadata |
| Funciona em qualquer linguagem? | Sim (com variações de sintaxe) | Sim — HTTP, qualquer stack |
| Latência? | ~0 ms (local) | <50 ms (chamada de API) |
Quando usar cada um?
- Um único país, um único tipo de identificador, e o dígito verificador não é crítico para o seu caso de uso.
- Protótipo ou MVP onde a prioridade é velocidade de desenvolvimento, não robustez.
- O identificador não tem dígito verificador (ex. RG brasileiro, que não usa módulo 11 de forma padronizada nacionalmente).
- Você já tem a biblioteca instalada e ela funciona corretamente no seu conjunto de testes.
- Orçamento zero para dependências externas e o time consegue manter as regex.
- Multi-país: você tem usuários ou clientes no Brasil, Argentina, México, Colômbia — cada um com suas próprias regras de identificador.
- O identificador tem dígito verificador complexo (CPF, CNPJ, CUIT, RFC, RUT): a regex detecta o formato mas não valida o checksum.
- Você precisa de normalização: que '123.456.789-09' e '12345678909' sejam tratados como o mesmo CPF.
- Stack multi-linguagem (Python, Go, JS, Java): uma única API em vez de uma regex por linguagem.
- O time não quer manter 10-20 regex com seus casos extremos, encodings e atualizações.
- Você vai rodar match ou dedupe sobre os identificadores e precisa da forma canônica como base — algo que uma regex não te dá, mas o match/dedupe você roda você mesmo.
O problema real: a regex que parece funcionar mas não valida
Considere este exemplo com CPF. A regex mais comum encontrada no Stack Overflow em PT: `^\d{3}\.\d{3}\.\d{3}-\d{2}$` ou simplesmente `^\d{11}$`. Parece correta — valida comprimento e caracteres. Mas o CPF 111.444.777-00 (onde os dígitos verificadores corretos são 3 e 5, não 0 e 0) passa essa regex sem problema. O número é estruturalmente inválido pelo algoritmo da Receita Federal, mas a regex não sabe disso. Isso significa que você pode armazenar milhares de CPFs inválidos no seu banco de dados, todos com formato aparentemente correto. Pior ainda: se depois você precisar fazer correspondência ou deduplicação contra dados de clientes, os CPFs mal validados vão gerar falsos negativos.
Código comparativo: Python, ambos os lados
O exemplo a seguir mostra como o mesmo CPF inválido (11144477700) passa a regex mas falha na API. A diferença está nos dígitos verificadores: os corretos para essa base são 3 e 5, não 0 e 0.
Exemplos de código
import re
CPF_REGEX = re.compile(r'^\d{11}$')
def validate_with_regex(cpf: str) -> bool:
digits = cpf.replace('.', '').replace('-', '').replace(' ', '')
return bool(CPF_REGEX.match(digits))
print(validate_with_regex("111.444.777-35")) # True (valid)
print(validate_with_regex("111.444.777-00")) # True (WRONG — invalid check digit, should fail)
print(validate_with_regex("000.000.000-00")) # True (WRONG — known invalid CPF pattern)import httpx
def validate_cpfs(cpfs: list[str]) -> list[dict]:
response = httpx.post(
"https://api.normadata.io/v1/validate/tax-ids",
headers={"X-API-Key": "nd_your_key"},
json={"items": [
{"id": str(i), "value": v, "country": "BR"}
for i, v in enumerate(cpfs)
]},
)
return response.json()["results"]
# Same endpoint for 1 or N — up to 1000 per request
results = validate_cpfs(["111.444.777-35", "111.444.777-00"])
print(results[0]["valid"]) # True
print(results[1]["valid"]) # False — wrong check digit
print(results[1]["error"]) # "invalid check digit"O Normadata é uma API hospedada — requer chamada de rede, tem latência (embora baixa) e terá custo pós-beta. Se o seu caso de uso é de um único país, sem dígito verificador complexo, e você consegue manter o código, uma regex pode ser a ferramenta correta. O Normadata não é a resposta para tudo: é a resposta para multi-país, dígitos verificadores complexos (CPF, CNPJ, CUIT, RFC) e normalização.
Perguntas frequentes
Posso usar regex para o CPF?
Você pode validar o formato (11 dígitos, opcionalmente com pontos e traço), mas não pode validar os dois dígitos verificadores com uma regex. O algoritmo do CPF usa módulo 11 com duas rodadas de cálculo. Existem CPFs com formato correto mas dígito verificador incorreto — uma regex os aceitaria.
Quanto custa o Normadata após a beta?
A precificação pós-beta não está anunciada. Durante a beta privada, o acesso é gratuito. Se você quiser acesso antecipado e precificação preferencial, pode se inscrever na lista de espera.
A API funciona com qualquer linguagem?
Sim. É HTTP puro com JSON. Funciona com qualquer linguagem que consiga fazer um POST request: Python, JavaScript, Go, Ruby, Java, PHP, Rust, etc. Nenhum SDK proprietário é necessário.
E os casos extremos de regex multi-país?
São muitos e não intuitivos. O CNPJ tem 14 dígitos com dois dígitos verificadores calculados com pesos distintos — diferente do CPF. O RFC mexicano tem 12 caracteres para pessoas jurídicas e 13 para físicas, com regras de derivação de nome e data. O RUT chileno tem um dígito verificador que pode ser a letra K. Manter regex corretas e atualizadas para cada país é um compromisso de tempo que uma API resolve.