# Google Search Results Scraper — Cheaper SERP API (`prodiger/google-search-scraper`) Actor

Scrape Google Search result pages by query or URL. Extract organic results, related searches, People Also Ask, best-effort ads, and HTML snapshots. Slightly cheaper pay-per-event pricing than Apify's Google Search Results Scraper.

- **URL**: https://apify.com/prodiger/google-search-scraper.md
- **Developed by:** [Arnas](https://apify.com/prodiger) (community)
- **Categories:** SEO tools, Lead generation, Developer tools
- **Features:** Limited permissions
- **Stats:** 57 total users, 12 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 actor starts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Search Results Scraper — Cheaper SERP API

Scrape Google Search result pages by keyword or by a pasted Google Search URL. The actor returns one dataset record per SERP page with organic results, related queries, People Also Ask, best-effort paid ads/product ads, result counts, pagination metadata, and optional raw HTML snapshots.

It is designed as a cheaper, simpler alternative to `apify/google-search-scraper` for the common SEO and market research workflow: "give me Google SERP pages and the links on them." AI search add-ons and lead enrichment are intentionally out of scope so the per-page price can stay lower and predictable.

### Why use this actor

- **A little cheaper** — $4.20 per 1,000 scraped SERP pages before Apify subscription discounts, compared with Apify's current $4.50 per 1,000 Free-plan page price.
- **No paid-ads add-on fee** — best-effort ad extraction is included in the page event price.
- **Google URL or keyword input** — paste raw search terms or full `google.com/search?...` URLs.
- **Advanced search filters** — country, interface language, result language, exact-match, site/related filters, title/text/URL words, file types, and date filters.
- **Debuggable output** — optionally save raw HTML in the dataset or key-value store for parser inspection.
- **Compatible page-level shape** — one dataset item per SERP page with `searchQuery`, `organicResults`, `paidResults`, `paidProducts`, `relatedQueries`, and `peopleAlsoAsk`.

### Pricing

This actor uses Apify Pay-Per-Event pricing.

| Event | Price |
|---|---:|
| Actor start | $0.001 per run |
| Scraped SERP page | $0.0042 per successful Google results page |

Examples before subscription discounts:

| Workload | Cost |
|---|---:|
| 10 SERP pages | $0.043 |
| 1,000 SERP pages | $4.201 |
| 10,000 SERP pages | $42.001 |

Failed or blocked pages emit an error record but are not charged as scraped SERP pages.

### Input

```json
{
  "queries": "best SEO tools\nsite:apify.com google search scraper",
  "maxPagesPerQuery": 2,
  "resultsPerPage": 10,
  "countryCode": "us",
  "languageCode": "en",
  "mobileResults": false,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

`queries` accepts one item per line. Each item can be either a normal Google query or a full Google Search URL such as:

```text
https://www.google.com/search?q=hotels+in+Seattle&num=10
```

#### Proxies

If you omit `proxyConfiguration`, the actor uses Apify `RESIDENTIAL` proxies (in the country given by `countryCode`), falling back to `GOOGLE_SERP` if residential proxies are not available on the account. Residential is the recommended setup: pages are small (~60–80 KB), fast (1–3 s) and every blocked request is retried on a fresh IP.

`GOOGLE_SERP` is still supported. It is slower (often 5–60 s per page), and its result links are opaque Google redirects that the actor resolves with extra requests.

Pages that are not real results pages (Google homepage, consent screen, CAPTCHA, "enable JavaScript" interstitial, or results that ignore part of the query) are retried and, if they still fail, emitted as uncharged error records.

### Output

Each dataset item represents one SERP page:

```json
{
  "searchQuery": {
    "term": "best SEO tools",
    "url": "http://www.google.com/search?q=best+SEO+tools&num=10&start=0&hl=en&gl=us&pws=0",
    "device": "DESKTOP",
    "page": 1,
    "type": "SEARCH",
    "domain": "google.com",
    "countryCode": "US",
    "languageCode": "en",
    "locationUule": null,
    "resultsPerPage": 10
  },
  "url": "http://www.google.com/search?q=best+SEO+tools&num=10&start=0&hl=en&gl=us&pws=0",
  "hasNextPage": true,
  "serpProviderCode": "google.com",
  "resultsTotal": "About 1,230,000 results",
  "organicResults": [
    {
      "title": "Example result",
      "url": "https://example.com/",
      "displayedUrl": "example.com",
      "description": "Result snippet from Google.",
      "emphasizedKeywords": ["SEO tools"],
      "siteLinks": [],
      "productInfo": {},
      "type": "organic",
      "position": 1
    }
  ],
  "paidResults": [],
  "paidProducts": [],
  "relatedQueries": [],
  "peopleAlsoAsk": [],
  "suggestedResults": [],
  "customData": null,
  "aiOverview": "not-found",
  "#error": false
}
```

If Google returns a block page or a request fails after retries, the actor emits a page-level error record with `#error: true` and debug details. Error records are not charged as scraped pages.

### Notes and limitations

Google changes SERP markup frequently. This actor uses static HTML parsing for speed and price: with residential or custom proxies it requests Google's server-rendered basic HTML results page (`gbv=1`), which does not need JavaScript.

- Google no longer honours `num`, so each page has about 10 organic results whatever `resultsPerPage` is. Use `maxPagesPerQuery` for more.
- Google sometimes answers automated traffic with results for only part of the query (for example ignoring `site:`). The actor detects this and retries in verbatim mode (`tbs=li:1`). Pages 2+ and `GOOGLE_SERP` requests always use verbatim mode, so their ranking can differ slightly from a normal browser search.
- `mobileResults` only changes the `device` field in the output. The basic HTML page is the same for every device. It is best for organic/link extraction and lightweight ad monitoring. It does not provide bundled AI Mode, Perplexity, ChatGPT, Copilot, Gemini, lead enrichment, or email verification add-ons.

For large runs, lower `maxConcurrency` if error records increase. For strict quality validation, enable `saveHtmlToKeyValueStore` and compare parsed fields against the original HTML snapshots.

### Legal

Scrape only public data you have a legitimate reason to process. Google Search results can include personal data, snippets from copyrighted pages, and region-specific content. Follow applicable laws, Google terms, and privacy rules such as GDPR.

# Changelog

This Actor's version history is a separate document: https://apify.com/prodiger/google-search-scraper/changelog.md

# Actor input Schema

## `queries` (type: `string`):

One search query or Google Search URL per line. Advanced Google operators are supported directly in each query.

## `maxPagesPerQuery` (type: `integer`):

Maximum number of Google result pages to scrape for each query.

## `resultsPerPage` (type: `integer`):

Number of results requested from Google per SERP page (the num parameter). Google no longer honours num and returns about 10 organic results per page regardless; use Max pages per search to get more results.

## `countryCode` (type: `string`):

Country used for Google domain and the gl search parameter.

## `languageCode` (type: `string`):

Google interface language passed as the hl parameter.

## `searchLanguage` (type: `string`):

Restrict results to a language using Google's lr=lang\_ parameter. Leave empty for no restriction.

## `locationUule` (type: `string`):

Optional Google UULE location parameter for local SERPs.

## `forceExactMatch` (type: `boolean`):

Wrap each plain text query in quotes before applying other filters.

## `site` (type: `string`):

Limit results to a specific site, for example example.com.

## `relatedToSite` (type: `string`):

Find pages related to a specific site. Ignored when Site filter is set.

## `wordsInTitle` (type: `array`):

Adds intitle: filters to plain text queries.

## `wordsInText` (type: `array`):

Adds intext: filters to plain text queries.

## `wordsInUrl` (type: `array`):

Adds inurl: filters to plain text queries.

## `fileTypes` (type: `array`):

Adds filetype: filters. Multiple values are combined with OR.

## `quickDateRange` (type: `string`):

Google qdr value, such as d7, m6, or y1.

## `beforeDate` (type: `string`):

Filter results before this date. Use YYYY-MM-DD.

## `afterDate` (type: `string`):

Filter results after this date. Use YYYY-MM-DD.

## `mobileResults` (type: `boolean`):

Use a mobile user agent and mark output query metadata as MOBILE.

## `includeUnfilteredResults` (type: `boolean`):

Pass filter=0 to Google to include lower-quality omitted results.

## `focusOnPaidAds` (type: `boolean`):

Best-effort paid ad extraction. Unlike Apify's reference actor, this actor does not add a separate ads extraction charge.

## `saveHtml` (type: `boolean`):

Include raw SERP HTML in dataset records.

## `saveHtmlToKeyValueStore` (type: `boolean`):

Save raw SERP HTML to the default key-value store and include htmlSnapshotUrl in dataset records.

## `renderJavascriptOnBlock` (type: `boolean`):

Deprecated and ignored. Google now requires JavaScript for its normal results page and blocks headless browsers, so the actor fetches Google's server-rendered basic HTML results page instead and retries blocked pages with a fresh proxy session.

## `maxConcurrency` (type: `integer`):

Maximum parallel SERP requests.

## `requestRetries` (type: `integer`):

Retries per SERP page before an error record is emitted. Blocked, CAPTCHA, consent, homepage and off-query pages are retried with a new proxy session and are never charged.

## `proxyConfiguration` (type: `object`):

Apify Proxy or custom proxy configuration. Leave empty to use Apify RESIDENTIAL proxies (recommended; falls back to GOOGLE_SERP if residential proxies are unavailable). GOOGLE_SERP is supported but slower.

## Actor input object example

```json
{
  "queries": "best SEO tools\nsite:apify.com google search scraper",
  "maxPagesPerQuery": 1,
  "resultsPerPage": 10,
  "countryCode": "us",
  "languageCode": "en",
  "forceExactMatch": false,
  "wordsInTitle": [],
  "wordsInText": [],
  "wordsInUrl": [],
  "fileTypes": [],
  "mobileResults": false,
  "includeUnfilteredResults": false,
  "focusOnPaidAds": true,
  "saveHtml": false,
  "saveHtmlToKeyValueStore": false,
  "renderJavascriptOnBlock": true,
  "maxConcurrency": 5,
  "requestRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Scraped Google Search result pages.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": `best SEO tools
site:apify.com google search scraper`,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("prodiger/google-search-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": """best SEO tools
site:apify.com google search scraper""",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("prodiger/google-search-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": "best SEO tools\\nsite:apify.com google search scraper",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call prodiger/google-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,prodiger/google-search-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/z1DkqP2QiqTdkM2bT/builds/AELZyhZ9Ycwe50Eks/openapi.json
