API 端点参考
包含所有 FourA API endpoint、request 参数及 response 格式的参考文档。
Base URL
https://eu.api.foura.ai/api
认证
每个 request 都需要在 X-API-Key header 中包含您的 API key:
curl -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"}'
在 控制台 中创建和管理 API key。Key 采用 pk_live_ 前缀。
Response Header
来自 /api/* 的 response 带有两个关联 header:
| Header | Value | Description |
|---|---|---|
X-FourA-Request-Id |
UUID | 分配给该 request 的唯一 ID。在所有 response(包括 4xx 和 5xx)中返回,但 FourA 完全无法读取 body 的情况除外:400 Invalid JSON in request body 和 413 会在分配 ID 之前被拒绝。请在你的端记录此 ID。 |
X-FourA-Credits |
integer | 该 request 消耗的积分。在到达引擎的所有 response(无论是成功还是失败,均已执行处理)中返回。FourA 在引擎运行前拒绝的调用(缺少或无效 key、套餐或平台限制、被拒绝的目标或 proxy ID)不包含此项。有关哪些结果计费的详细信息,请参阅 Request Outcomes。 |
同一 request ID 对应控制台 活动日志 中的 request 和 response payload 预览(保留 24 小时,每个 key 最近 200 条),因此你可以稍后查找确切的 request,并直接从活动日志重放到 Playground。联系技术支持时附上该 ID,可在数秒内精准定位 request。
$ 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/2 200
content-type: application/json
x-foura-request-id: 8f3e2a14-7b6c-4d1a-9e2f-5a3b8c1d4e7f
x-foura-credits: 2
...
请参阅 Response Headers 获取完整列表及使用提示。
Endpoints
通过 MCP 使用这些 endpoint?
@fouradata/mcp服务端已将全部四个 endpoint 封装为原生 MCP 工具(foura_auto、foura_single、foura_proxy、foura_browser),保持相同的输入格式,并额外提供offload_large选项以优化大响应的 token 占用。
FourA 提供四个 request endpoint,分别针对不同场景进行了优化:
| Endpoint | 适用场景 |
|---|---|
POST /auto/ |
智能抓取。传入 URL 后,FourA 会选择成本最低的有效路径(直连、轮换 proxy 或浏览器),并记住每个 host 的有效方案。 |
POST /single/ |
快速 HTTP request、静态页面、API |
POST /proxy/ |
受保护站点,支持自动 proxy 轮换,可选目标可见的国家/地区定位 |
POST /browser/ |
JavaScript 渲染页面、SPA |
GET /profiles |
适用于 single 和 proxy 的浏览器配置文件目录。公开可用,无需 API key。 |
有关选型详细指南,请参阅 Choosing the Right Endpoint 以及 Smart Fetch 指南。
Target URL Restrictions
解析至私有、本地回环或保留 IP 地址段(RFC 5735、RFC 6598、IPv6 保留块)的目标会在 request 发出 FourA 前被拒绝并返回 400 错误。仅转发公共主机名和公共 IP。
{ "error": "Refusing to fetch <target>: target resolves to a private or reserved IP range. The FourA scraping API only forwards requests to public internet hosts." }
Smart Fetch (Auto)
POST /api/auto/
您传入一个 URL 以及可选的 validate 规则。FourA 按照成本感知的阶梯逐步尝试(低成本直接探测、轮换 proxy、完整浏览器),并在第一个返回符合您规则的 response 的层级停止。在对同一 host 的重复调用中,会直接重放已预热的 session,从而降低第二次请求的成本。
您无需调整重试机制、池大小或 proxy 数量。FourA 会针对每个 host 自行学习并调整。
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
url |
string | Yes | - | 目标 URL |
method |
string | No | "GET" |
HTTP method |
headers |
[string, string][] | No | - | 自定义 headers,格式为 [name, value] 键值对 |
data |
any | No | - | 非 GET 请求的 request body |
validate |
object | No | - | 成功标准,结构与 Single Request 的 validate 相同(见下文)。告知 auto 真实页面的特征,以便其区分内容页与验证质询页。 |
returnSession |
boolean | No | true |
在 response 中包含成功的 session(proxy、cookies、userAgent),以便您可以通过 /api/single/ 或 /api/browser/ 进行重放。 |
forceProxy |
boolean | No | true |
始终通过轮换 proxy 进行路由。设为 false 可在目标允许时使用更低成本的直连路径(某些防御机制对 proxy 流量更为严格)。 |
timeout_ms |
integer | No | 120000 |
整个调用的总时间预算,单位为毫秒。所有子尝试均在该预算内运行。最小值为 5000,最大值为 180000。 |
ignoreProxies |
string[] | No | - | 在每次子尝试中需避开的 Proxy ID 列表。使用之前 /api/auto/ 或 /api/proxy/ response 返回的 ID。 |
followRedirects |
integer | No | 5 |
在低成本阶梯层级上跟随重定向的最大次数。设为 0 可禁用。最大值为 20。 |
Response
{
"status": 200,
"data": "<!doctype html>...",
"headers": [{"content-type": "text/html"}],
"meta": {
"rung": "cache",
"solved": false,
"attempts": 1,
"credits": 2
},
"session": {
"proxy": "A1B2C3",
"cookies": [{"name": "session", "value": "abc", "domain": "example.com"}],
"userAgent": "Mozilla/5.0..."
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
status |
number | 目标返回的 HTTP 状态码。 |
data |
string | 无论由哪个阶梯层级提供,响应 body 均为文本。JSON 页面将作为 JSON 文本返回,需自行解析。 |
headers |
array or object | 目标响应 headers。Single 和 proxy 层级返回逐跳 header 对象数组;browser 层级返回扁平对象。 |
meta.rung |
string | 交付响应的阶梯层级。取值之一:probe(低成本直接 request)、proxy(轮换 proxy)、browser(完整 browser 渲染)、cache(重放预热会话)、warmup(先抓取站点入口页并利用其 cookie 打开深层 URL),或 fail(没有层级生成有效响应)。 |
meta.solved |
boolean | 页面是否需要额外步骤(挑战页面)且已在本次调用中完成。 |
meta.attempts |
number | 成功前进行的子尝试次数。 |
meta.credits |
number | 本次调用消耗的总积分。与 X-FourA-Credits 一致。 |
session.proxy |
string | 交付响应的 proxy 编码 ID。可在 Single 或 Browser request 中复用。当 returnSession 为 true 时存在。 |
session.cookies |
array | 成功尝试所获取的 cookie。当 returnSession 为 true 时存在。 |
session.userAgent |
string | 成功尝试所使用的 User-Agent。当 returnSession 为 true 时存在。 |
error |
string | 调用失败时的错误信息。 |
示例
curl -X POST https://eu.api.foura.ai/api/auto/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/product/42",
"validate": {"data": {"accept": ["Add to cart"]}}
}'
说明
- Auto 是一个协调器。它在内部调用 Single、Proxy 或 Browser,并将您的 API key 转发给每个子调用。Auto 调用在您的 Activity Log 和 Overview 中仅计为一次 request,消耗其子调用 credits 的总和;各子调用作为其重试尝试列于其下,绝不会单独计为独立的 request。
- 传递
validate.data.accept,填入仅真实页面包含的子字符串。若不提供,Auto 无法区分真实的 200 状态码与返回 200 状态码的验证挑战拦截页。 timeout_ms限制整个调用的最长时间。首次冷请求访问受保护站点可能需要数十秒;复用热 session 通常在 1 秒内完成。
Single Request
POST /api/single/
发送具有真实拟浏览器底层通信特征的 HTTP request,无需启动真实浏览器。这是速度最快的 endpoint。
Request Body
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
method |
string | 是 | - | HTTP 方法: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS |
url |
string | 是 | - | 目标 URL。在 URL 任意位置使用 {ts} 可插入当前时间戳以防止缓存。 |
headers |
[string, string][] | 否 | - | 自定义 headers,格式为 [name, value] 键值对 |
unblocker |
boolean | 否 | true |
发送逼真的浏览器 headers (User-Agent, Sec-Ch-Ua, Sec-Fetch-*, Accept-Encoding)。默认开启。设置为 false 可发送基础客户端特征。 |
timeout_ms |
number | 否 | 15000 | 总超时时间,单位为毫秒 (最大值: 120000) |
connect_timeout_ms |
number | 否 | 5000 | 连接超时时间,单位为毫秒 |
accept_timeout_ms |
number | 否 | 5000 | 接收超时时间,单位为毫秒 (等待连接建立的时间) |
server_response_timeout_ms |
number | 否 | 15000 | 服务器响应超时时间,单位为毫秒 (等待首字节的时间) |
dns_cache_timeout_sec |
number | 否 | 120 | DNS 缓存 TTL,单位为秒 (最大值: 240) |
followRedirects |
number | 否 | disabled | 最大重定向跟随次数 (0-20)。省略则禁用。 |
tryJsonData |
boolean | 否 | false | 若可行则将响应 body 解析为 JSON |
returnBuffer |
boolean | 否 | false | 返回原始 buffer 而非解码后的字符串 |
data |
any | 否 | - | 请求 body (字符串或对象,自动序列化为 JSON) |
proxy |
string | 否 | - | 早期响应中返回的 proxy ID,用于固定同一出口。原样传回该不透明字符串。原始 proxy 地址将被拒绝并返回 400 Invalid proxy format。某些 ID 无法被固定: 请参阅 固定出口。 |
browser |
string | 否 | Chrome | 呈现的浏览器: Chrome, Edge, Safari, Firefox 或 Tor。请参阅 Browser profiles。 |
os |
string | 否 | - | 呈现的操作系统: Windows, macOS, Android 或 iOS。系列名称可匹配其任意版本。 |
version |
string | 否 | newest | 呈现的浏览器版本,如目录中所列。存在多个匹配项时优先选择最新版本。 |
profile |
string | 否 | - | 来自 GET /api/profiles 的精确 profile id,用于替代上述三个字段。 |
validate |
object | 否 | - | 响应验证规则 (见下文) |
Browser profiles
默认情况下,请求会呈现最新的 Google Chrome。部分目标会接受某种浏览器而拒绝另一种,因此可以通过 browser、os 和 version 筛选已测量的 profile 目录,或通过 profile 按 id 直接选择。
{
"method": "GET",
"url": "https://example.com",
"browser": "Firefox",
"os": "Windows"
}
规则:
- 选择需要
unblocker(默认开启)。关闭unblocker时不会发送任何浏览器 header,因此 request 会被拒绝,而不是部分应用。 - 当有多个 profile 匹配时,以最新版本为准。
- 如果目录中不存在所请求的组合,将返回错误并说明可用选项。request 绝不会以其他浏览器身份发送。
- 相同的四个字段也可在
POST /proxy/的request对象中使用。
GET /api/profiles 返回完整目录,无需 API key:
{
"profiles": [
{ "id": "...", "browser": "Chrome", "version": "...", "os": "...", "osFamily": "macOS" }
],
"default": "..."
}
构建选择器时,使用 osFamily 的值进行过滤;os 保留发布名称以供显示。
验证规则
validate 对象用于定义成功和失败的条件。如果匹配 fail 条件,request 将被视为失败。如果设置了 accept 条件,则仅匹配的 response 会被视为成功。
{
"validate": {
"status": { "accept": [200, 201], "fail": [403, 503] },
"headers": { "accept": {"content-type": "application/json"} },
"data": { "accept": ["product"], "fail": ["captcha", "blocked"] }
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
validate.status.accept |
number[] | 接收的 HTTP 状态码 |
validate.status.fail |
number[] | 拒绝的 HTTP 状态码 |
validate.headers.accept |
object | 必须存在的 header 键值对 |
validate.headers.fail |
object | 触发失败的 header 键值对 |
validate.data.accept |
string[] | 必须出现在 response body 中的字符串 |
validate.data.fail |
string[] | response body 中触发失败的字符串 |
示例
curl -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/products",
"timeout_ms": 10000
}'
Response:
{
"status": 200,
"headers": [{"result": {"version": "HTTP/2", "code": 200, "reason": ""}, "content-type": "text/html", "server": "...", "set-cookie": ["session=abc", "tracker=xyz"]}],
"data": "<!doctype html>...",
"total_time": 0.342,
"proxy": "A1B2C3"
}
当目标在返回正文前执行 Bot 检查时,response 中还会包含一个 defense 对象,指明供应商名称以及检查是否通过:
{
"status": 200,
"data": "<!doctype html>...",
"total_time": 3.61,
"defense": {
"vendor": "sgcaptcha",
"solved": true,
"present": ["sgcaptcha"],
"ms": 3412,
"cookie": "_I_=<clearance>"
}
}
| 字段 | 类型 | 描述 |
|---|---|---|
status |
number | 来自目标的 HTTP 状态码 |
headers |
array | 每个重定向跃点一个对象。每个对象包含一个 result 字段,包含状态行以及所有 response header。多值 header (Set-Cookie, Link, WWW-Authenticate) 作为字符串数组返回。 |
data |
string/object | Response body(如果 tryJsonData 为 true 则为 JSON) |
total_time |
number | 总 request 时间(秒) |
proxy |
string | request 经过的 proxy 的编码 ID(仅在 request 中提供了 proxy 时返回)。可在后续调用中重用以固定相同的出口。 |
defense |
object | 当目标对此 request 执行了 Bot 检查,或使用网站自身的 cookie 重试生成了 body 时存在。defense.solved 表示是否通过检查,defense.retry 表示重试是否获取到了内容。查看 Site checks 获取所有字段和完整的系统列表。 |
error |
string | request 失败时的错误信息 |
Proxy Request
POST /api/proxy/
通过轮换 proxy 路由您的 request,失败时自动重试。可选择将选择范围限定在一组目标可见的出口国家/地区。
Request Body
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
request |
object | 是 | - | 单个 request body(与上方的 Single Request 字段相同) |
timeout_ms |
number | 否 | 45000 | 所有尝试的总超时时间(毫秒,最大值:120000) |
maxTries |
number | 否 | 5 | 最大 proxy 轮换尝试次数(最大值:90) |
ignoreProxies |
string[] | 否 | - | 从轮换中排除的 proxy ID(使用先前 response 返回的 ID) |
exitCountries |
string[] | 否 | - | 目标可见的双字母国家/地区代码严格允许列表(例如 ["CZ", "GB"])。值会被去除首尾空格、转为大写并去重。出口未知的 proxy 将被排除,且 request 绝不会回退到未请求的国家/地区。 |
exitClass |
string | 否 | - | standard 或 premium。premium 允许在标准池于受保护目标上面临困难时,将 request 升级至高级出口。需要包含高级出口的方案。 |
exitCountries 范围限定
筛选使用最新的可用目标可见国家/地区元数据,通常在大约十分钟内刷新。这并非 request 期间的实时地理位置查询。请勿从 proxy 主机地址推断服务国家/地区。
如果当前池中没有与所请求国家/地区匹配的项,response 将返回带有错误信封的 HTTP 200:
{
"error": "No eligible proxy found for exit countries: CZ, GB",
"code": "no_eligible_proxy",
"details": { "exitCountries": ["CZ", "GB"] },
"total": 0.084
}
保留请求的作用域并在稍后重试。仅在工作流的国家要求明确发生变更时,才修改或放宽该范围。
示例
curl -X POST https://eu.api.foura.ai/api/proxy/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"maxTries": 3,
"exitCountries": ["CZ", "GB"],
"request": {
"method": "GET",
"url": "https://example.com/prices"
}
}'
Response:
{
"status": 200,
"headers": [{"result": {"code": 200}, "content-type": "text/html", "set-cookie": ["a=1", "b=2"]}],
"data": "<!doctype html>...",
"total_time": 1.204,
"proxy": "A1B2C3",
"exitCountry": "CZ",
"total": 2.341
}
| 字段 | 类型 | 描述 |
|---|---|---|
proxy |
string | 所使用 proxy 的编码标识符。通过将其作为 proxy 字段传入,可在 Single 或 Browser request 中复用,或在下一次 Proxy request 中通过 ignoreProxies 跳过它。 |
exitCountry |
string | 处理该 request 的 proxy 对目标可见的两位字母国家/地区代码。仅在 request 设置了 exitCountries 时存在。在信任 response 之前,请务必验证它是否属于您请求的代码之一。 |
exitClass |
string | 处理此 request 的出口类别,当 request 指定了出口类别时会出现在成功的 response 中。premium 表示由高级出口返回了 body;standard 表示由标准池返回。失败的调用未处理任何内容,因此不包含 exitClass;查看其 attemptReport 可了解各次尝试遇到的情况。 |
total |
number | 外部实际耗时(秒,浮点数)。包含 proxy 选择、重试以及成功的尝试。total_time 仅表示内部 request 耗时;total 始终 >= total_time。 |
profile |
string | 轮换机制选择的 browser profile,仅在与您请求的不一致时存在。缺失表示 request 完全按原样发出。在后续调用中将该 id 作为 profile 传回,以保留有效的 browser。 |
error |
string | request 失败时的错误信息。在 scope 未命中时,code 为 no_eligible_proxy,且 details.exitCountries 会回显规范化后的 scope。 |
attemptReport |
object | 存在于每个失败的 Proxy 调用中。统计各次尝试遇到的情况,以便受限池、失效池以及从未匹配的 validate 规则不会显示为相同的错误。详见下文。 |
所有 Single Request response 字段也均包含在内,其中包括 defense:遇到 bot 拦截的 proxy 尝试会以与 Single 相同的方式进行报告。
Proxy 调用失败的原因
无论尝试过程如何,Download maxTry limit reached 的显示都相同,因此每个失败的 Proxy response 都会在错误旁附带一个 attemptReport:
{
"error": "Download maxTry limit reached",
"attemptReport": {
"total": 25,
"noResponse": 0,
"defense": 0,
"contentRejected": 25,
"statusRejected": 0,
"other": 0,
"vendors": [],
"profilesTried": ["default"],
"summary": "25 attempt(s): 25 returned HTTP 200 with no defense present and were rejected only by your validate.data - the page was fetched, your content rule did not match it"
},
"total": 34.812
}
| 字段 | 类型 | 描述 |
|---|---|---|
total |
integer | 已尝试的次数 |
noResponse |
integer | 出口未响应,因此从未连接到目标站点 |
defense |
integer | 站点已响应,并在该响应中识别出 Bot 检测 |
contentRejected |
integer | HTTP 200,无 Bot 检测,仅被您的 validate.data 拒绝 |
statusRejected |
integer | 站点已响应,无 Bot 检测,被您的 validate.status 拒绝 |
other |
integer | 已响应,且不属于上述任何情况 |
vendors |
string[] | 在任务中任意位置识别到的 Bot 检测供应商 |
profilesTried |
string[] | 任务发送的浏览器 profile,按首次使用顺序排列。default 表示您的 request 未经修改直接发出。 |
summary |
string | 根据各计数生成的一句话,可安全记录到日志 |
error 字符串保持不变,因此基于此进行匹配的客户端可以继续正常工作。针对各项计数的处理方法请参见 Why a Proxy Request Ran Out of Tries。
exitClass
无论尝试多少次,某些目标站点都会拒绝标准池中的出口。exitClass: premium 告知 Proxy,除标准池外,还可以将此类 request 升级到 premium exit,而不是仅在标准池内轮换。
{
"exitClass": "premium",
"request": { "method": "GET", "url": "https://example.com/report" }
}
在发送之前,有三点值得了解。
这是一种配额许可,而非硬性指令。 标准池仍会竞速响应,且通常会胜出。只有当标准池在该 request 上消耗了短暂的预算配额,或目标明确拒绝时,高级出口才会介入。在尝试任何高级出口之前由标准池响应的 request 属于正常成功,不会消耗您的 premium 流量。一旦尝试了高级出口,其流量即计入消耗,详情如下所述。
response 会明确说明实际提供服务的节点。 当您指定一个类别时,response 会返回 exitClass:
{
"status": 200,
"exitClass": "premium",
"proxy": "Y2QXVK",
"data": "..."
}
premium 表示响应体由高级出口返回。standard 表示由标准池返回。当无法获取高级出口,或者您套餐内包含的高级流量(加上额外购买的流量)在当前计费周期内已用尽时,也会返回该值。这两种情况都不是错误,您可以按请求核对高级流量,而无需仅依赖月度数据。相同的值会在 X-FourA-Exit-Class 响应 header 中传递(参见 Response Headers)。
高级流量按网络传输量计量。 高级尝试会统计其在网络中发送和接收的字节数(包含传输过程中的压缩和加密大小),无论是否成功返回页面。当另一个出口已返回响应时,仍在运行的尝试会立即停止且不计入流量。高级流量计入您的高级配额,同时也包含在总带宽内:同一批字节会分别呈现在两项统计中,但绝不会重复相加。当高级出口交付页面时,其流量即为该请求的全部流量,因此该页面不会作为标准流量再次计费。您的 Usage & Limits 页面会显示总流量、其中的高级流量占比以及用于计量的可用高级配额。
省略该字段并不等同于发送 standard。省略表示不作明确设定;发送 standard 则明确声明此请求绝不升级,这是完全避免特定任务使用高级流量的方法。
配额用尽不是错误。 配额用尽后,指定 premium 的请求仍会继续工作:由标准池提供服务,且响应显示 standard。任务不会因配额用尽而中断。
exitClass: premium 需要包含高级出口的套餐。在不包含高级出口的套餐中,请求绝不会消耗高级出口:它要么被拒绝并返回携带 X-FourA-Limit: plan_limit_premium 的 403 错误(参见 Rate Limits),要么由标准池处理并在响应中返回 exitClass: standard。请对这两种情况都进行处理。
Browser Profile Rotation
Proxy 会轮换出口。当目标网站拒绝 FourA 提供的浏览器特征而不是出口 IP 时,Proxy 还会切换到目录中的另一个浏览器系列。这不会增加尝试次数:轮换只会改变重试时发送的内容,绝不会影响是否发生重试。
Proxy 还会暂时记录目标网站最近接受的浏览器系列,以便随后对同一网站的调用可以直接使用该系列,而不是默认系列。与轮换选择的任何系列一样,响应会在 profile 中标明该系列名称。
在内部 request 上显式指定的 profile、browser、os 或 version 绝不会被覆盖;携带自身 User-Agent 或 Cookie header 的请求也不会被覆盖,因为验证凭证与其获取时所用的签名绑定。
Browser Request
POST /api/browser/
在 Chrome 浏览器实例中打开您的 URL。页面加载并执行 JavaScript 后,您将获得完整渲染的 HTML 以及 cookie 存储区。
请求体
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
url |
string | 是 | - | 目标 URL |
headers |
object | 否 | - | 自定义 header,格式为键值对 |
cookies |
array | 否 | - | 要设置的 cookie:[{name, value, domain?}] |
userAgent |
string | 否 | - | 自定义 User-Agent 字符串 |
unblocker |
boolean | 否 | true |
完成页面加载前要求的验证(质询页面或类似拦截)。默认开启。设置为 false 可按原样渲染页面返回的任何内容,包括质询页面。 |
proxy |
string | 否 | - | 来自先前 response 的 proxy ID,用于固定同一出口。请原样传回该不透明字符串。传入原始 proxy 地址将被拒绝并返回 400 Invalid proxy format。 |
exitCountry |
string | 否 | - | request 出口国家的两位国家代码 (ISO 3166-1 alpha-2)。将浏览器时钟设置为匹配的时区。请参阅 将浏览器时钟与出口匹配。 |
timeout_ms |
number | 否 | 30000 | 页面加载超时时间(毫秒,最大值:120000) |
checkStatus |
number | 否 | - | 预期的 HTTP 状态码(不符合则 request 失败) |
checkText |
string | 否 | - | 渲染页面中必须包含的文本 |
将浏览器时钟与出口匹配
页面可以读取浏览器的时区,并将其与检测到的 IP 归属国进行比对。时区不匹配是 Bot 检测程序成本最低的识别信号之一,而消除该信号无需任何额外成本。
将 exitCountry 设置为流量出口的国家,浏览器便会报告对应的时区:
{
"url": "https://example.com",
"proxy": "A1B2C3",
"exitCountry": "BR"
}
规则:
- 该值为出口国家/地区,即目标网站看到的国家/地区,而不是 proxy 所在的位置。两者经常不一致,这一点至关重要。
- 省略此项时,FourA 会在已知出口国家/地区时使用它,否则保持浏览器时钟不变,而不是随意猜测。
- 无法识别的国家/地区代码会被视为省略该字段。这不会报错。
- 仅时钟会跟随国家/地区调整。
Accept-Language以及网站提供的内容不受影响,因此页面不会自动切换语言。
userAgent 参数
发送 userAgent 后,页面、其 Worker 以及目标端看到的都将是这个完全相同的字符串。FourA 还会据此生成匹配的 Client Hints(sec-ch-ua、sec-ch-ua-platform、navigator.platform 以及检测程序按名称请求的高熵值),确保 request 不会在 header 中声明一种浏览器而在 JavaScript 中声明另一种。
response 中的 userAgent 即为实际呈现的值。这在重放 clearance 时尤为重要:cf_clearance cookie 会绑定到获取它时的出口和 User-Agent,因此请回传 response 中报告的字符串,而不是你以为使用的字符串。请参阅 Site checks。
发送非 Chromium 字符串(例如 Firefox User-Agent)时,它会按原样呈现,不附加 Chromium 品牌列表。
示例
curl -X POST https://eu.api.foura.ai/api/browser/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/spa-app",
"timeout_ms": 15000,
"checkText": "product-list"
}'
Response:
{
"status": 200,
"headers": {"content-type": "text/html"},
"body": "<!doctype html>...",
"cookies": [{"name": "session", "value": "abc123", "domain": "example.com", "path": "/", "expires": 1735689600, "httpOnly": true, "secure": true, "sameSite": "Lax"}],
"userAgent": "Mozilla/5.0...",
"defenseSolved": true,
"defenses": {"present": ["cloudflare"], "cleared": ["cloudflare"]},
"proxy": "A1B2C3"
}
| 字段 | 类型 | 说明 |
|---|---|---|
status |
number | 目标返回的 HTTP 状态码 |
headers |
object | 响应 headers |
body |
string or object | 完整渲染的页面内容。当 content-type 为 HTML 时为 HTML 字符串;当页面返回 JSON 并被自动解析时为 object。 |
cookies |
array | 来自页面的完整 cookie 对象。每个 cookie 包含 name、value、domain、path、expires、httpOnly、secure、sameSite 以及其他 cookie 属性。 |
userAgent |
string | 所使用的浏览器 User-Agent |
defenseSolved |
boolean | 若在此次调用中遇到并真正通过了 Bot 防护,则为 true。否则不存在。用于决定该调用消耗 5 还是 10 个 credits。 |
defenses |
object | present 列出页面加载过程中识别出的所有供应商,cleared 列出最终页面已获得放行的供应商。供应商可能出现在 present 中但从未出现在 cleared 中。参见 站点检查。 |
proxy |
string | 请求所经过代理的编码 ID(仅当请求中提供了 proxy 时)。在后续调用中重复使用它以保持相同的出口。 |
error |
string | 请求失败时的错误信息 |
固定出口
在 Single 或 Browser 请求中传入 proxy 值可固定先前调用所使用的出口。原样传回不透明 ID,切勿传入 proxy 地址。
以下三种值会被拒绝,均返回 400 状态码:
| 错误 | 含义 |
|---|---|
Invalid proxy format |
该值不是 FourA 签发的 ID。直接传入原始 proxy 地址会触发此错误。 |
Proxy not found |
ID 已成功解码,但不再指向活动的出口。请通过新调用获取新 ID。 |
Managed exit: this proxy id cannot be pinned to a request |
出口存在,但 FourA 不会为指定请求保持开启。当套餐中的高级流量耗尽时,高级出口的 ID 会触发此错误。请复用返回它的会话,或通过 POST /api/proxy/ 发起调用并接受其自动选择的出口。 |
固定的高级出口按高级流量计费。响应中包含 X-FourA-Exit-Class: premium,以便你查看单次请求的用量。无论目标站点是否返回了预期页面,该出口消耗的流量均会计入 用量与限额 页面中的高级流量以及总带宽。固定出口需要套餐支持高级出口且尚有可用额度;否则 ID 将被拒绝并返回上述 managed-exit 400 错误。
HTTP 状态码
| 状态码 | 含义 |
|---|---|
| 200 | 请求已完成(检查内部 status 获取目标 response) |
| 400 | 无效的 request body、参数、目标 IP 属于私有/保留地址范围,或 proxy ID 无法固定 |
| 401 | 缺少 API key 或 API key 无效 |
| 403 | 该 endpoint 或参数不在您的套餐计划中。X-FourA-Limit 会指明具体项:plan_limit_feature 或 plan_limit_premium。 |
| 404 | Not Found:该路径下不存在 endpoint。 |
| 413 | JSON request body 超过 100 KB。返回内容非 JSON 且不包含 X-FourA-Request-Id。 |
| 429 | 套餐配额限制(已设置 X-FourA-Limit)或平台的每分钟共享配额超限(无 header) |
| 500 | 内部服务器错误 |
| 502 | Upstream unavailable。FourA 已连接到引擎,但返回内容不可用。请重试。 |
| 503 | 服务暂时不可用或已满载,或在引擎重启期间返回 Backend service unavailable |
| 504 | Upstream timeout。引擎未能在该 request 的时间预算内完成。请调高 timeout_ms 或重试。 |
后续步骤
- Smart Fetch (Auto):何时让 FourA 自动选择路径
- 选择合适的 Endpoint:何时手动选择 Single、Proxy 或 Browser
- 身份验证:管理您的 API key
- 错误处理:从容处理各类错误
- 站点检查:读取
defense字段并重放 clearance - Proxy 请求耗尽重试次数的原因:读取
attemptReport并采取相应措施 - Rate Limit:了解 request 限制
- 快速入门:30 秒内发送您的第一个 request