Google's Custom Search API shuts down Jan 1. Migrate by changing one URL. A developer built cse-compat, an open-source Cloudflare Worker that preserves the Google Custom Search JSON API contract ahead of the API's January 1, 2027 shutdown. The tool serves the same /customsearch/v1 endpoint, parameters, response fields and error format while proxying queries to providers like Serper or Brave using the user's own API key, so existing clients only need to change the host and key. It is released under Apache-2.0 and runs on Cloudflare's free plan. If you have code that calls https://www.googleapis.com/customsearch/v1 , it stops working on January 1, 2027 . Google has already closed the API to new customers, and existing ones are being moved off it. I went through this myself and ended up building a small open-source tool for it. This post covers what's changing, what your options are, and the approach I went with, including where it falls short. The Custom Search JSON API is the one where you send key , cx and q , and get back JSON with an items array. For years it was the easy way to put web search into a script, an internal tool, or more recently an AI agent: 100 free queries a day, then $5 per 1,000. Google's suggested replacements aren't the same product: So if you were using it for general web search, there's no official drop-in path. 1. Rewrite for a new search API. Brave, Serper, Exa, Tavily and others all have good APIs. But each one returns a different JSON shape, so you rewrite your parsing, pagination and error handling. That's fine for one small script, and painful if the call is spread across several services or buried inside a library you don't own. 2. Switch to Vertex AI Search. Makes sense if you were only ever searching your own sites. It's a different API, though, so it's still a rewrite. 3. Keep the old API shape and swap what's behind it. Put a thin layer in front of a new provider that speaks the old format exactly. Your code keeps calling the same endpoint shape, you change the base URL, and that's it. I went with option 3. If you try to build a compatibility layer yourself, "return some JSON with items " isn't enough. Code that has run against this API for years quietly depends on details like: items is missing entirely when there are no results. if "items" in res . htmlSnippet and htmlTitle