Google Search Results Scraper
Pricing
from $1.00 / 1,000 search results
Google Search Results Scraper
Scrape Google Search results by keyword. You get organic results, ads, People Also Ask and related searches, page by page. Pick the country, the language and the Google domain. No API key. A proxy is on by default, because Google now blocks plain requests.
Pricing
from $1.00 / 1,000 search results
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
5
Monthly active users
9 hours ago
Last modified
Categories
Share
Google Search Results Scraper: organic listings, ads and People Also Ask for one query
Type one Google query and get the results page back as rows: organic listings with their rank, the ads above them, the People Also Ask questions and the related searches at the bottom. You pick the country, the language, the Google domain and how many pages to follow.
One thing to check before you wire it into anything. The url on a result row is the link exactly
as Google printed it, and that is not always the destination: in the real row below it came back as
a google.com/goto?url=... redirect, with the publisher's name sitting in displayedUrl instead.
| Input | One Google query, operators like site:, quotes and OR included |
| Output | One row per organic result, ad, People Also Ask entry or related search |
| Ceiling | 100 rows per run, across up to 10 pages |
| Account needed | None, and no Google API key |
| Price | $1.00 per 1,000 rows, flat on every plan |
๐ What Google Search Results Scraper does
It runs your query against the Google domain you name, reads the results page, and turns it into four kinds of row.
Organic rows carry the title, the link, the domain, the displayed URL, the snippet and the rank. Ad rows carry the same shape for the paid results Google marks as such. People Also Ask rows carry the question and the answer text Google shows when the box is expanded in the HTML. Related search rows carry the phrases printed at the bottom.
Set maxPages above 1 and it follows Google's own Next link, page by page, stopping when your row
limit is reached or Google runs out of pages. Duplicate links are dropped across pages, so a listing
that appears twice arrives once.
๐ฅ What you give it
{"query": "best running shoes site:runnersworld.com","countryCode": "US","language": "en","googleDomain": "google.com","maxResults": 20,"maxPages": 2}
| Field | Default | What it is |
|---|---|---|
query | box starts at best running shoes | Your search. site:, intitle:, quoted phrases, OR and minus terms all work. |
googleDomain | google.com | The Google host, without https://. google.co.uk, google.ca and the rest are fine. |
countryCode | US | Two-letter country, sent as Google's gl. |
language | en | Interface language, sent as Google's hl. |
maxResults | 10 | Total rows, 1 to 100, counting all four kinds together. It is also the most a run can bill you. |
maxPages | 1 | Follow Google's pagination this far, 1 to 10. |
includeAds | on | Return the paid results Google marks as ads. |
includePeopleAlsoAsk | on | Return the People Also Ask questions and their answer text. |
includeRelatedSearches | on | Return the related phrases from the foot of the page. Read the limit below first. |
enableProxyFallback | on | Leave it on. Switched off, runs come back with a JS_REQUIRED row and no results. |
proxyConfiguration | leave it alone | Optional. Your own servers are used exactly as given. |
There is one more field the schema does not show: proxyUrls, an array of your own server URLs. Pass
it and those are tried first, verbatim.
Setting useApifyProxy to false inside proxyConfiguration does not take effect. The run
routes itself either way. If you want your own servers used, list them rather than switching the
object off.
๐ค What you get back
A real organic row from a recent run, with the long link and the snippet cut short:
{"ok": true,"type": "organic","title": "The 15 Best Running Shoes of 2026","url": "https://google.com/goto?url=CAESdwHrOzAV7FPP0O3re4bWugQoRsUlWFw65cAN47wAxFn...","domain": "google.com","displayedUrl": "Runner's World","snippet": "Aug 3, 2026 ... For new runners we recommend a shoe like the Brooks Ghost or Nike Pegasus as a starting point. ...Read more","rank": 1,"page": 1,"query": "best running shoes","countryCode": "US","language": "en","googleDomain": "google.com","transport": "proxy_fallback_serp","fetchedAt": "2026-09-14T05:43:56.720Z"}
| Field | What it is |
|---|---|
type | organic, ad, people_also_ask or related_search. All four land in the same dataset. |
url | The link as Google gave it. Follow it, or read displayedUrl, before treating it as the destination. |
rank | Position within its own page, so page 2 starts counting again. |
question, answer | People Also Ask rows only. answer is whatever text Google put in the HTML, which is sometimes empty. |
query | The search you typed. On a related_search row this overwrites the related phrase, which survives only inside url. |
page | Which Google page the row came from, counting from 1. |
snippet | Google's own description text, trailing Read more and all. |
๐งพ Reading the output
Three kinds of row can land in your dataset.
| Row | How to spot it | Billed as a result |
|---|---|---|
| A real result | ok: true and a type of organic, ad, people_also_ask or related_search | yes |
| The sample row | _sample: true | no |
| A diagnostic | ok: false and an errorCode | no |
Filter on ok being true with _sample absent. An empty query writes the sample row and stops, so
you can see the shape first.
| Code | What it means |
|---|---|
NO_RESULTS | The page loaded and nothing usable was on it. A query with no matches lands here. |
BLOCKED | Google would not serve that request. Re-run it or reword the query. |
RATE_LIMITED | Google answered with a rate limit. Wait and re-run. |
JS_REQUIRED | Google served its JavaScript gate instead of a results page. Turn enableProxyFallback back on. |
NETWORK | Google was unreachable or answered badly. A googleDomain that is not a real Google host also lands here rather than saying the value is wrong. |
The Overview table hides answer, displayedUrl and the diagnostic fields, so a run that produced
only a diagnostic looks almost blank there. Switch the dataset to JSON to read it.
โถ๏ธ How to run it
- Open Google Search Results Scraper and click Try for free.
- Put your search in Search query, replacing the example.
- Set Maximum results. Ten is a sensible first run.
- Change Google domain, Country code and Language if you want another country's view, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it from the Apify API.
๐ฐ How much does it cost?
$1.00 per 1,000 rows. Flat on every Apify plan, no volume tiers.
Every row that lands is one result, whether it is organic, an ad, a People Also Ask entry or a
related search. maxResults caps all four together, so it also caps what a run can bill: set it to
10 and ten rows is the most you can be charged for, however many pages get read.
The sample row, every diagnostic row and a query that finds nothing are not billed as results.
๐ก What people use it for
- Tracking where a page ranks for a keyword, week by week, with
rankandpagealready split out. - Pulling the People Also Ask questions for a topic to see what the audience actually asks.
- Checking which advertisers sit above the organic results for a commercial term in one country.
- Running the same query across
google.com,google.co.ukandgoogle.deto compare what each country sees.
๐ง What it does not do
- Related searches collapse into one row. Measured on a page carrying nine related phrases: one
related_searchrow came out, and itsqueryheld the search that was typed, not the phrase. The phrase is only readable insideurl. TurnincludeRelatedSearchesoff if you do not need it. - With a small
maxResults, ads are taken first. Cap a run at 5 on an advert-heavy term and ads can use most of the budget. SwitchincludeAdsoff if you only want organic rows. - A failure on page two or later throws away the earlier rows. With
maxPagesabove 1, a run that trips on a later page writes a diagnostic and no results. KeepmaxPagesat 1 when one page is better than nothing. - Four kinds of row, and no more. No local pack, no shopping carousel, no news box, no knowledge panel.
- Ads and People Also Ask are spotted from how Google marks them up, so a layout change on Google's side can leave some of them out until the parser catches up.
- One query per run. Feed a keyword list by scheduling or looping runs.
- Rows are a snapshot of that page at that moment. Rankings move daily.
๐งญ Which Google scraper do you need?
| If you want | Use |
|---|---|
| The web results page for a keyword | This one |
| News articles, with the publisher's real link | Google News Scraper |
| Images and where they are hosted | Google Images Scraper |
| Job postings from the jobs box | Google Jobs Scraper |
| Businesses and places | Google Maps Scraper |
โ Questions people ask
Do I need a Google API key? No. Nothing to apply for, no quota to watch.
Can I search more than one keyword at a time? Not in one run. query takes a single search. Use
a schedule or a loop for a list.
Do Google search operators work? Yes. site:, intitle:, quoted phrases, OR and minus terms
all go straight through.
Why did I get fewer rows than maxResults? Google decides how much it prints. A narrow query,
or one with site: on a small domain, often runs out before your limit does.
Can I schedule it? Yes. Runs are independent, so a daily rank check is just a schedule with the same query.
Is scraping Google Search legal? These are public search results. Apify's write-up on scraping and the law is a good starting point, and we are not lawyers.
๐ If something breaks
Open the Issues tab on the actor page. Send the query and the run ID. The errorCode on the
diagnostic row usually names the problem on its own.