Google Search Results Scraper (SERP) - No Login, Per Page avatar

Google Search Results Scraper (SERP) - No Login, Per Page

Pricing

from $1.50 / 1,000 results pages

Go to Apify Store
Google Search Results Scraper (SERP) - No Login, Per Page

Google Search Results Scraper (SERP) - No Login, Per Page

Scrape Google search results for your keywords: organic positions, titles, URLs, snippets, dates, sitelinks and related searches. Pick country and language, up to 10 pages per query. One row per result. No login.

Pricing

from $1.50 / 1,000 results pages

Rating

0.0

(0)

Developer

Cliqto Media

Cliqto Media

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Add search queries, pick a Google country and language, and get the public Google search results (SERP) as one row per result: organic results and related searches, each with its position. No Google login, no API key; you pay per loaded results page, about $0.006 for the first page of one query.

Use it for rank tracking, SEO research and competitor checks. The smallest run is the prefilled query apify web scraping with one page; it finishes in a few seconds.

Google Search Results Scraper: queries in, organic results and related searches out, one row per result

Table of contents

What it does

The Actor opens the public Google results page for each query, in the country (gl) and language (hl) you choose, and reads up to 10 result pages per query. It saves:

  • organic results: position, title, URL, displayed URL, snippet, date and sitelinks (when Google shows them);
  • related searches: the "People also search for" list, once per query.

Google's simple results page does not carry ads or prices. The field price stays in every row for compatibility (always null), and the includeAds option adds no rows today. Sitelinks (the short links under some results) are saved in the sitelinks list of that result and are not separate rows; the list is empty when Google shows none.

Every row has the query, page number and status, so you can filter and sort in the Dataset, in a spreadsheet or by API.

Good fit

  • Track where a site ranks for a list of keywords in one country.
  • Collect top 10–100 URLs for a topic for SEO or content research.
  • See which shops and brands rank for product queries.
  • Find related searches to grow a keyword list.

Not a fit / limits

  • The Actor reads Google's simple HTML results page. It does not return ads, shopping prices, People Also Ask, AI Overviews, featured snippets, maps or image packs.
  • Results are not personalised and not tied to a city. A Google Ads account, Search Console data or search volume are not included.
  • Google sometimes blocks automated traffic. The Actor changes IP addresses and retries, but it never solves CAPTCHAs (see Troubleshooting).

Quick start

  1. Open the Input tab.
  2. In Search queries (queries), keep the prefilled apify web scraping or add your own queries, one per line.
  3. Keep Country us and Language en (defaults), or choose others.
  4. Keep Pages per query (maxPagesPerQuery) at 1 (prefill), or set up to 10.
  5. Click Start.
  6. Open the Output tab (Dataset) and check type, position, title and url.

Expected result: 9–10 organic rows and about 8 related searches for each query page.

Use cases

Buyer jobInput pathOutput entityKey fieldsNext integration
Rank trackingqueries, countryCode, maxPagesPerQueryorganic rowquery, position, url, pageSchedule + Google Sheets or API
SEO content researchqueries, languageCodeorganic rowtitle, description, displayedUrl, dateExport CSV / JSON
Shop and brand checkqueries, countryCodeorganic rowtitle, url, displayedUrl, descriptionExport to spreadsheet
Keyword ideasqueries, includeRelatedrelated rowtitle, urlFeed back into queries

Input

Input fields

FieldPlain nameTypeRequiredDefault / prefillAllowed valuesEffectExample
queriesSearch queriesarray of textyesprefill ["apify web scraping"]1–500 queries, up to 256 characters eachOne Google search per query. Operators like site: and "exact phrase" work. Duplicates and extra spaces are removed.["best running shoes", "site:apify.com scraper"]
countryCodeCountrytextnodefault usGoogle country codes, e.g. us, gb, de, fr, jpCountry for ranking (gl)"de"
languageCodeLanguagetextnodefault enGoogle language codes, e.g. en, de, fr, pt-BRInterface language (hl)"de"
maxPagesPerQueryPages per queryintegernodefault 1, prefill 11–10How many result pages per query (usually 9–10 organic results each). Each loaded page is charged.3
includeAdsInclude ads (not available)true/falsenodefault truetrue, falseKept for compatibility. Google's simple results page shows no ads, so this option adds no rows today.false
includeRelatedInclude related searchestrue/falsenodefault truetrue, falseAdds related search rows once per queryfalse
proxyConfigurationProxyobjectnoApify datacenter proxyApify proxy groups or your own URLsWhere requests come from. With the default, a page that Google refuses on several datacenter IPs is retried through Apify residential proxy in the chosen country.{"useApifyProxy": true}

