常见问题
使用 FourA API 时的常见问题解决方案。
内容为空或不完整
现象: API 返回 200 状态码,但 data 字段为空或缺少预期内容。
原因: 目标页面在初始页面加载后使用 JavaScript 渲染内容。
解决方案: 从单请求 endpoint 切换到 browser endpoint。使用 checkText 验证内容是否已加载:
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/products",
"timeout_ms": 15000,
"checkText": "product-list"
}'
注意:browser endpoint 在 body 字段中返回内容(而非 data)。
403 Forbidden 或验证页面
现象: API 返回包含验证页面或访问拒绝页面的 HTML。
原因: 目标网站检测到该 request 为自动化请求并进行了拦截。
解决方案: 使用 proxy endpoint 进行自动 IP 轮换:
curl -X POST https://eu.api.foura.ai/api/proxy/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"maxTries": 5,
"request": {
"method": "GET",
"url": "https://example.com/prices",
"unblocker": true
}
}'
如果问题仍然存在,请增加 maxTries 以便为 proxy 轮换提供更多重试次数。
目标返回的 403 会作为 HTTP 200 返回,并在 body 内包含 status: 403。调用本身的 403(带有 X-FourA-Limit header)则属于不同情况:请参阅 403 Not in Your Plan。
Timeout Errors
症状: request 因超时错误而失败。
原因: 目标页面加载时间超过了配置的超时时间。
解决方案: 增加 timeout_ms(默认单次请求为 15s,browser 为 30s,proxy 为 45s):
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://slow-site.com",
"timeout_ms": 60000
}'
对于浏览器 request,还需要验证 checkText 值是否确实出现在页面上。拼写错误会导致调用失败并返回 checkText:<your text> not found。
403 Not in Your Plan
**症状:**API 返回 403,并带有 X-FourA-Limit header 以及值为 plan_limit_feature 或 plan_limit_premium 的 reason。
{
"error": "Geo targeting (the exitCountries parameter) is not included in your plan (Free). Remove the parameter or upgrade.",
"reason": "plan_limit_feature",
"documentation": "https://foura.ai/prices"
}
原因: 您的套餐不包含调用的 endpoint 或传入的 parameter。plan_limit_feature 对应未包含的 endpoint 以及未包含地理定位功能的 exitCountries;plan_limit_premium 对应未包含高级出口的 exitClass: premium。请求未连接至目标,未产生任何扣费。
解决方案: 移除该 parameter,调用套餐内包含的 endpoint,或升级套餐。Usage & Limits 的 Limits & Features 标签页列出了套餐包含的功能。请勿在未作修改的情况下重试:由于等待不会改变结果,因此未设置 Retry-After。
429 Too Many Requests
现象: API 返回 429。
原因: 两种检查机制之一拒绝了调用,response 会指出具体原因。若包含 X-FourA-Limit header,则表明达到了套餐的某项限制:该 endpoint 的并发 request 数或每分钟 request 数、当天的 Browser request 数,或者计费周期的 credit 或带宽。若无此 header,则表明平台该服务每分钟的共享配额已满,这与 FourA 整体流量有关,而非您的个人流量。
解决方案: 首先读取 X-FourA-Limit。如果限制仅需等待数秒,请等待;否则请停止请求。可通过等待解除的套餐限制会将秒数填入 Retry-After header 和 retry_after_seconds 中;共享限制则会将秒数填入 retryAfter:
import time
import requests
# Plan limits that come back in hours or days, not seconds.
STOP_ON = {"plan_limit_browser_daily", "plan_limit_credits", "plan_limit_bandwidth"}
def make_request(endpoint_url, payload, retries=3):
for i in range(retries):
resp = requests.post(
endpoint_url,
headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
json=payload
)
if resp.status_code == 429:
limit = resp.headers.get("X-FourA-Limit")
if limit in STOP_ON:
raise Exception(f"stopped by {limit}: {resp.json().get('error')}")
header = resp.headers.get("Retry-After")
body = resp.json()
wait = (
int(header) if header and header.isdigit()
else body.get("retry_after_seconds") or body.get("retryAfter") or 2 ** i
)
time.sleep(wait)
continue
return resp
raise Exception("Rate limit not resolved after retries")
# Example: single request
make_request(
"https://eu.api.foura.ai/api/single/",
{"method": "GET", "url": "https://example.com"}
)
如果 header 显示为 plan_limit_concurrency 或 plan_limit_rate,解决方法是限制保持打开的调用数量以及每分钟发起的调用数量,而不是更频繁地重试。立即重新发送被拒绝的批次会导致整个批次再次被拒绝。被拒绝的调用不会计入您的每分钟限制,但如果它们的到达速率持续超过该限制的两倍,拒绝就会转变为冷却期:429 body 会携带 cooldown: true 并要求您暂停 30 秒 (retry_after_seconds: 30)。并行运行请求 提供了相关模式,控制台 中的 Usage & Limits 会在上限旁显示您的实时计数器。
503 Service Unavailable
症状: API 返回 503 状态。
原因: 这会在以下两种情况下发生:
- 服务达到容量上限。 FourA 在该引擎上同时运行的请求数已达允许的最大值(计算的是所有流量,而不仅仅是您的流量)。
error字段中为Service at capacity。通常会在几秒钟内恢复。 - 服务暂时禁用。 正在进行维护。
error字段中为Service disabled。
两种情况都会在响应中包含 retryAfter 字段。两者都不属于套餐限制:您自身套餐的限制始终会在 403 或 429 上通过 X-FourA-Limit header 响应,绝不会返回 503。
解决方案: 等待 retryAfter 秒,然后重试:
import time
import requests
def make_request_with_retry(endpoint_url, payload, retries=3):
for i in range(retries):
resp = requests.post(
endpoint_url,
headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
json=payload
)
if resp.status_code in (429, 503):
header = resp.headers.get("Retry-After")
body = resp.json()
wait = (
int(header) if header and header.isdigit()
else body.get("retry_after_seconds") or body.get("retryAfter") or 2 ** i
)
time.sleep(wait)
continue
return resp
raise Exception("Request not resolved after retries")
503 容量不足表示 FourA 正处于繁忙状态,退避并重试即可解决。如果您收到 429 拒绝响应以及 X-FourA-Limit,则是由于您的原因导致:请减少流水线中的并发 request 数量。
504 Upstream Timeout
症状: API 返回 504 及 {"error": "Upstream timeout"}。
原因: 任务未在您为 request 声明的时间预算内完成。目标站点响应缓慢、冷启动验证挑战求解或页面过大都会导致此问题。这不是您的 key、参数或 proxy 的问题。
解决方案: 为调用预留更多时间,或重试。FourA 会等待您设定的 timeout_ms 加上一小段缓冲时间,因此调高该值能真正延长等待时间:
{
"url": "https://slow-site.com/report",
"timeout_ms": 90000
}
对于受保护目标上的 /api/auto/,首次冷调用的耗时可能达到数十秒。其 timeout_ms 覆盖整个梯度重试流程,最大支持 180000。
当 /api/auto/ 自身耗尽该配额时,调用仍会返回 HTTP 200。响应体包含以 time budget exhausted 开头的 error,且 status 通常为 504(较早失败的尝试可能会在此处保留其自身状态)。请调高 timeout_ms 或重试。
502 Upstream Unavailable
症状: API 返回 502 并附带 {"error": "Upstream unavailable"},或返回 503 并附带 {"error": "Backend service unavailable"}。
原因: FourA 已连接到自身引擎,但无法使用该响应,通常是因为实例正在重启。
解决方案: 设置简短的退避时间后重试。两者均归类为 service_error,且系统仅对 success 计费,因此重试不会产生额外费用。如果问题持续超过一两分钟,请查看 状态页。
401 认证错误
症状: 所有请求均返回 401 Unauthorized。
排查清单:
- 确认请求头为
X-API-Key: YOUR_API_KEY(而非Authorization: Bearer或Api-Key) - 检查 API 密钥中是否存在多余的空格或换行符
- 如果当前密钥可能已泄露,请在 控制台中创建新密钥
400 目标解析为私有或保留 IP
症状: 请求离开 FourA 之前,API 返回 400 并附带 Refusing to fetch <target>: target resolves to a private or reserved IP range。
原因: 您的 url 解析为私有、环回或保留 IP 地址段(RFC 5735、RFC 6598 或 IPv6 保留网段)。FourA 会拒绝此类目标,以防止其网络被用于访问内部主机。
解决方案: 请求公共 URL。如果处于测试阶段,请使用公开目标(如 https://example.com 或 https://httpbin.org/get)。如果您计划访问的目标是由您运行的服务,请先将其公开在公共主机名下。
{ "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." }
无法解析的主机名不会被直接拒绝。该调用会返回 HTTP 200 以及 status: 0 和原因 (could not resolve <host>: <reason>),就像 FourA 无法访问的任何目标一样,并且不会计费。
使用 exitCountries 时的 no_eligible_proxy
**症状:**带有 exitCountries 的 /api/proxy/ 调用返回 HTTP 200 以及 JSON 错误封装包:
{
"error": "No eligible proxy found for exit countries: CZ, GB",
"code": "no_eligible_proxy",
"details": { "exitCountries": ["CZ", "GB"] },
"total": 0.084
}
原因: 当前 proxy 池中没有对目标可见国家/地区匹配您白名单的可用出口。当您设置 exitCountries 时,FourA 绝不会回退到未请求的国家/地区。
解决方案: 保留请求的作用域并在稍后重试。proxy 池大约每十分钟刷新一次,因此当前无匹配的国家/地区通常会在一小时内获得可用出口。
import time, requests
def fetch_scoped(url, countries, max_attempts=6, wait_sec=600):
for _ in range(max_attempts):
r = requests.post("https://eu.api.foura.ai/api/proxy/",
headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
json={"maxTries": 5, "exitCountries": countries,
"request": {"method": "GET", "url": url}}).json()
if r.get("code") == "no_eligible_proxy":
time.sleep(wait_sec)
continue
return r
raise RuntimeError(f"no eligible exit in {countries} after {max_attempts} attempts")
仅在工作流的国家/地区要求确实发生变更时才放宽国家列表。静默回退到其他国家可能会破坏下游依赖于地理位置的逻辑。
Response Body 返回为乱码
现象: 当目标站点使用非 UTF-8 字符集时,响应 data(或 body)包含乱码或无法读取的字符。
原因: FourA 默认根据目标的 Content-Type header 或 HTML <meta charset> 标签将 response body 自动解码为 UTF-8。如果目标声明的字符集有误,就会导致乱码。
解决方案: 对于二进制载荷(图像、protobuf、原始音频),请在 request 中设置 returnBuffer: true。Single 和 Proxy 随后会将 data 作为包含原始字节的对象返回,{"type": "Buffer", "data": [<byte values>]},且不进行任何字符集转码。
{
"method": "GET",
"url": "https://example.com/image.png",
"returnBuffer": true
}
对于错误声明字符集的文本目标,请自行解码原始字节:使用 returnBuffer: true 进行抓取,读取 data.data 中的字节值,然后使用正确的字符集对其进行解码。
收到 HTML 而非预期的 JSON
症状: 您预期从目标站点获取 JSON,但收到了 HTML。
原因: 目标页面可能会根据请求 header 返回不同的内容。
解决方案: 添加 Accept header 并启用 unblocker 以生成真实的浏览器 header:
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://api.example.com/data",
"headers": [["Accept", "application/json"]],
"unblocker": true
}'
你也可以将 tryJsonData 设置为 true,让 FourA 自动解析 JSON 响应。
Body 是质询页面而非目标内容
现象: 调用成功,status 为 200,但 data(或 body)是 Bot 验证拦截页而非所需页面。
原因: 目标站点触发了 Bot 验证,FourA 遇到了该验证但未能通过。响应中会明确标注:Single 和 Proxy 会返回带有 solved: false 的 defense,Browser 会返回 defenseSolved: false 并在 defenses.present 中注明厂商。
解决方案: 首先检查 defense.vendor,然后逐步升级策略。尝试在 Single 上更换浏览器 Profile,升级到 Proxy 使用不同出口,或使用 Browser 运行 JavaScript。完整字段参考和厂商列表:站点验证。
添加仅真实页面包含的 validate.data.accept 子字符串。FourA 识别出的验证页面绝不会被视为成功:它会返回 X-FourA-Check-Page 响应头且不计费。若不使用 validate,FourA 未能识别且返回 HTTP 200 的验证页面将被视为成功请求,导致你只能在下游流程中发现问题而非在调用时即刻捕获。
仍未解决?
如果上述方案均无效:
- 查看 状态页 确认是否有进行中的突发事件
- 在 控制台 中查看你的 request 指标
- 发送邮件至 support@foura.ai 联系支持团队并附上 request 详情(请包含失败响应中的
X-FourA-Request-Id)
后续步骤
- 错误处理:API 错误代码参考
- Rate Limits:所有套餐限制与平台限制及相关字段
- Request 结果:结果分类说明
- 站点验证:
defense字段的含义解析 - 选择合适的 Endpoint:为你的目标站点挑选最佳方案
- 控制台概览:监控你的 request