Google Custom Search API Alternative (CSE JSON)
Pricing
from $4.00 / 1,000 searches
Google Custom Search API Alternative (CSE JSON)
Drop-in replacement for Google's Custom Search JSON API, which shuts down on 1 January 2027: the same /customsearch/v1 parameters and JSON (items with title, link, snippet; image search too) from live Google results. No 10,000-a-day cap. $5 per 1,000 searches, Google's own price.
Pricing
from $4.00 / 1,000 searches
Rating
0.0
(0)
Developer
Nathan Carter
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
7 minutes ago
Last modified
Categories
Share
A drop-in replacement for Google's Custom Search JSON API, which Google has closed to new customers and retires on 1 January 2027. Send the same /customsearch/v1 requests and get the same JSON back (items with title, link, snippet, image search with searchType=image), served from live Google results. Existing code changes two things: the base URL and the key.
Example result
q=best crm for startups&num=2, a real response from 6 October 2026 (only the url template is left out):
{"kind": "customsearch#search","queries": {"request": [{"title": "Google Custom Search - best crm for startups","searchTerms": "best crm for startups","count": 2,"startIndex": 1,"inputEncoding": "utf8","outputEncoding": "utf8","safe": "off","totalResults": "4"}],"nextPage": [{"title": "Google Custom Search - best crm for startups","searchTerms": "best crm for startups","count": 2,"startIndex": 3,"inputEncoding": "utf8","outputEncoding": "utf8","safe": "off","totalResults": "4"}]},"context": {"title": "Google Search by AutomationNation"},"searchInformation": {"searchTime": 1.548,"formattedSearchTime": "1.55","totalResults": "4","formattedTotalResults": "4"},"items": [{"kind": "customsearch#result","title": "What's the best CRM for an early stage, bootstrapped ...","htmlTitle": "What's the <b>best</b> <b>CRM</b> <b>for</b> an early stage, bootstrapped ...","link": "https://www.reddit.com/r/CRM/comments/1ncf59q/whats_the_best_crm_for_an_early_stage/","displayLink": "www.reddit.com","snippet": "We're just 2 people right now who are growing fast averaging 60 leads a month, and Salesforce or HubSpot feel way too heavy for where we are. But Google ...","htmlSnippet": "We're just 2 people right now who are growing fast averaging 60 leads a month, and Salesforce or HubSpot feel way too heavy for where we are. But Google ...","formattedUrl": "https://www.reddit.com/r/CRM/comments/1ncf59q/whats_the_best_crm_for_an_early_stage/","htmlFormattedUrl": "https://www.reddit.com/r/CRM/comments/1ncf59q/whats_the_best_crm_for_an_early_stage/"},{"kind": "customsearch#result","title": "Best CRM For Startups: The All-In-One Guide","htmlTitle": "<b>Best</b> <b>CRM</b> <b>For</b> <b>Startups</b>: The All-In-One Guide","link": "https://www.salesforce.com/crm/startup-crm/","displayLink": "www.salesforce.com","snippet": "Find out how the right CRM for startups can help boost revenue, reduce costs, and scale operations.","htmlSnippet": "Find out how the right CRM for startups can help <b>boost revenue, reduce costs, and scale operations</b>.","formattedUrl": "https://www.salesforce.com/crm/startup-crm/","htmlFormattedUrl": "https://www.salesforce.com/crm/startup-crm/"}]}
Quick facts
- Same requests, same JSON:
q,num,start,gl,hl,lr,cr,safe,dateRestrict,siteSearch,exactTerms,excludeTerms,orTerms,fileType,searchType=imageand the image filters.cxandkeyare accepted and ignored. - Keeps working after 1 January 2027, with no 10,000-queries-a-day cap.
- Price: $5 per 1,000 searches of up to 10 results, the same as Google charged, and less on paid Apify plans. Searches that return nothing are free.
- Two ways to use it: an HTTP endpoint for existing code (Standby mode), or normal runs from Apify Console, the API, schedules and integrations, with one dataset row per result.
- Speed: a request usually takes 4–10 seconds, occasionally up to about 20, because each one fetches live Google results (Google's API answered in under a second). Run requests in parallel for throughput.
- Clean results: web searches use Google's "Web" results view: ten plain results per page, without the AI Overview, ads or video and forum boxes, which is close to what the API returned.
Switch your code in two lines
Replace the endpoint and send your Apify API token instead of the Google key. Everything else stays the same.
| Before | After | |
|---|---|---|
| Endpoint | https://www.googleapis.com/customsearch/v1 | https://automationnation--google-custom-search-api.apify.actor/customsearch/v1 |
| Auth | key=YOUR_GOOGLE_KEY&cx=YOUR_ENGINE_ID | token=YOUR_APIFY_TOKEN (or the header Authorization: Bearer YOUR_APIFY_TOKEN) |
curl
$curl "https://automationnation--google-custom-search-api.apify.actor/customsearch/v1?q=best+crm+for+startups&num=10&token=$APIFY_TOKEN"
Python
import os, requestsr = requests.get("https://automationnation--google-custom-search-api.apify.actor/customsearch/v1",params={"q": "best crm for startups", "num": 10, "gl": "us"},headers={"Authorization": f"Bearer {os.environ['APIFY_TOKEN']}"},timeout=60,)for item in r.json().get("items", []):print(item["title"], item["link"])
JavaScript
const url = new URL('https://automationnation--google-custom-search-api.apify.actor/customsearch/v1');url.search = new URLSearchParams({ q: 'best crm for startups', num: '10' });const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.APIFY_TOKEN}` } });const { items = [] } = await res.json();for (const item of items) console.log(item.title, item.link);
Set your HTTP timeout to at least 60 seconds. The first request after a quiet spell also starts the server, which adds a few seconds.
Google's Python client and LangChain
Code built on Google's own client (google-api-python-client) keeps working too: point it at this endpoint and add the token as a header. This snippet was tested on 6 October 2026:
import osimport httplib2from googleapiclient.discovery import buildclass ApifyAuth(httplib2.Http):"""Sends your Apify token with every request."""def request(self, uri, method="GET", body=None, headers=None, *args, **kwargs):headers = {**(headers or {}), "Authorization": f"Bearer {os.environ['APIFY_TOKEN']}"}return super().request(uri, method, body, headers, *args, **kwargs)service = build("customsearch", "v1",developerKey="unused", # the Apify token in the header replaces the keyhttp=ApifyAuth(timeout=60),client_options={"api_endpoint": "https://automationnation--google-custom-search-api.apify.actor"},static_discovery=True, # uses the API description bundled with the library; nothing goes to Google)res = service.cse().list(q="best crm for startups", cx="unused", num=10).execute()
LangChain (GoogleSearchAPIWrapper from langchain-google-community) uses that client, so give it the service above:
from langchain_google_community import GoogleSearchAPIWrappersearch = GoogleSearchAPIWrapper(google_api_key="unused", google_cse_id="unused", k=5)search.search_engine = serviceprint(search.run("how to learn rust"))
Supported parameters
| Parameter | What it does here |
|---|---|
q | The search. Google operators work: site:, filetype:, "exact phrase", -exclude, OR. |
num | Results per request, 1–10 (default 10). |
start | Index of the first result, 1–100. As with Google's API, results stop at 100. |
gl / hl | Country and interface language of the Google results (default us / en). |
lr / cr | Language (lang_de) and country (countryDE) restrictions. |
safe | active turns on SafeSearch. |
dateRestrict | d[number], w[number], m[number] or y[number], e.g. m6 for the past six months. |
siteSearch + siteSearchFilter | Only results from a site (i, the default) or none from it (e). |
exactTerms, excludeTerms, orTerms, fileType | Added to the query the way Google's engine does it. |
filter | 0 turns off Google's duplicate filter. |
searchType=image | Google Images, with imgSize, imgType, imgColorType, imgDominantColor and rights. Items include image.contextLink, width, height, byteSize and the thumbnail. |
cx, key, fields, alt | Accepted so existing code doesn't break. cx is echoed back; the others are ignored. |
Errors use the API's own format, for example a missing q returns HTTP 400 with {"error": {"code": 400, "message": "Required parameter: q", …}}.
Differences from Google's API
Most code won't notice these, but check them before you switch:
- It searches the whole web, like a Programmable Search Engine set to "Search the entire web". A
cxlimited to your own sites isn't read; pass those sites withsiteSearch, or inqassite:example.com OR site:example.org. Off-site results that Google mixes into later pages are removed. totalResultsis a lower bound. Google no longer shows result counts, so it's the results so far plus one more page while there are more. Clients that page until they run out still work.- No
pagemap(thumbnails and metatags per result). sort,linkSite,lowRange,highRange,hqandc2coffare ignored.- Slower: usually 4–10 seconds per request instead of under one, since each request fetches live Google results. If your client has a short timeout (10 seconds is common), raise it to 60.
Use it as a normal Actor run
In Apify Console, through the Apify API, on a schedule or from Make, n8n or Zapier, give it a list of searches and get one dataset row per result, in the API's item format.
Input example
{"queries": ["best project management software", "mcp server site:github.com"],"maxResultsPerQuery": 20,"country": "us","language": "en"}
Options: searchType (web or image), maxResultsPerQuery (up to 100), country, language, siteSearch with excludeSite, dateRestrict, fileType and safeSearch.
Output example
A real row from 6 October 2026 (htmlTitle, htmlSnippet and htmlFormattedUrl left out):
{"query": "mcp server site:github.com","position": 1,"searchType": "web","kind": "customsearch#result","title": "modelcontextprotocol/servers: Model Context Protocol ...","link": "https://github.com/modelcontextprotocol/servers","displayLink": "github.com","snippet": "The servers in this repository are intended as reference implementations to demonstrate MCP features and SDK usage. They are meant to serve as educational ...","formattedUrl": "https://github.com/modelcontextprotocol/servers","country": "us","language": "en","scrapedAt": "2026-10-06T11:52:43.406Z"}
Image searches add mime, fileFormat and image (contextLink, width, height, byteSize, thumbnailLink). A run summary per search is saved as OUTPUT in the key-value store.
How much does it cost?
You pay per search of up to 10 results: $5 per 1,000, the price Google charged for the Custom Search JSON API. Searches that return nothing, and requests Google doesn't answer, are free. A normal run counts each page of up to 10 results it saves as one search.
| Searches | Free & Bronze plans | Silver | Gold and above |
|---|---|---|---|
| 1,000 | $5.00 | $4.50 | $4.00 |
| 10,000 | $50 | $45 | $40 |
| 100,000 | $500 | $450 | $400 |
Google's API also gave 100 free queries a day. Here, the Apify free plan's $5 monthly credit covers about 1,000 searches a month. There's no daily cap, and for normal runs you can set a maximum cost per run.
Use it with AI agents (MCP)
Add https://mcp.apify.com?tools=automationnation/google-custom-search-api to Claude, ChatGPT, Cursor or another MCP client and sign in with Apify. The agent can then run Google searches and read the results as JSON.
FAQ
Is the Custom Search JSON API really going away? Yes. Google's documentation says it's closed to new customers and that existing customers have until 1 January 2027 to move. For searching up to 50 domains Google suggests Vertex AI Search, a different product with a different API; for whole-web search it asks you to contact Google.
Do I need to change my parsing code?
No. The response has the same shape: items[].title, link, displayLink, snippet, htmlSnippet, formattedUrl, queries.nextPage and searchInformation. Check the differences above for totalResults and pagemap.
Can I use my Programmable Search Engine's site list?
Not by its cx. Put the sites in siteSearch (one site) or in q (site:a.com OR site:b.com).
How fast is it, and how many requests can I send? Usually 4–10 seconds per request, occasionally up to about 20. Requests run in parallel, so send several at once for throughput; there's no daily cap.
Is it legal? It reads public Google results, like a person searching. Use the data in line with the laws and terms that apply to you.
Guides: Custom Search JSON API shutting down: a drop-in replacement · LangChain GoogleSearchAPIWrapper after the shutdown · Image search after the Custom Search API · Code examples (Python, JavaScript, curl)
More Google data from AutomationNation
- Google Images Scraper: up to 100 full-size images per search, with sizes and source pages.
- Google News Scraper: headlines, sources, dates and article URLs.
- Google Shopping Scraper: prices, stores and reviews for any product search.
- Google Videos Scraper: videos from YouTube, TikTok and more, with channel and duration.
- Google AI Overview Tracker: whether Google's AI Overviews cite your site.
- Google Trends Scraper: interest over time, related queries and trending searches.
Questions or a missing parameter? Open an issue on the Issues tab; fixes usually ship within a day.