Triagem de erro HTTP
Um erro HTTP informa que uma requisição falhou. Geralmente, não diz o porquê. Concluir que "a chave morreu" a partir de um 403 é um palpite disfarçado de número.
Nascido de um incidente real (2026-07-30): uma API de enriquecimento de contatos de terceiros
retornou 403 error code: 1010 para todas as chamadas por seis dias. Foi interpretado como "chave
não autorizada", "créditos esgotados", "cota mensal atingida". Uma solução alternativa de automação de navegador com 756 linhas foi construída com base nessa crença, e um cliente quase foi solicitado a verificar um plano que estava correto. A causa real era um User-Agent ausente, então o CDN baniu o cliente na borda. Um cabeçalho resolveu: 200 OK, dados completos, e o saldo de créditos estava lá o tempo todo.
Execute estes três controles antes de diagnosticar
1. O controle de credencial inválida. Envie a mesma requisição com uma credencial deliberadamente inválida, e novamente sem nenhuma.
for label, key in [("real", REAL_KEY), ("garbage", "0"*36), ("empty", "")]:
... # mesma URL, mesmo método, mesmos cabeçalhos
Se todas as três retornarem o mesmo status e corpo, o erro não é sobre sua credencial. Ele não carrega nenhuma informação sobre autorização, cota ou validade. Pare de raciocinar sobre a chave.
2. O controle de caminho sem sentido. Solicite um caminho que certamente não existe, e a raiz do site.
GET https://api.example.com/definitely-not-a-real-path-12345
GET https://api.example.com/
GET https://www.example.com/ # site de marketing deles
Se o erro da API também vier do site de marketing, você está sendo bloqueado na frente da origem. Nada sobre a chamada da API ajudará.
3. Leia os cabeçalhos da resposta, não apenas o corpo.
except urllib.error.HTTPError as e:
print(e.code, e.headers.get("server"), e.read()[:200])
server: cloudflare em um erro de "auth" é a pista. Assim como cf-ray,
x-amzn-waf, akamai. Isso é infraestrutura, não a API.
Assinaturas conhecidas
| Sintoma | Causa real | Correção |
|---|---|---|
403 + corpo error code: 1010, server: cloudflare | Cloudflare baniu a assinatura do cliente | Envie um User-Agent de navegador real |
Mesmo erro para todo caminho, inclusive / | Bloqueio de borda/WAF ou banimento de IP | Mude UA, depois IP/proxy |
402 | Realmente sem créditos: a requisição autenticou | Recarregue; a chave está boa |
429 logo após um sucesso | Limite de taxa real | Paceie requisições, adicione backoff |
400 com uma mensagem de campo | Você chegou à API e a autenticação passou | Corrija o payload; isso é uma boa notícia |
Um erro de validação 400 é um sinal de sucesso para triagem: prova que a autenticação foi aceita.
Cabeçalhos padrão para qualquer chamada de API server-side
O urllib do Python envia User-Agent: Python-urllib/3.x, que muitos WAFs banem
diretamente. Sempre defina:
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36",
"Accept": "application/json",
"Content-Type": "application/json",
}
Então meça o custo antes de qualquer varredura
Assim que funcionar, não estime gastos. Leia o uso antes e depois de uma chamada, e leia o próprio campo de faturamento do provedor na resposta.
before = usage(); result = call(); after = usage()
print("charged:", result.get("billing"), "| measured:", before - after)
O que relatar
Declare o que você testou e o que permanece desconhecido. "Ambas as chaves 403" não é uma descoberta se uma chave vazia retorna o mesmo 403. Diga, em vez disso: "403 é não informativo aqui, uma credencial nula também o retorna; a causa está a montante da autenticação."