An empty queries list stops the run with a clear input error and no page charge.

Interacting settings

WhenInput AInput BEffective behaviorCost effect
Google has fewer pagesmaxPagesPerQuerythe queryThe Actor stops at the last page Google hasOnly loaded pages are charged
Ads on or offincludeAdsany queryNo ad rows either way: the simple Google page has noneNo change
Own proxyproxyConfigurationcountryCodeNo automatic switch to residential proxySame price per page; own proxy URLs are paid by you

Input examples

Track 3 keywords in Germany, 2 pages each

{
"queries": ["laufschuhe herren", "matratze test", "site:zalando.de sneaker"],
"countryCode": "de",
"languageCode": "de",
"maxPagesPerQuery": 2,
"includeRelated": false
}

Expected behavior: 6 result pages, organic rows only. Expected output: query, page, position, title, url. Cost note: 6 pages + 1 start = $0.016 on the Free plan.

Output

One Dataset row per result. A query without results gets one not_found row; a query that could not be scraped gets one error row.

Output fields

FieldMeaningTypeCan be empty?Example / enum
queryYour search querytextno"apify web scraping"
pageGoogle result page (1 = first)numbernull on status rows1
typeRow type (ad is reserved and not written today)textnull on status rowsorganic, related
positionPlace among rows of the same type for this query; organic positions continue across pages; a URL that Google repeats on a later page is saved oncenumbernull on status rows1
titleResult title or related search texttextyes"Apify"
urlResult URL; for related, a Google search URLtextyes, when Google hid the link"https://apify.com/"
displayedUrlSite as Google shows it (domain and breadcrumb)textyes"www.apify.com › store"
descriptionSnippet texttextyes
dateDate shown before the snippet, as Google prints ittextyes"Oct 9, 2026"
sitelinksLinks shown under a result, as {title, url}; an empty list when Google shows none. They are not separate rows and do not change positionarrayno[{"title": "Python Introduction", "url": "https://www.tutorialspoint.com/python/index.htm#introduction"}]
priceAlways null: the simple Google page has no pricestextalways null
countryCode, languageCodeCountry and language usedtextno"us", "en"
searchUrlGoogle page that was readtextno
statuscomplete, not_found or errortextnocomplete
statusReason, errorCodeReason for not_found/error rows or a note on a resulttextyesSOURCE_BLOCKED
fetchedAtWhen the page was read (ISO 8601)textno

null means Google did not show this value. It is not zero and not an error.

Output entities and surfaces

SituationWhereShapeWhat to do
Normal resultDatasetone row per result, status: completeUse type, position, url
No results for a queryDatasetone not_found rowCheck the query spelling or operators
Some queries failedDataset + RUN_SUMMARYerror rows, run status PARTIALRun the failed queries again
Query stopped after some pagesDataset + RUN_SUMMARYrows of the loaded pages, then one error row; query status partialRun this query again later
Run stopped by time or charge limitRUN_SUMMARYstatus CAPPED, rows so far are keptRaise the limit or split the queries

RUN_SUMMARY in the Key-value store has the run status (COMPLETE, PARTIAL, NO_RESULTS, CAPPED, ERROR), the stop reason, totals (pages, charged pages, rows, organic, ads (0 today), related, errors) and, per query, its status (results, partial, not_found, error, not_processed), pages and organic, ad and related counts.

The Apify run itself shows SUCCEEDED for COMPLETE, PARTIAL, NO_RESULTS and CAPPED. It shows FAILED when no query could be loaded or Google kept refusing; rows already saved stay in the Dataset.

Output example

Trimmed first row of a run for coffee machine (us/en, 1 page):

{
"query": "coffee machine",
"page": 1,
"type": "organic",
"position": 1,
"title": "Coffee & Espresso Makers | Macy's",
"url": "https://www.macys.com/shop/home/kitchen-dining/kitchen/coffee-espresso-makers?id=24732",
"displayedUrl": "www.macys.com › Home › Kitchen & Dining › All Kitchen",
"description": "Shop coffee makers at Macy's with stylish, high-quality ...",
"date": "Oct 9, 2026",
"sitelinks": [],
"price": null,
"countryCode": "us",
"languageCode": "en",
"searchUrl": "https://www.google.com/search?q=coffee+machine&hl=en&gl=us",
"status": "complete",
"statusReason": null,
"errorCode": null,
"fetchedAt": "2026-10-22T04:06:02.872Z"
}

