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

Atualizado em: 12 de agosto de 2026