Google Custom Search JSON API Is Shutting Down: How to Migrate Before January 1, 2027
Google has closed the Custom Search JSON API to new customers and set a January 1, 2027 deadline for existing ones. Here are your options, and a step-by-step migration to a SERP API.

- What is happening
- Your options
- Migration, step by step
- 1. Change the URL and the key
- 2. Fix the page offset
- 3. Keep your site restriction, if you had one
- 4. Rename the fields you read
- 5. Run both side by side
- What it costs
- A checklist
What is happening
Google’s Custom Search JSON API overview now says two things:
- “The Custom Search JSON API is closed to new customers.”
- “Existing Custom Search JSON API customers have until January 1, 2027 to transition to an alternative solution.”
If your product calls https://www.googleapis.com/customsearch/v1, it stops working on January 1, 2027. If you were planning to start using it, you already can’t.
Your options
What to move to depends on what you were searching.
You search your own site or a short list of sites. Google suggests Vertex AI Search, which it describes as “a favorable alternative for searching up to 50 domains.” It indexes the sites you give it and is built for site search, not for reading Google’s public results.
You need results from the whole web. Google’s page asks teams with this need to contact them, with no self-serve product named. The self-serve answer is a SERP API: a service that runs the search on Google and returns the results page as JSON. That is what the rest of this guide covers, using Serply as the example. The steps carry over to any SERP API; our SERP API pricing comparison covers the others.
You use it for rank tracking or SEO. Custom Search results come from a Programmable Search Engine and were never a faithful copy of what a person sees on google.com. A SERP API returns the real results page, including ads, answer boxes and related questions, so this is a chance to fix that as well.
Migration, step by step
1. Change the URL and the key
Custom Search takes the key as a key parameter and needs a search engine ID in cx. Serply takes the key in an X-Api-Key header and has no engine ID, because it searches all of Google.
Before:
import requests
resp = requests.get(
"https://www.googleapis.com/customsearch/v1",
params={
"key": GOOGLE_API_KEY,
"cx": SEARCH_ENGINE_ID,
"q": "best running shoes",
"num": 10,
"start": 11,
"gl": "us",
},
)
items = resp.json().get("items", [])
After:
import requests
resp = requests.get(
"https://api.serply.io/v1/search/",
headers={"X-Api-Key": SERPLY_API_KEY},
params={
"q": "best running shoes",
"num": 10,
"start": 10,
"gl": "us",
},
)
items = resp.json().get("results", [])
2. Fix the page offset
This is the change most likely to slip through. Custom Search counts start from 1, so the second page is start=11. Serply counts from 0, so the second page is start=10. Subtract 1 everywhere you build a start value, or every page after the first will overlap by one result.
Both cap num at 10. To get 30 results, request three pages. See the pagination guide.
3. Keep your site restriction, if you had one
If your search engine was limited to certain sites, there is no cx to carry that setting any more. Put it in the query with Google’s site: operator:
q=return policy site:example.com
The search operators guide lists the rest. If you rely on siteSearch, use the same operator.
4. Rename the fields you read
| Custom Search | Serply |
|---|---|
items[] | results[] |
items[].title | results[].title |
items[].link | results[].link |
items[].snippet | results[].description |
items[].displayLink | results[].metadata.display_url |
searchInformation.totalResults | total |
Two differences to code for:
totalis oftennull. Google only shows an estimated count on some result pages, so do not use it to decide how many pages to fetch.- Some
linkvalues carry Google’s tracking parameters (ved=,usg=and similar). Strip them if you store or compare URLs.
Image search (searchType=image) moves to its own endpoint, /v1/image.
5. Run both side by side
Before you switch traffic, run a sample of your real queries through both APIs and compare the top results. Every new Serply account gets 2,500 free credits with no card, which is enough for a few hundred test queries with room to spare.
What it costs
Custom Search gives 100 free queries a day (about 3,000 a month), then charges $5 per 1,000, up to 10,000 queries a day.
| Searches a month | Custom Search | Serply |
|---|---|---|
| 10,000 | $35 | $15 (Starter pack, $1.50 per 1,000) |
| 50,000 | $235 | $49 (Growth pack, $0.98 per 1,000) |
| 300,000 | $1,485 | $225 (Pro pack rate, $0.75 per 1,000) |
Serply sells prepaid packs, and purchased credits never expire, so a pack bigger than one month’s usage simply carries over. Full details are on the pricing page.
A checklist
- List every place your code calls
customsearch/v1. - Move the key to an
X-Api-Keyheader and dropcx. - Subtract 1 from every
startvalue. - Move site restrictions into
site:operators. - Rename
itemstoresultsandsnippettodescription. - Handle a
nulltotal. - Compare a sample of queries before switching.
- Switch before January 1, 2027.
If you want to see the response before writing any code, the Custom Search alternative page runs a live search without a key.