Skip to content

Build1 publisher3 min readPublished

Callers of Google's Custom Search JSON API must pick a new web search provider before January 1, 2027

Google stops serving the Custom Search JSON API on January 1, 2027 and has already closed it to new customers. Teams using it for general web search now pick between rewriting for another provider and running a shim that copies the old contract.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying Callers of Google's Custom Search JSON API must pick a new web search provider before January 1, 2027
Generated illustration

What happened

  • Vertex AI Search, one of Google's suggested replacements, is built for an organisation's own content or up to 50 domains and is not a general web search API.
  • For full web search, Google points customers to a partner-only offering that has no public pricing and requires contacting the company.
  • A developer has published cse-compat, an open-source Cloudflare Worker that serves the /customsearch/v1 endpoint using Google's old contract.
  • Moving a caller onto the cse-compat shim changes only the host and the key in each request URL.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost Any 2027 budget for general web search has to come from a new vendor's quote, since Google prices its own web option only through a partner channel.
  • exposure Services that swap providers directly can fail in production on billing or quota errors their clients were never tested against.
  • decision Teams with search calls in several services or inside third-party libraries now choose between a multi-site rewrite and running a proxy they have to own.

A host swap is safe only if the new endpoint reproduces the old one's edge cases. Callers sent key, cx and q and got JSON with an items array back [3]. According to the developer who built cse-compat and described it on dev.to, code that has run against that contract for years quietly depends on details well beyond the items array [10].

When a query has no results, the items key is missing entirely, and plenty of code checks `if "items" in res` [11]. Matched words in htmlTitle and htmlSnippet arrive wrapped in `<b>` tags, and some interfaces render them directly [12]. Most pagination loops stop on queries.nextPage [13]. A request cannot reach past result 100 through start plus num, num must fall between 1 and 10, and Google returns a specific 400 error when a caller breaks either rule [14]. Even totalResults is a string [16]. "Getting these right is most of the work," the author wrote [17].

Errors are where a plain provider swap breaks first [15]. Retry logic often checks for a 429 carrying RESOURCE_EXHAUSTED [15]. A new provider that returns 402 Payment Required sends the client into a code path it has never seen [15]. The cse-compat Worker returns Google's error format along with Google's parameters and response fields [18].

"So if you were using it for general web search, there's no official drop-in path," the author wrote [8]. Vertex AI Search is a different API, so even teams that only ever searched their own sites face a rewrite [6]. In my view the shim is the right tradeoff when the search call is spread across several services or buried in a library the team does not own. That is the case the author calls painful for a rewrite against Brave, Serper, Exa or Tavily, because each returns its own JSON shape [9]. For one small script, the author calls a rewrite fine [9], and it leaves one fewer service to operate.

Running the shim puts a Cloudflare Worker on the request path. It is licensed Apache-2.0 and runs on Cloudflare's free plan [18]. Inside the Worker, the Serper key is a Wrangler secret; apps send a proxy key the operator makes up in place of the old Google key, so the calling services never hold the provider credential [20]. Results come from Serper today, with a Brave adapter included, even though the response shape is Google's [19]. For real use you deploy your own copy, since the public demo has a daily cap [25].

The client guidance is the most careful part of the post. Google's official client has Google's host built in but accepts an override: in Python through `client_options={"api_endpoint": "https://cse.yourdomain.workers.dev"}` [22], and in Node through `rootUrl` [24]. The Python example also sets `static_discovery=True`. That flag makes the client use its built-in API description and skip fetching one from Google, so nothing depends on Google's servers after the shutdown [23].

Budgeting starts from the old rate: 100 free queries a day, then $5 per 1,000 [4], or half a cent a query [2]. The post does not include prices for Serper, Brave or the other providers it names. The unit to price is the call. A loop that pages to the end of the 100-result window at 10 results per page makes 10 calls for one search [1].

What to watch

  • Whether Google publishes access terms or pricing for its partner-only web search offering before the January 1, 2027 cutoff.
  • Published per-call prices from Serper and Brave, the two providers cse-compat supports today.
  • Whether cse-compat adds adapters for providers beyond Serper and Brave.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories