无需 KYC — 无需 ID、无需自拍、无需文件。使用加密货币支付:BTC, USDT, USDC, ETH, SOL, LTC
语言: 简体中文
获取 API 密钥

文档 · 错误 · API v1

SERP API 错误:错误码、原因、修复和重试

六个错误码,一条规则:错误永不消耗积分。本页说明每个错误码的触发条件、是否需要重试,并提供 Python 和 Node.js 中带指数退避的重试代码。

最后更新:

快速回答

哪些 SERP API 错误应该重试,失败的搜索会收费吗?

SerpCrypto 从不对错误收费:只有成功的搜索才消耗 1 积分。对 429 concurrency_limit、502 search_failed 和 504 search_timeout 用指数退避重试。不要重试 400、401 或 402:先修好参数、API 密钥或余额。积分价格低至 US$0.30/千次搜索,且永不过期;加密货币支付,无需 KYC。

每个错误码是什么意思?

本表没有任何一行会消耗积分。1 积分 = 1 次成功的查询请求,可在任意支持的引擎上返回一页结果。失败的请求不计费。

HTTPcode原因如何处理是否重试?
400invalid_parameter缺少 q,或有值不在允许的列表内修正请求;错误信息会指明是哪个参数否
401invalid_api_key没有密钥、密钥拼写错误或密钥已被吊销检查请求头或 api_key;如有需要,新建一个密钥否
402insufficient_credits账户积分为 0用余额购买积分包购买后
429concurrency_limit同时发起的查询数超过账户允许的上限等待、降低并发数,或联系支持申请更高的上限可以,配合退避重试
502search_failed该请求对应的引擎或集合失败重试同一个请求可以,配合退避重试
504search_timeout未能在规定时间内返回结果重试同一个请求可以,配合退避重试

错误响应长什么样?

每个错误都返回同样精简的 JSON 响应体,带有稳定的 code 和面向人阅读的 message。在你的程序中根据 code 分支处理,并把 message 记录到日志供人查看。HTTP 状态码与上表一致。

402 响应的响应体
{
  "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 表示未在规定时间内完成。两者都免费,也都值得重试。每次新的尝试前多等一会儿,就像下面的代码那样,并在五次尝试后放弃,以免卡住的任务无限循环。

Python:对 429、502 和 504 使用指数退避重试
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"])
Node.js:用 fetch 实现同样的逻辑
// 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 集成方面的帮助。

起价 US$0.30/千次搜索 · 无需 KYC

获取 API 密钥