Erros da API
Como tratar erros da API FourA.
Formato da resposta de erro
A API retorna objetos JSON planos para todos os erros. Não há um objeto error aninhado ou códigos de erro.
{
"error": "Invalid API key"
}
Alguns erros incluem campos extras como status, service, retryAfter, current ou limits no nível superior:
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
Rastreando um request
Toda response da API (sucesso ou erro) inclui um header X-FourA-Request-Id com um UUID para essa chamada. Registre isso do seu lado. Se você precisar perguntar ao suporte o que aconteceu com um request específico, esse ID nos permite encontrá-lo.
curl -i -X POST https://eu.api.foura.ai/api/single/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method": "GET", "url": "https://example.com"}'
# HTTP/1.1 200 OK
# X-FourA-Request-Id: 9f1c4e6c-7b2a-4d3e-8a1f-2c9d8e4a3b15
# Content-Type: application/json
# ...
Tipos de Erro
400: Bad Request
O corpo do request não possui os campos obrigatórios, contém valores inválidos ou especifica um alvo que a API se recusa a buscar.
{
"error": "Invalid request body format"
}
O mesmo 400 também cobre a proteção SSRF. Se o seu url resolver para um intervalo de IP privado, de loopback ou reservado (RFC 5735, RFC 6598, blocos reservados IPv6), o request é rejeitado antes de sair da rede da FourA:
{
"error": "Target <ip> resolves to a private/reserved IP"
}
JSON malformado no corpo é recusado da mesma forma, antes que qualquer campo seja lido:
{
"error": "Invalid JSON in request body"
}
Os campos proxy e ignoreProxies têm seus próprios erros 400. Ambos aceitam os IDs de proxy opacos que as responses anteriores retornaram, então qualquer outra coisa falha ao decodificar:
| Mensagem | O que aconteceu |
|---|---|
Invalid proxy format |
O valor proxy não é um ID de proxy emitido pela FourA. Um endereço de proxy bruto cai aqui. |
Invalid ignoreProxies format |
Uma das entradas em ignoreProxies não é um ID de proxy. |
Proxy not found |
O ID foi decodificado corretamente, mas não resolve mais para uma saída ativa. Escolha um novo. |
Correção: Verifique se a sua request inclui todos os campos obrigatórios, se as URLs usam http:// ou https://, se o host resolve para um endereço público e se qualquer valor proxy é um ID copiado exatamente de uma response anterior.
401: Não autorizado
Sua chave de API está ausente ou inválida.
Chave ausente:
{
"error": "Missing API key. Include X-API-Key header."
}
Chave inválida:
{
"error": "Invalid API key"
}
Correção: Verifique se o seu header X-API-Key contém uma chave válida. Gere uma nova chave no Dashboard se necessário.
429: Rate Limited
Você enviou muitos requests em um curto período.
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
Solução: Aguarde o número de segundos em retryAfter antes de enviar mais requests. Consulte Rate Limits para obter detalhes.
500: Erro do Servidor
Algo deu errado do nosso lado.
Solução: Tente o request novamente após um curto atraso. Se o erro persistir, verifique a página de status ou entre em contato com o suporte com o X-FourA-Request-Id do response que falhou.
502: Upstream Indisponível
A FourA alcançou seu próprio mecanismo, mas não conseguiu usar a resposta.
{
"error": "Upstream unavailable",
"details": "..."
}
Correção: Tente novamente com um curto backoff. Isso é um problema do nosso lado, portanto não tem custo para você: o resultado é service_error e apenas success é cobrado.
504: Upstream Timeout
O motor não concluiu dentro do limite de tempo para este request.
{
"error": "Upstream timeout",
"details": "the backend did not finish inside the time budget for this request"
}
Um erro 504 é sobre quanto tempo o trabalho levou, não sobre sua chave, seus parâmetros ou seu proxy. Alvos lentos, resoluções a frio de desafios e páginas grandes são as causas comuns.
Correção: Aumente o timeout_ms na request (Single aceita até 120000, Browser até 120000, Auto até 180000) ou tente novamente. O FourA aguarda o tempo limite que você declarou mais uma pequena margem, então pedir mais tempo genuinamente compra mais tempo.
503: Serviço Desativado ou na Capacidade Máxima
Um erro 503 significa que o serviço está temporariamente indisponível para manutenção ou você atingiu o limite de concorrência. Ambas as respostas incluem um campo retryAfter. O formato de concorrência também inclui current e limits.
{
"error": "Service disabled",
"status": 503,
"retryAfter": 60
}
Correção: Aguarde retryAfter segundos e tente novamente. A página de status lista as janelas de manutenção ativas.
Um terceiro formato 503 não possui retryAfter. Isso significa que o motor por trás do seu endpoint estava reiniciando quando a sua chamada chegou:
{
"error": "Backend service unavailable",
"backend_status": 503
}
Tente novamente após um ou dois segundos.
Lendo falhas de /api/auto/
POST /api/auto/ responde com HTTP 200 sempre que a ladder for executada, mesmo quando cada rung falhar. O resultado real está no body:
{
"status": 0,
"error": "all attempts failed",
"attempts": 7,
"meta": { "rung": "fail", "solved": false, "attempts": 7, "credits": 47 }
}
Portanto, não faça ramificações no status de transporte para Auto. Em vez disso, leia status e error do corpo. Um status não 200 genuíno de /api/auto/ significa que a FourA rejeitou a chamada antes de iniciar a escada: 401, 400, 429 ou 503, todos documentados acima.
Falhas no Lado do Alvo Dentro de 200 OK
Nem toda falha aparece como um status HTTP não 2xx. Quando o site alvo retorna HTTP 200 com um payload de erro, a FourA ainda entrega o corpo para você, mas classifica a request como application_error. Quando o alvo retorna um status não 2xx que suas regras de validate não aceitam, o resultado é application_fail e o corpo é retornado inalterado.
Ambos os casos são faturáveis como se a request tivesse funcionado no nível da rede. A referência de Resultados cobre toda a taxonomia.
Codificação de Response
A FourA decodifica automaticamente os corpos de response para UTF-8. Se o alvo fornecer windows-1251, gbk, shift_jis, iso-8859-* ou qualquer outro charset declarado no header Content-Type ou em uma tag HTML <meta charset>, você receberá uma string UTF-8 limpa no campo data (único, proxy) ou body (browser).
Para payloads binários (imagens, protobuf, áudio bruto), defina returnBuffer: true na request. O corpo retorna como um buffer base64 sem nenhuma transcodificação de charset aplicada.
Estratégia de Retry
Uma política prática de retry:
import time
import requests
def make_request(url, payload, api_key, max_retries=3):
for attempt in range(max_retries):
resp = requests.post(
url,
headers={"X-API-Key": api_key, "Content-Type": "application/json"},
json=payload,
)
if resp.status_code == 200:
return resp.json()
body = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
retry_after = body.get("retryAfter", 2 ** attempt)
request_id = resp.headers.get("X-FourA-Request-Id", "?")
if resp.status_code in (429, 503):
time.sleep(retry_after)
continue
if resp.status_code >= 500: # 500, 502, 503, 504 are all ours to fix
time.sleep(2 ** attempt)
continue
# 400/401/404 won't fix themselves
raise RuntimeError(f"{resp.status_code} (request {request_id}): {body.get('error')}")
raise RuntimeError(f"Exhausted {max_retries} retries")
Relacionados
- Rate Limits: Detalhes de concorrência e RPM
- Resultados da request: Os sete valores de resultado explicados
- Problemas Comuns: Sintomas, causas, correções
- Defesas Anti-Bot: Quando o body é uma página de desafio em vez de um erro