响应标头
FourA API 的每个 response 都包含一组自定义 header。它们适用于链路追踪、技术支持、账单核对和事后分析。
FourA 设置的 Header
| Header | 生效范围 | 说明 |
|---|---|---|
X-FourA-Request-Id |
所有 /api/* response,包括错误和 401,但 FourA 完全无法读取 body 的情况除外(400 Invalid JSON in request body、413),此类请求在分配 ID 前即被拒绝 |
标识此 request 的 UUID。建议在客户端记录此 ID。 |
X-FourA-Credits |
到达后端的每个 /api/* response |
本次调用消耗的积分。无论成功还是失败均会返回(后端均已执行处理)。 |
X-FourA-Limit |
由套餐限额触发的每个 403 或 429 |
拒绝该调用的具体限制项:plan_limit_ 紧跟 feature、premium、concurrency、rate、browser_daily、credits 或 bandwidth。 |
Retry-After |
可通过等待恢复的套餐限额 429(并发、速率、积分、带宽) |
需要等待的秒数(整数)。与 body 中的 retry_after_seconds 一致。 |
X-FourA-Exit-Class |
指定了 exitClass 并成功返回页面的每个 /api/proxy/ 调用,以及通过高级出口节点路由的每个 Single 或 Browser 调用 |
premium 或 standard:交付 body 的出口类别。失败的 Proxy 调用未交付任何内容,因此不包含此 header。 |
X-FourA-Check-Page |
HTTP 200 body 为 FourA 可识别的机器人验证页面的 Single、Proxy Finder 和 Browser response | 验证页面的名称,例如 amazon-captcha。此类 request 不计费:参见 Request Outcomes。 |
Content-Type |
所有 response | 响应外层始终为 application/json。目标内容的 content-type 会在外层的 headers 字段中返回。 |
X-FourA-Request-Id
每次对 POST /api/auto/、POST /api/single/、POST /api/proxy/ 或 POST /api/browser/ 的调用都会标记一个 UUID。即使身份验证失败也会设置该 header,便于关联排查配置错误的调用。
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
X-FourA-Credits: 2
Content-Type: application/json
...
适用场景
- 技术支持工单:附带 request ID,以便我们在记录中精准定位该次调用。
- 自定义日志:将其与应用程序日志行一同存储。如果客户反馈“14:32 的数据有误”,你可以重放完全相同的 request。
- 控制台追踪:相同的 ID 会显示在你所管理密钥的 Activity feed 中,方便你打开对应行并检查捕获的 request 和 response。
示例:在客户端记录日志
import logging
import requests
log = logging.getLogger(__name__)
def fetch(url, api_key):
resp = requests.post(
"https://eu.api.foura.ai/api/single/",
headers={"X-API-Key": api_key, "Content-Type": "application/json"},
json={"method": "GET", "url": url},
)
request_id = resp.headers.get("X-FourA-Request-Id", "no-id")
credits = resp.headers.get("X-FourA-Credits", "0")
log.info("foura request_id=%s url=%s status=%s credits=%s", request_id, url, resp.status_code, credits)
resp.raise_for_status()
return resp.json()
async function fetchPage(url, apiKey) {
const resp = await fetch('https://eu.api.foura.ai/api/single/', {
method: 'POST',
headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify({ method: 'GET', url })
});
const requestId = resp.headers.get('X-FourA-Request-Id') || 'no-id';
const credits = resp.headers.get('X-FourA-Credits') || '0';
console.log(`foura request_id=${requestId} url=${url} status=${resp.status} credits=${credits}`);
return resp.json();
}
X-FourA-Credits
X-FourA-Credits 报告刚完成调用的积分消耗。它是一个计量器,而非账单:无论结果如何,该 header 都反映本次操作所消耗的额度。控制台的计费层仅针对计费结果计入您的套餐(请参阅 Request Outcomes 了解哪些结果计费)。
费用参考
| Engine | Base | With unblocker |
|---|---|---|
| Single | 1 | 2 |
| Proxy | 2 | 4 |
| Browser | 5 | 10 (when a defense was solved) |
/api/auto/ 在控制台中计为一次 request,其积分消耗为其内部子调用的总和(在预热目标上的单次重试可能消耗 2;在复杂站点上的冷启动破解可能消耗更多)。Auto 响应上的 X-FourA-Credits 值等于 body 中的 meta.credits,并跟踪完整的阶梯调用成本。
为什么同时提供 header 和 body 字段?
Header 便于使用:您可以在解析 body 之前读取它、将其记录在 request 行旁边,或者在无需解析 JSON 的情况下对多次调用求和。Body 中的 meta.credits (Auto) 或各 engine 元数据(Single、Proxy、Browser 控制台)包含相同的数值,但可以在响应封装内读取。
X-FourA-Limit
X-FourA-Limit 仅在套餐限制拒绝该调用时出现。平台的共享 rate limit 绝不会设置此项,因此该 header 是区分“我的套餐阻止了此请求”与“FourA 繁忙”的最快方式,无需解析 body。
HTTP/1.1 429 Too Many Requests
X-FourA-Limit: plan_limit_concurrency
Retry-After: 1
X-FourA-Request-Id: 9f1c4e6c-7b2a-4d3e-8a1f-2c9d8e4a3b15
Content-Type: application/json
在这七个值中,有两个返回 403 而不是 429:plan_limit_feature(该 endpoint 或 exitCountries 参数未包含在您的套餐中)和 plan_limit_premium(exitClass: premium 未包含在您的套餐中)。两者均未设置 Retry-After,因为等待不会改变结果。
STOP_ON = {
"plan_limit_feature", "plan_limit_premium",
"plan_limit_browser_daily", "plan_limit_credits", "plan_limit_bandwidth",
}
resp = requests.post(url, headers=headers, json=payload)
limit = resp.headers.get("X-FourA-Limit")
if limit in STOP_ON:
stop_the_run(limit) # hours or days away, not seconds
elif limit:
time.sleep(int(resp.headers.get("Retry-After", 1)))
这七个值以及各自附带的 body 字段请参见 Rate Limits。
X-FourA-Exit-Class
X-FourA-Exit-Class 用于指定传递 body 的出口类别:高级出口传递时为 premium,标准池传递时为 standard。当 request 指定了 exitClass 时,它会出现在成功交付页面的 POST /api/proxy/ response 中,此时 body 包含相同的值;当您固定的 proxy 为高级出口时,它会出现在 Single 或 Browser response 中,此时 body 中不包含该字段。失败的 Proxy 调用未提供任何内容,因此既不包含 header 也不包含该字段。
HTTP/1.1 200 OK
X-FourA-Exit-Class: premium
X-FourA-Credits: 2
X-FourA-Request-Id: 2c1d0f9e-4a7b-4c3e-9d2a-8b1f6e5c4d3a
Content-Type: application/json
通过高级出口的流量会计入您的高级流量以及总带宽。该指标在网络层进行计量,并包含未成功返回页面的高级尝试。因此,即使返回 standard 的 request,也可能在标准池响应之前的失败尝试中消耗了部分高级流量。此 header 仅指明交付响应的类别,并不表示是否使用了高级流量:Activity 记录行上的 premium 标记以及 Usage & Limits 页面会显示实际计费情况。关于 exitClass 的作用以及何时使用高级出口,请参阅 exitClass。
Cache Behavior
API 不会在 response 中设置 Cache-Control 或 ETag。每次调用都会请求后端。如果需要缓存,请在客户端自行实现。
Target Response Headers
目标网站返回的 header 不会直接出现在 FourA API 的 response 中。它们会作为 headers 字段封装在 JSON 数据中返回。对于 Single 和 Proxy endpoint,这是一个包含每跳 header 对象的数组(每个重定向步骤对应一个条目)。对于 Browser endpoint,它是最终 response header 的扁平对象。
{
"status": 200,
"headers": [
{ "Content-Type": "text/html; charset=utf-8", "Server": "..." }
],
"data": "<!doctype html>...",
"total_time": 0.42
}
如果需要特定的目标 header,请从 envelope 的 headers 字段中读取,而不是直接从 API 调用的 HTTP response 中读取。
相关内容
- API Endpoints: Request 和 response envelope 结构
- API Errors: 错误 response 的结构说明
- Request Outcomes: 哪些结果计费
- Activity Log: 按 request ID 索引的单次 request 历史记录
- Rate Limits: 每个
X-FourA-Limit值的含义