PAYATHON 2026

Custom Search JSON API 已启用计费仍返回 403,如何排查?

数据阿明

先确认 API 的接入资格。启用 Custom Search JSON API、开通计费并创建 API Key,都不代表项目一定能够使用这项服务。Google 当前的官方文档说明:Custom Search JSON API 已停止向新客户开放,现有客户需要在 2027 年 1 月 1 日前迁移到其他方案。官方说明

如果这两个项目属于新接入场景,应优先核实是否受到访问资格限制。不过,仅凭这段 403 响应,还无法确定 Google 对这两个项目的具体资格判定。

为什么启用 API 和计费后仍然报错?

错误中最关键的信息是:

This project does not have access to Custom Search JSON API

它指向项目对该服务的访问权限。排查时要区分以下条件:

  • API 已启用:项目配置中开启了该服务。
  • 计费已开通:项目具备计费配置。
  • API Key 无限制:密钥没有设置应用或 API 使用限制。
  • 服务访问资格:服务是否允许该客户或项目接入。

即使前三个条件都满足,也不能由此认定项目具备服务访问资格。如果问题确实是服务停止向新客户开放导致的,继续创建项目或重新生成密钥也无法解决资格问题。

已有 Google 账号、已有搜索引擎或较早创建的 Cloud 项目,都不足以单独证明你属于官方所说的现有 Custom Search JSON API 客户。当前材料也没有提供这方面的历史调用证据。

为什么 APIs Explorer 使用 OAuth 可以成功?

OAuth 测试成功,说明那次请求在所用凭据和调用环境下能够执行,也为 Search Engine ID 可用提供了依据。但这不能直接证明代码中 API Key 所属的项目具有相同访问资格。

Google 文档说明,标准 API Key 会把请求关联到一个项目,用于计费和配额归属。API Key 说明

需要对照 APIs Explorer 实际发出的请求,检查以下内容:

  1. 请求是否使用同一个 cx 和相同查询参数。
  2. 请求是否同时携带了 API Key,以及它是否与代码中的密钥相同。
  3. 是否包含 Authorization: Bearer ... 等 OAuth 凭据。
  4. 能否确认两次请求使用了相同的消费项目。

原始材料没有提供 Explorer 的完整请求,因此无法断言它使用了哪个项目。OAuth 测试成功也不能证明 API Key 调用应当成功,更不能保证改用 OAuth 就能绕过服务限制。

按什么顺序排查?

1. 核对实际运行的密钥及其所属项目

在 Google Cloud Console 的凭据页面找到代码实际使用的 API Key,确认它属于哪个项目,再核对该项目的 API 和计费状态。

如果密钥通过环境变量或部署配置传入,还要检查运行环境是否仍在使用旧值。不要只检查控制台当前选中的项目,也不要公开完整密钥。

2. 检查是否存在历史成功调用

如果此前有项目通过 API Key 成功调用过 Custom Search JSON API,先检查该项目的历史使用记录,再用它自己的密钥做对照测试。

如果两个项目都是本次新建的,而且没有任何历史成功调用,应先核实接入资格。当前文档已明确停止向新客户开放,不宜把排查重点放在反复开通计费或重建密钥上。

3. 保留完整错误响应

原来的请求使用了 key、cx 和 q,现有材料没有显示出需要修改参数拼写的问题。可以先完善错误处理,获取更多诊断信息。

下面的示例沿用已有的 API_KEY 和 SEARCH_ENGINE_ID 变量,需要在支持 fetch 的环境中运行:

async function testCustomSearch() {
  const url = new URL('https://www.googleapis.com/customsearch/v1');
  url.search = new URLSearchParams({
    key: API_KEY,
    cx: SEARCH_ENGINE_ID,
    q: 'test'
  }).toString();

  const response = await fetch(url, { method: 'GET' });
  const data = await response.json();

  if (!response.ok) {
    console.error('HTTP status:', response.status);
    console.error('API error:', JSON.stringify(data, null, 2));
    throw new Error(data.error?.message ?? `HTTP ${response.status}`);
  }

  return data;
}

try {
  const data = await testCustomSearch();
  console.log(data);
} catch (error) {
  console.error(error.message);
}

fetch 收到 HTTP 403 时通常仍会返回 Response,因此需要检查 response.ok。这段代码用于收集错误信息,不会改变项目的访问权限。

如果响应中包含 error.status、error.errors 或 error.details,应一并保留。不要仅凭 HTTP 403 就认定原因是配额、计费或密钥限制,也不要记录包含完整 API Key 的请求 URL。

4. 历史可用项目仍失败时,提交资格核查

如果同一个项目此前用同一种 API Key 调用方式成功过,现在却持续返回这条错误,可以向 Google 支持渠道提供:

  • 项目 ID 和项目编号。
  • 历史成功调用及本次失败的大致时间。
  • 完整错误响应。
  • API 启用状态、计费状态及密钥所属项目。
  • APIs Explorer 与应用请求在凭据方面的差异。

这些信息有助于核查项目的具体访问状态。是否能够恢复访问,需要由 Google 确认,不能承诺增加某个 IAM 角色或更换密钥就能恢复。

如果确认没有接入资格,如何继续?

应根据搜索范围评估替代方案。Google 官方说明将 Vertex AI Search 列为最多搜索 50 个域名的替代方向;对于全网搜索需求,则提供了联系入口。这两种需求需要分别评估,不能把限定域名搜索直接视为原有全网搜索功能的替换。官方迁移说明

当前可以先确认实际密钥所属项目及其历史 API 使用资格,再对照 OAuth 测试的真实请求。现有信息不足以支持一个保证生效的配置修复方案。

备注:内容仅供参考。