快速回答
哪些 SERP API 错误应该重试,失败的搜索会收费吗?
SerpCrypto 从不对错误收费:只有成功的搜索才消耗 1 积分。对 429 concurrency_limit、502 search_failed 和 504 search_timeout 用指数退避重试。不要重试 400、401 或 402:先修好参数、API 密钥或余额。积分价格低至 US$0.30/千次搜索,且永不过期;加密货币支付,无需 KYC。
每个错误码是什么意思?
本表没有任何一行会消耗积分。1 积分 = 1 次成功的查询请求,可在任意支持的引擎上返回一页结果。失败的请求不计费。
| HTTP | code | 原因 | 如何处理 | 是否重试? |
|---|---|---|---|---|
| 400 | invalid_parameter | 缺少 q,或有值不在允许的列表内 | 修正请求;错误信息会指明是哪个参数 | 否 |
| 401 | invalid_api_key | 没有密钥、密钥拼写错误或密钥已被吊销 | 检查请求头或 api_key;如有需要,新建一个密钥 | 否 |
| 402 | insufficient_credits | 账户积分为 0 | 用余额购买积分包 | 购买后 |
| 429 | concurrency_limit | 同时发起的查询数超过账户允许的上限 | 等待、降低并发数,或联系支持申请更高的上限 | 可以,配合退避重试 |
| 502 | search_failed | 该请求对应的引擎或集合失败 | 重试同一个请求 | 可以,配合退避重试 |
| 504 | search_timeout | 未能在规定时间内返回结果 | 重试同一个请求 | 可以,配合退避重试 |
错误响应长什么样?
每个错误都返回同样精简的 JSON 响应体,带有稳定的 code 和面向人阅读的 message。在你的程序中根据 code 分支处理,并把 message 记录到日志供人查看。HTTP 状态码与上表一致。
{
"error": {
"code": "insufficient_credits",
"message": "Your account has no search credits left."
}
}为什么我会收到 400 invalid_parameter?
某个必填值缺失,或有值不在 API 接受的列表内。常见原因包括 q 为空、引擎名拼错(例如把 google_news 写成 google-news)、page 大于 10,或 device 不是 desktop 或 mobile。
message 会指明出错的参数。把请求与 API 参考 对照一下;不会扣费,所以你可以立即修正后重新发送。
为什么我会收到 401 invalid_api_key?
密钥没有送达 API,或密钥无效。检查请求头是否恰好是 Authorization: Bearer YOUR_KEY,Bearer 后面有一个空格。还要检查运行代码的 shell 或服务中是否设置了环境变量,而不只是在你自己的终端里设置。已吊销的密钥会持续失败:请在控制台中新建一个。
收到 402 insufficient_credits 该怎么办?
用余额购买积分包,然后重新发送。如果余额太低,先用加密货币充值;最低充值金额为 US$25。在执行大型任务前,先从 GET https://serpcrypto.com/api/v1/credits 读取 credits_remaining,以免中途停止:该调用免费。
如何处理 429 concurrency_limit?
降低速度,而不是直接停下。该限制统计的是同时运行的查询数,而不是每天的查询数。每个账户可同时运行固定数量的查询;该限制显示在你的 dashboard 中,并可按需提高。从积分 endpoint 读取 concurrency_limit 并据此设置你的 worker 池大小;Python 和 Node.js 页面展示的池永远不会超过该限制。
502 和 504 在什么时候返回?
502 search_failed 表示该请求的查询未能完成;504 search_timeout 表示未在规定时间内完成。两者都免费,也都值得重试。每次新的尝试前多等一会儿,就像下面的代码那样,并在五次尝试后放弃,以免卡住的任务无限循环。
import os
import random
import time
import requests
API_URL = "https://serpcrypto.com/api/v1/search"
RETRYABLE = {429, 502, 504}
def search(params, max_attempts=5):
headers = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}
for attempt in range(1, max_attempts + 1):
r = requests.get(API_URL, params=params, headers=headers, timeout=90)
if r.status_code == 200:
return r.json()
error = r.json().get("error", {})
if r.status_code not in RETRYABLE or attempt == max_attempts:
raise RuntimeError(f"{r.status_code} {error.get('code')}: {error.get('message')}")
# exponential backoff with jitter: about 1 s, 2 s, 4 s, 8 s
time.sleep(2 ** (attempt - 1) + random.random())
raise RuntimeError("unreachable")
print(search({"q": "solar panel installers", "gl": "au", "hl": "en"})["search_metadata"])// retry.mjs — Node.js 18+
const API_URL = "https://serpcrypto.com/api/v1/search";
const RETRYABLE = new Set([429, 502, 504]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export async function search(params, maxAttempts = 5) {
const url = `${API_URL}?${new URLSearchParams(params)}`;
const headers = { Authorization: `Bearer ${process.env.SERPCRYPTO_API_KEY}` };
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fetch(url, { headers });
if (res.ok) return res.json();
const body = await res.json().catch(() => ({}));
const code = body.error?.code ?? "unknown";
if (!RETRYABLE.has(res.status) || attempt === maxAttempts) {
throw new Error(`${res.status} ${code}: ${body.error?.message ?? ""}`);
}
// exponential backoff with jitter: about 1 s, 2 s, 4 s, 8 s
await sleep(1000 * 2 ** (attempt - 1) + Math.random() * 1000);
}
throw new Error("unreachable");
}
console.log((await search({ q: "solar panel installers", gl: "au", hl: "en" })).search_metadata);我的 HTTP 超时应该设短还是设长?
要足够长,让查询能够完成:查询是实时执行的,所以把客户端超时设为 60 到 90 秒,而不是几秒。客户端过早放弃会在第一个请求仍在运行时发出第二个请求,这会浪费一个并发槽位;如果两个都成功,还会消耗两个积分。
错误相关疑问
如果我的程序在读取答案之前崩溃了,搜索还会被收费吗?
会,如果 API 完成了搜索并返回 200:积分在搜索成功时就被扣除,而不是在你读取结果时。这也是设置较长客户端超时的另一个原因。
重试会额外收费吗?
只有成功的那次尝试才会消耗积分。以 429、502 或 504 失败的尝试免费,因此第三次才成功的请求总共只花费 1 个积分。
反复出现的错误应该在哪里报告?
请写信至 [email protected],附上成功搜索的 search_metadata.id,或失败搜索的时间、引擎和参数。电子邮件回复在 12 小时内,每周 7 天,包括 API 集成方面的帮助。