serpgrab answers the same requests as SerpApi with the same JSON, so moving over is mostly a find-and-replace. This post shows the change for the three ways people usually call SerpApi, and lists what to check before you switch production traffic.
You will need a serpgrab key. The free one takes an email address at serpgrab.com and covers 250 searches a month.
Plain HTTP: change the host and the key
If you build the URL yourself (curl, fetch, requests, an HTTP node in a no-code tool), the
two lines that change are the host and the key. The path, the parameter names and api_key
stay as they are:
- https://serpapi.com/search.json?engine=google&q=coffee&location=Austin,Texas,United+States&api_key=SERPAPI_KEY
+ https://api.serpgrab.com/search.json?engine=google&q=coffee&location=Austin,Texas,United+States&api_key=SERPGRAB_KEY
If you would rather keep the key out of URLs and logs, send it as an X-API-Key header or as
Authorization: Bearer <key> instead.
Google Maps works the same way: engine=google_maps with q and ll, on the same
/search.json path.
Python: the official serpapi client
SerpApi’s own Python package keeps its host in one attribute, so you can point a client at serpgrab and leave the rest of your code alone:
import os
import serpapi
client = serpapi.Client(api_key=os.environ["SERPGRAB_KEY"], timeout=100)
client.BASE_DOMAIN = "https://api.serpgrab.com" # the one new line
results = client.search(engine="google", q="coffee", location="Austin,Texas,United States")
for r in results["organic_results"]:
print(r["position"], r["title"], r["link"])
Paging works too. next_page() and yield_pages() follow serpapi_pagination.next, and
serpgrab fills that link with its own host:
for page in results.yield_pages(max_pages=3):
for r in page.get("organic_results", []):
print(r["title"])
We tested this with serpapi 1.1.2.
Node: swap getJson for fetch
SerpApi’s Node package (serpapi on npm) fixes its host name inside the library, so you can’t
point it somewhere else. The good news is that getJson does very little, and a dozen lines
of fetch (built into Node 18 and later) replace it with the same signature:
// before: import { getJson } from 'serpapi';
async function getJson(params) {
const url = new URL('https://api.serpgrab.com/search.json');
url.search = new URLSearchParams({ ...params, api_key: process.env.SERPGRAB_KEY });
const res = await fetch(url, { signal: AbortSignal.timeout(100_000) });
const data = await res.json();
if (!res.ok) throw new Error(data.error ?? `serpgrab: HTTP ${res.status}`);
return data;
}
const data = await getJson({ engine: 'google', q: 'coffee', location: 'Austin,Texas,United States' });
for (const r of data.organic_results ?? []) console.log(r.position, r.title, r.link);
Your existing getJson({...}) calls don’t change, as long as you pass them the parameters as an
object.
On the Pro plan (RapidAPI)
Pro is billed through RapidAPI, so paid calls go to RapidAPI’s host, and the key travels in two
headers instead of api_key. Everything else, including paths, parameters and responses, is the
same:
curl -G 'https://google-serp-search-results-json.p.rapidapi.com/search.json' \
--data-urlencode 'q=coffee' \
--data-urlencode 'location=Austin,Texas,United States' \
-H 'x-rapidapi-host: google-serp-search-results-json.p.rapidapi.com' \
-H 'x-rapidapi-key: YOUR_RAPIDAPI_KEY'
With the Python client, set the host and add the headers to its session:
client = serpapi.Client(timeout=100)
client.BASE_DOMAIN = "https://google-serp-search-results-json.p.rapidapi.com"
client.session.headers.update({
"x-rapidapi-host": "google-serp-search-results-json.p.rapidapi.com",
"x-rapidapi-key": os.environ["RAPIDAPI_KEY"],
})
In the Node helper, change the URL to the same host and pass those two headers to fetch.
Set a longer timeout
Most searches answer in 1-5 seconds. Now and then a search needs a fresh connection to Google and takes up to about 70 seconds, which is longer than the Node library’s 60-second default. The examples above use 100 seconds. Whatever client you use, give it at least that.
What stays the same
- Block and field names:
organic_results,local_results,knowledge_graph,answer_box,related_questions,ai_overview,adsand the rest, with the same fields inside them. - Links: organic
linkis the real destination URL, with Google’s redirect resolved. - Positions and paging:
positionrestarts at 1 on every page, as on SerpApi, andstart=10is page 2.serpapi_pagination.nextpoints back at the API. - Errors: errors come back as JSON with an
errorfield and an HTTP status that says what went wrong (400 for a bad parameter, 401 for a bad key, 503 when busy, withRetry-After).
What to check before you switch
These are the gaps, so you find them now rather than in production:
- Engines:
googleandgoogle_maps(Maps search only; place details and reviews are not there yet). Any other engine returns 400. - Desktop only:
device=mobileanddevice=tabletreturn 400. nfpr=1andfilter=0return 400 for now.search_information.showing_results_forstill tells you when Google corrected the query.google_domainis ignored: every search runs on google.com. Useglfor the country; the search then runs from a connection in that country.- SerpApi’s other APIs are not there: no Account API (
/account), Locations API (/locations.json), Search Archive (/searches/<id>) orasync=true. Responses have nosearch_metadata.id. - SerpApi’s own links (
serpapi_link,reviews_link,photos_linkand similar), which point at SerpApi’s servers, are left out. - Not parsed yet: chart data (hourly weather, price history) and the part of an AI Overview that Google only loads after “Show more”.
If your code reads any of those, keep that part on SerpApi for now, or email us and tell us which one you need.
A safe way to switch
- Run your usual queries against both APIs for a day and compare the blocks your code reads. Expect some values to differ, because Google reshuffles results from minute to minute and the two searches won’t see the exact same page.
- Move a slice of traffic, watch your error rate, then move the rest.
- Keep the SerpApi key until the first month has gone by without surprises.
Try it
Get a free key at serpgrab.com: 250 searches a month, no card. After that, Pro is $15 for 5,000 searches a month on RapidAPI, against $75 on SerpApi’s Developer plan (how we compare with SerpApi, SearchApi and Serper). If something your code relies on doesn’t match SerpApi, email hello@serpgrab.com and we will look at it.
- The serpgrab team