Skip to content

New AI assistant answers: ChatGPT, Gemini, Copilot and AI Mode by API

SerpKite
Get API key

Custom Search API 403 "does not have the access": the fix

New Google Cloud projects get 403 PERMISSION_DENIED from the Custom Search JSON API. Why no key or setting fixes it, and the two-line switch.

SerpKite team 2 min read

On this page

If a call to https://www.googleapis.com/customsearch/v1 fails like this, nothing is wrong with your key:

{
  "error": {
    "code": 403,
    "message": "This project does not have the access to Custom Search JSON API.",
    "errors": [
      {
        "message": "This project does not have the access to Custom Search JSON API.",
        "domain": "global",
        "reason": "forbidden"
      }
    ],
    "status": "PERMISSION_DENIED"
  }
}

Client libraries wrap the same response: Python’s googleapiclient raises HttpError 403 ... "This project does not have the access to Custom Search JSON API.", and n8n shows Forbidden - perhaps check your credentials? followed by the same sentence.

Why you get it

Google closed the Custom Search JSON API to new customers on January 20, 2026. A Google Cloud project that was not already using it gets this 403 on every request. The API is still listed in the API Library and can be “enabled”, so the console looks correct while every call fails.

Existing projects keep working until January 1, 2027, when the API shuts down for everyone. After that date, expect these calls to fail for every project, not only new ones.

What does not fix it

People in Google’s support forum, developer forum and issue tracker report trying all of these without success:

  • creating a new API key, or removing the key’s API restrictions;
  • disabling and re-enabling the Custom Search API in the project;
  • enabling billing or upgrading the account;
  • creating a new project or a new Programmable Search Engine (cx);
  • calling with OAuth instead of a key.

Google offers no self-serve full-web replacement. Vertex AI Search covers your own sites and data stores, not the whole web.

The fix: point the same request at SerpKite

SerpKite serves /customsearch/v1 with the same query parameters and the same customsearch#search response, built from Google’s public results page. Change the host and the key:

Google (403) −1 line
curl "https://www.googleapis.com/customsearch/v1?key=$GOOGLE_API_KEY&cx=$CX&q=asyncio"
SerpKite +1 line
curl "https://api.serpkite.com/customsearch/v1?key=$SERPKITE_API_KEY&cx=$CX&q=asyncio"

Your parsing code keeps reading items[].title, items[].link, items[].snippet, searchInformation.totalResults and queries.nextPage. cx is accepted and ignored, so you can leave it in place.

If your engine searched only your own sites

SerpKite searches the whole public web. Add siteSearch=docs.example.com or a site: operator in q to keep the restriction.

The migration guide has the parameter table and code for Python (requests and google-api-python-client), Node.js and Go. The CSE migration helper rewrites a pasted request URL for you.

Errors after the switch

Errors from /customsearch/v1 use Google’s error body, so error.code is the HTTP status and error.errors[0].reason a Google reason such as keyInvalid; SerpKite’s own code is in error.details[0].reason. A 503 means the search failed upstream; it is not billed and is safe to retry. See Errors.

Cost

Each /customsearch/v1 call is 1 credit. Packs cost $0.60–$1.00 per 1,000 searches, credits never expire, and there is no daily cap. New accounts get 2,500 free credits and 1,000 more every month, with no card. Details are on the pricing page.

Written by the SerpKite team. Questions or corrections: support@serpkite.com. Subscribe via RSS.

Related posts

Start building

Get your API key in 30 seconds

2,500 free credits, then 1,000 every month. No credit card.