API 错误

如何处理来自 FourA API 的错误。

错误响应格式

API 为所有错误返回扁平的 JSON 对象。没有嵌套的 error 对象或错误代码。

{
  "error": "Invalid API key"
}

某些错误在顶层包含额外字段,例如 statusserviceretryAftercurrentlimits

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

跟踪 Request

每个 API response(成功或错误)都包含一个带有该调用 UUID 的 X-Foura-Request-Id header。请在您的端记录它。如果您需要向支持人员咨询特定 request 的情况,该 ID 可以帮助我们找到它。

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
# ...

错误类型

400: Bad Request

Request body 缺少必需字段、包含无效值,或者指定了 API 拒绝获取的目标。

{
  "error": "Invalid request body format"
}

相同的 400 错误也适用于 SSRF 保护。如果您的 url 解析为私有、环回或其他保留的 IP 范围(RFC 5735、RFC 6598、IPv6 保留块),则该 request 在离开 FourA 的网络之前就会被拒绝:

{
  "error": "Target <ip> resolves to a private/reserved IP"
}

解决办法: 检查您的 request 是否包含所有必需字段,URL 是否使用 http://https://,以及主机是否解析为公共地址。

401: Unauthorized

您的 API key 缺失或无效。

缺失 key:

{
  "error": "Missing API key. Include X-API-Key header."
}

无效 key:

{
  "error": "Invalid API key"
}

解决办法: 验证您的 X-API-Key header 是否包含有效的 key。如果需要,请从 Dashboard 生成新 key。

429: Rate Limited

您在短时间内发送了太多 request。

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

解决办法: 等待 retryAfter 中指定的秒数,然后再发送更多 request。详情请参阅 Rate Limits

500: Server Error

我们这边出了问题。

解决办法: 稍后重试该 request。如果错误仍然存在,请检查 status page 或联系支持人员,并提供失败 response 中的 X-Foura-Request-Id

503: Service Disabled or At Capacity

503 表示服务因维护暂时不可用,或者您已达到并发限制。这两种 response 都包含 retryAfter 字段。并发形式的错误还包括 currentlimits

{
  "error": "Service disabled",
  "status": 503,
  "retryAfter": 60
}

解决办法: 等待 retryAfter 秒,然后重试。status page 列出了处于活动状态的维护窗口。

200 OK 内部的目标端失败

并非所有失败都会显示为非 2xx HTTP 状态。当目标网站返回带有错误负载的 HTTP 200 时,FourA 仍会将 body 交付给您,但会将该 request 分类为 application_error。当目标返回您的 validate 规则不接受的非 2xx 状态时,结果为 application_fail,并且 body 将保持不变。

这两种情况都将计费,就像 request 在网络层成功工作一样。Outcomes 参考文档涵盖了完整的分类。

Response 编码

FourA 会自动将 response body 解码为 UTF-8。如果目标提供 windows-1251gbkshift_jisiso-8859-* 或在 Content-Type header 或 HTML <meta charset> 标签中声明的任何其他字符集,您将在 data(single、proxy)或 body(browser)字段中收到干净的 UTF-8 字符串。

对于二进制负载(图像、protobuf、原始音频),请在 request 上设置 returnBuffer: true。返回的 body 将作为 base64 缓冲区,不进行任何字符集转码。

重试策略

一个实用的重试策略:

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:
            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")

相关内容

更新于: 2026年6月18日