Plataformas de venda de passagens aéreas e rodoviárias são obrigadas a validar o CPF do passageiro para cumprir exigências da ANAC, ANTT e Receita Federal — sem isso, a emissão do bilhete e da nota fiscal fica comprometida. A CPFHub.io permite essa validação em ~900ms via API REST, retornando nome completo e data de nascimento para conferência automática dos dados, o que reduz erros no embarque e bloqueia fraudes com cartões roubados.
Introdução
A venda online de passagens aéreas e rodoviárias no Brasil movimenta bilhões de reais por ano. Diferentemente de outros segmentos do e-commerce, esse setor opera sob regulamentações específicas da ANAC e da ANTT que exigem a identificação do passageiro no momento da compra. O CPF é o principal identificador utilizado nesse processo -- e sua validação é obrigatória para garantir conformidade, prevenir fraudes e evitar problemas no embarque.
Exigências regulatórias
ANAC -- passagens aéreas
A Agência Nacional de Aviação Civil exige que o bilhete aéreo contenha o nome completo do passageiro conforme documento oficial. Embora o CPF não seja tecnicamente obrigatório no bilhete, ele é amplamente utilizado como identificador único para fins fiscais, programas de fidelidade e check-in online. Divergências entre o nome do passageiro e o nome no documento podem impedir o embarque.
ANTT -- passagens rodoviárias
A Agência Nacional de Transportes Terrestres, por meio da Resolução 4.770, exige que a venda de passagens rodoviárias interestaduais e internacionais inclua a identificação do passageiro. O CPF é o documento mais utilizado para esse fim, especialmente em vendas online onde o passageiro não apresenta documento físico no momento da compra.
Receita Federal
A emissão de nota fiscal na venda de passagens exige o CPF do comprador. Um CPF inválido ou inexistente impede a emissão fiscal correta, gerando problemas contábeis e regulatórios para a plataforma.
Cenários de fraude no setor
O setor de passagens enfrenta fraudes específicas que a validação de CPF ajuda a combater.
Compra com cartão roubado
O fraudador compra passagens com cartão de crédito roubado e as revende abaixo do preço de mercado. A validação de CPF permite verificar se o titular do cartão corresponde ao passageiro, adicionando uma camada de verificação.
Cambistas digitais
Intermediários compram passagens em promoções e as revendem com lucro. Embora nem sempre ilegal, essa prática pode ser controlada limitando o número de compras por CPF em determinado período.
Reservas fantasma
Bots criam reservas em massa para segurar assentos em voos promocionais, liberando-os apenas quando o prazo de pagamento está prestes a vencer. A exigência de CPF válido no momento da reserva dificulta essa prática.
Implementação em Python
O exemplo a seguir demonstra um sistema de venda de passagens com validação de CPF integrada.
import requests
import re
from datetime import datetime, timedelta
from typing import Optional
import json
CPFHUB_API_URL = "https://api.cpfhub.io/cpf"
CPFHUB_API_KEY = "SUA_CHAVE_DE_API"
REQUEST_TIMEOUT = 10 # segundos
def consultar_cpf(cpf: str) -> Optional[dict]:
"""Consulta CPF na API CPFHub.io."""
cpf_limpo = re.sub(r"\D", "", cpf)
try:
response = requests.get(
f"{CPFHUB_API_URL}/{cpf_limpo}",
headers={
"x-api-key": CPFHUB_API_KEY,
"Accept": "application/json",
},
timeout=REQUEST_TIMEOUT,
)
response.raise_for_status()
dados = response.json()
if dados.get("success"):
return dados["data"]
return None
except requests.exceptions.Timeout:
raise Exception("Timeout na consulta de CPF")
except requests.exceptions.HTTPError as e:
status = e.response.status_code
mensagens = {
401: "Chave de API inválida",
404: None, # CPF não encontrado
}
if status in mensagens:
if mensagens[status] is None:
return None
raise Exception(mensagens[status])
raise Exception(f"Erro HTTP {status}")
except requests.exceptions.RequestException:
raise Exception("Erro de conexão com a API")
def normalizar_nome(nome: str) -> str:
"""Remove acentos e normaliza o nome para comparação."""
import unicodedata
nome_normalizado = unicodedata.normalize("NFKD", nome)
nome_sem_acento = nome_normalizado.encode("ASCII", "ignore").decode("ASCII")
return nome_sem_acento.upper().strip()
def verificar_correspondencia_nome(
nome_informado: str, nome_api: str, tolerancia: float = 0.8
) -> dict:
"""Verifica se o nome informado corresponde ao retornado pela API."""
partes_informado = normalizar_nome(nome_informado).split()
partes_api = normalizar_nome(nome_api).split()
# Verifica primeiro e último nome
primeiro_ok = partes_informado[0] == partes_api[0] if partes_informado and partes_api else False
ultimo_ok = partes_informado[-1] == partes_api[-1] if partes_informado and partes_api else False
# Calcula score de similaridade
partes_em_comum = set(partes_informado) & set(partes_api)
total_partes = max(len(partes_informado), len(partes_api))
score = len(partes_em_comum) / total_partes if total_partes > 0 else 0
return {
"corresponde": primeiro_ok and ultimo_ok and score >= tolerancia,
"score": round(score, 2),
"primeiro_nome_ok": primeiro_ok,
"ultimo_nome_ok": ultimo_ok,
"nome_sugerido": nome_api,
}
def validar_passageiro(
cpf: str,
nome_passageiro: str,
data_viagem: str,
) -> dict:
"""Valida CPF e dados do passageiro para emissão de bilhete."""
cpf_limpo = re.sub(r"\D", "", cpf)
# Validação estrutural do CPF
if len(cpf_limpo) != 11:
return {"valido": False, "erro": "CPF deve ter 11 dígitos"}
# Consulta à API
try:
dados = consultar_cpf(cpf_limpo)
except Exception as e:
return {"valido": False, "erro": str(e)}
if not dados:
return {"valido": False, "erro": "CPF não encontrado na base"}
# Verificação de correspondência de nome
verificacao_nome = verificar_correspondencia_nome(
nome_passageiro, dados.get("name", "")
)
if not verificacao_nome["corresponde"]:
return {
"valido": False,
"erro": "Nome do passageiro não corresponde ao CPF",
"nome_no_cpf": dados.get("name"),
"score_similaridade": verificacao_nome["score"],
"sugestao": f"Verifique se o nome correto é: {dados.get('name')}",
}
# Verificação de idade (menores podem precisar de autorização)
ano_nascimento = dados.get("year", 0)
idade = datetime.now().year - ano_nascimento
menor_de_idade = idade < 18
return {
"valido": True,
"passageiro": {
"cpf": cpf_limpo,
"nome": dados.get("name"),
"nomeUpper": dados.get("nameUpper"),
"dataNascimento": dados.get("birthDate"),
"genero": dados.get("gender"),
"menorDeIdade": menor_de_idade,
},
"alertas": (
["Passageiro menor de idade -- autorização pode ser necessária"]
if menor_de_idade
else []
),
}
def emitir_bilhete(
cpf: str,
nome_passageiro: str,
origem: str,
destino: str,
data_viagem: str,
tipo: str = "aereo",
) -> dict:
"""Emite bilhete após validação completa."""
# Valida passageiro
validacao = validar_passageiro(cpf, nome_passageiro, data_viagem)
if not validacao["valido"]:
return {"emitido": False, "erro": validacao["erro"]}
passageiro = validacao["passageiro"]
# Gera localizador
import hashlib
hash_base = f"{cpf}-{origem}-{destino}-{data_viagem}-{datetime.now().isoformat()}"
localizador = hashlib.md5(hash_base.encode()).hexdigest()[:6].upper()
bilhete = {
"emitido": True,
"localizador": localizador,
"tipo": tipo,
"passageiro": passageiro["nomeUpper"],
"cpf": passageiro["cpf"][:3] + ".***.***-" + passageiro["cpf"][-2:],
"origem": origem,
"destino": destino,
"dataViagem": data_viagem,
"emitidoEm": datetime.now().strftime("%d/%m/%Y %H:%M"),
"alertas": validacao.get("alertas", []),
}
return bilhete
# Exemplo de uso
if __name__ == "__main__":
# Emitir passagem aérea
resultado = emitir_bilhete(
cpf="123.456.789-09",
nome_passageiro="João da Silva",
origem="GRU",
destino="GIG",
data_viagem="15/10/2025",
tipo="aereo",
)
print(json.dumps(resultado, indent=2, ensure_ascii=False))
# Emitir passagem rodoviária
resultado_rod = emitir_bilhete(
cpf="987.654.321-00",
nome_passageiro="Maria Oliveira",
origem="São Paulo - Tietê",
destino="Rio de Janeiro - Novo Rio",
data_viagem="20/10/2025",
tipo="rodoviario",
)
print(json.dumps(resultado_rod, indent=2, ensure_ascii=False))
Controle de compras por CPF
Para combater cambistas e reservas fantasma, implemente limites de compra por CPF.
from collections import defaultdict
from datetime import datetime, timedelta
# Registro de compras por CPF
compras_por_cpf = defaultdict(list)
# Limites configuráveis
LIMITE_PASSAGENS_DIA = 5
LIMITE_PASSAGENS_MES = 20
LIMITE_MESMO_TRECHO_DIA = 2
def verificar_limites(cpf: str, origem: str, destino: str) -> dict:
"""Verifica se o CPF atingiu algum limite de compra."""
cpf_limpo = re.sub(r"\D", "", cpf)
agora = datetime.now()
compras = compras_por_cpf.get(cpf_limpo, [])
# Compras nas últimas 24 horas
compras_24h = [c for c in compras if agora - c["data"] < timedelta(hours=24)]
# Compras no mês atual
compras_mes = [c for c in compras if c["data"].month == agora.month]
# Mesmo trecho nas últimas 24 horas
mesmo_trecho_24h = [
c for c in compras_24h
if c["origem"] == origem and c["destino"] == destino
]
alertas = []
if len(compras_24h) >= LIMITE_PASSAGENS_DIA:
return {
"permitido": False,
"erro": f"Limite de {LIMITE_PASSAGENS_DIA} passagens por dia atingido",
}
if len(compras_mes) >= LIMITE_PASSAGENS_MES:
return {
"permitido": False,
"erro": f"Limite de {LIMITE_PASSAGENS_MES} passagens por mês atingido",
}
if len(mesmo_trecho_24h) >= LIMITE_MESMO_TRECHO_DIA:
return {
"permitido": False,
"erro": f"Limite de {LIMITE_MESMO_TRECHO_DIA} passagens para o mesmo trecho por dia",
}
if len(compras_24h) >= LIMITE_PASSAGENS_DIA - 1:
alertas.append("Próximo do limite diário de compras")
return {"permitido": True, "alertas": alertas}
Integração com companhias
As companhias aéreas e rodoviárias exigem que os dados do passageiro sejam consistentes em todas as etapas -- reserva, emissão, check-in e embarque. A API da CPFHub.io retorna exatamente os campos exigidos pelas companhias nos arquivos de manifesto de passageiros, garantindo consistência end-to-end sem retrabalho manual.
Os dados retornados pela API -- nome completo, data de nascimento e gênero -- são precisamente os campos exigidos pelas companhias nos arquivos de manifesto de passageiros.
Considerações de performance
No setor de passagens, a velocidade do checkout é crítica. Promoções de passagens aéreas esgotam em minutos, e qualquer latência adicional pode significar a perda da venda.
A API da CPFHub.io opera com latência média de ~900ms, o que é suficiente para validar o passageiro em segundo plano enquanto o usuário preenche os demais campos do formulário, sem impactar a experiência de compra.
Perguntas frequentes
O que é necessário para implementar validação de CPF neste contexto?
A validação de CPF exige uma chamada à API com o número do documento e a chave de autenticação. A CPFHub.io retorna o status do CPF, nome do titular e data de nascimento em ~900ms, permitindo a verificação em tempo real durante o cadastro ou transação.
A API CPFHub.io funciona para todos os volumes de consulta?
Sim. O plano gratuito oferece 50 consultas por mês sem cartão de crédito — ideal para testes e projetos pequenos. Para volumes maiores, o plano Pro inclui 1.000 consultas mensais por R$149. Se o limite for ultrapassado, a API não bloqueia: cobra R$0,15 por consulta adicional.
Como garantir conformidade com a LGPD ao usar uma API de CPF?
Use o CPF apenas para a finalidade declarada ao titular, armazene apenas o necessário (não guarde o CPF cru se um token bastar), implemente controle de acesso aos logs de consulta e documente a base legal para o tratamento. A ANPD orienta que dados de identificação devem ser tratados com o princípio da necessidade.
Quanto tempo leva para integrar a API CPFHub.io?
A integração básica leva menos de 30 minutos: crie uma conta em cpfhub.io, gere a API key no painel e faça uma chamada GET para https://api.cpfhub.io/cpf/{CPF} com o header x-api-key. A documentação inclui exemplos em Python, Node.js, PHP, Java e outras linguagens.
Conclusão
A validação de CPF em plataformas de venda de passagens não é apenas uma boa prática -- é uma necessidade regulatória e operacional. Ela garante conformidade com as exigências da ANAC e ANTT, previne fraudes com cartões roubados, combate cambistas digitais e evita problemas no embarque por divergência de dados.
A integração com a CPFHub.io leva menos de 30 minutos e já inclui tratamento de erros, comparação de nomes e controle de limites por CPF — tudo o que uma plataforma de passagens precisa para operar com segurança e conformidade. Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e comece hoje mesmo.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