A page usually returns 9–10 organic rows and about 8 related searches.

Moving from a one-row-per-page format

Some SERP tools save one row per page with nested lists. Here each result is its own row:

One-row-per-page fieldThis Actor
searchQuery.termquery
searchQuery.pagepage
organicResults[].title / url / displayedUrl / description / daterows with type: "organic", same field names
organicResults[].siteLinkssitelinks (when Google shows them)
paidResults[], paidProducts[]not available: no ad rows
relatedQueries[]rows with type: "related"

Pricing and limits

Pricing unit

You pay per loaded Google results page (serp-page) plus a small start fee per run. Organic results and related searches on that page are included. Platform usage (proxy, compute) is included in the price.

EventFreeBronzeSilverGold+
Run start (apify-actor-start)$0.004$0.004$0.004$0.004
Results page (serp-page)$0.002$0.0018$0.0017$0.0015
  • A query with no results costs one page: Google was asked and answered.
  • error rows (Google refused the page) are free.
  • If you set a maximum charge for the run, the Actor stops before it, keeps the rows and ends with status CAPPED.

Cost examples (Free plan)

ScenarioInput scopePagesCharge
Prefill1 query, 1 page1$0.006
Small keyword list10 queries, 1 page10$0.024
Top 100 for 10 keywords10 queries, 10 pages100$0.204
Large batch250 queries, 4 pages1,000$2.004
Query without results1 query1$0.006

Limits

  • Up to 500 queries and 10 pages per query in one run.
  • Run time depends on Google's answers: in the latest test, 40 pages took about 7 seconds without blocks. Very large runs were not measured on the current route, so start with a smaller list. After 3,600 seconds the run stops with status CAPPED and keeps all rows; split bigger lists across runs.
  • Google decides how many pages a query has; some queries end before page 10.

API, export and integrations

  • API: start the Actor with the same JSON input and read the Dataset items. See the API tab for ready code.
  • Export: download the Dataset as JSON, CSV, Excel or HTML from the Output tab.
  • Scheduling: create a Schedule with your keyword list to track rankings every day or week.

Use with AI agents (MCP)

  • MCP server with only this Actor: https://mcp.apify.com?tools=cliqtomedia/google-search-scraper
  • Smallest input:
{ "queries": ["apify web scraping"], "maxPagesPerQuery": 1 }
  • Key output fields: type (organic or related), position, title, url, description.
  • One query page takes a few seconds and costs $0.006 with the start fee. Keep maxPagesPerQuery low for quick answers.

Troubleshooting

Some queries have error rows with SOURCE_BLOCKED

Symptom: the run is PARTIAL, some queries have one error row. Likely reason: Google showed an "unusual traffic" page to all tried IP addresses. Check: statusReason and RUN_SUMMARY. Action: run only the failed queries again later. Error rows are not charged.

Fewer pages than maxPagesPerQuery

Symptom: a query has 3 pages, you asked for 10. Likely reason: Google has no next page for this query. Action: nothing to fix; only loaded pages are charged.

No ad rows

Symptom: includeAds is on, but there are no ad rows. Likely reason: Google's simple results page does not carry ads, so the Actor cannot read them. Action: use the organic rows; ad rows are not available. Empty sitelinks on a result means Google showed no sitelinks for it.

Results look different from my browser

Likely reason: your browser shows personalised results for your location and account. The Actor gets anonymous results for the chosen country.

FAQ

Do I need a Google account or API key?

No. The Actor reads public results pages without login or cookies of any account.

How many results do I get per page?

Usually 9–10 organic results and 8–10 related searches, depending on the query.

Is the order the same as on google.com?

position follows the order on the simple Google results page for the chosen country and language. It can differ a little from a personalised desktop page.

What does null mean?

Google did not show that value, for example no date. It is not zero and not an error.

Support

For bugs, questions or feature requests, open the Issues tab of this Actor. Add the run ID, your input (queries can be shortened) and the statusReason text. Never send tokens, cookies or passwords.