# Google Search Results (SERP) & Ads Scraper (`scrapeforgehq/google-serp-scraper`) Actor

Scrape Google SERPs at scale: paid ads (headline, copy, displayed/final URL), organic results, People Also Ask, and related searches — by keyword, country, language, and device. Clean JSON output for SEO, PPC, and competitor ad research.

- **URL**: https://apify.com/scrapeforgehq/google-serp-scraper.md
- **Developed by:** [ScrapeForge](https://apify.com/scrapeforgehq) (community)
- **Categories:** SEO tools, Marketing, Lead generation
- **Stats:** 3 total users, 2 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 (SERP) & Ads Scraper

**Turn any keyword list into clean, structured Google SERP data — paid ads,
organic results, People Also Ask, and related searches — as analysis-ready
JSON.** Built for marketers, SEO/PPC agencies, and competitive-intelligence
teams who need to know who's bidding on a keyword, what their ad copy says, and
how the whole results page looks — without searching Google by hand.

Runs on desktop or mobile, for any country and language, and returns one tidy
row per query per page.

### What you get

- **Paid ads** — headline, description, displayed URL, final URL, and position
- **Organic results** — title, URL, snippet, and position
- **People Also Ask** — the questions Google surfaces for the query
- **Related searches** — the suggestions at the foot of the SERP
- A consistent JSON schema, ready for a spreadsheet, a dashboard, or a diff
  against last week's run

### Why this scraper (the edge over other Google SERP actors)

This category is crowded, but most actors in it share the same complaints: runs
that die on a consent screen, and empty results when Google shifts its markup.
This one is built to fix exactly those:

- **It doesn't crash on block pages.** Google's consent interstitials and
  "unusual traffic" walls are handled gracefully: the row is marked
  `blocked: true`, a page snapshot is saved for debugging, and the run keeps
  going instead of failing outright.
- **Ads *and* organic *and* PAA *and* related — in one pass.** Many actors give
  you only organic results or only ads. This returns the full competitive
  picture for each keyword.
- **Device- and locale-aware.** Ad placement and layout differ a lot between
  desktop and mobile and across countries — this honors `device`,
  `countryCode`, and `languageCode` so you see what a real searcher there sees.
- **Resilient, documented selectors.** All parsing is isolated in one file that
  targets stable page landmarks (ad rails, headings, ARIA labels) instead of
  Google's rotating class names — so when Google changes, fixes ship fast.
- **Honest scope.** Real ad copy and placement only — no invented "bid" or
  "spend" estimates dressed up as data.

### Use cases

1. **Competitor ad monitoring** — run the same keyword list on a schedule
   (weekly, daily) and diff the `ads` array to see who started or stopped
   bidding and how their copy changed.
2. **Keyword & SERP research** — one-off pulls of the full competitive
   landscape (ads + organic + PAA) before a campaign or a content push.
3. **Ad-copy swipe file** — bulk-collect real, currently-running ad headlines
   and descriptions in a niche for copywriting inspiration.
4. **Share-of-voice tracking** — measure how often each competitor appears
   across a keyword set, on desktop vs. mobile.
5. **Content & SEO planning** — mine People Also Ask and related searches for
   questions and topics to cover.
6. **Local & multi-market checks** — compare the same queries across countries
   and languages to see how ads and rankings shift by market.

### Input

Provide a list of `queries`; everything else is optional with sensible defaults.

```json
{
  "queries": ["crm for small business", "project management software"],
  "countryCode": "us",
  "languageCode": "en",
  "device": "desktop",
  "maxPagesPerQuery": 1
}
```

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `queries` | array of strings | — (required) | One or more search terms; each scraped as its own SERP. |
| `countryCode` | string | `us` | Google `gl` parameter (`us`, `gb`, `ph`, …). |
| `languageCode` | string | `en` | Google `hl` parameter (`en`, `es`, `fr`, …). |
| `device` | `desktop` | `mobile` | `desktop` | Ad placement and layout differ by device. |
| `maxPagesPerQuery` | integer 1–5 | `1` | SERP pages per query (10 results each). |
| `extractAds` / `extractOrganic` / `extractPaa` / `extractRelatedSearches` | boolean | `true` | Toggle each section on or off. |

### Output

One dataset row per query per page:

```json
{
  "query": "crm for small business",
  "page": 1,
  "countryCode": "us",
  "languageCode": "en",
  "device": "desktop",
  "scrapedAt": "2026-09-27T10:00:00.000Z",
  "ads": [{ "position": 1, "headline": "...", "description": "...", "displayedUrl": "example.com", "finalUrl": "https://example.com/..." }],
  "organic": [{ "position": 1, "title": "...", "url": "https://...", "snippet": "..." }],
  "peopleAlsoAsk": ["..."],
  "relatedSearches": ["..."]
}
```

If Google serves a block/CAPTCHA page, the row is still emitted with
`"blocked": true` and empty arrays, and a snapshot of the page HTML is saved to
the run's key-value store for debugging. An empty `ads` array is also normal —
not every keyword has ads running.

### Pricing

**$2.50 per 1,000 results** — pay-per-result, no subscription. One result = one
SERP (one query, one page), so 500 keywords at one page each = **$1.25**.

### FAQ

**What counts as a "result"?**
One result is one SERP — a single query on a single page. `maxPagesPerQuery: 2`
over 100 queries = 200 results.

**Do I need my own proxies?**
No. It defaults to Apify's `GOOGLE_SERP` residential proxy group, tuned for
Google. You can supply your own proxy configuration if you prefer.

**Can it scrape mobile SERPs?**
Yes — set `device: "mobile"`. Ad slots and layout differ from desktop, and the
scraper matches its browser fingerprint to the device you pick.

**Which countries and languages are supported?**
Any Google market — set `countryCode` (e.g. `us`, `gb`, `ph`) and
`languageCode` (e.g. `en`, `es`). Ads and rankings are localized accordingly.

**How many keywords can I run at once?**
As many as you like — pass a large `queries` array. Very high volumes may
occasionally hit rate limits even on residential proxies; blocked pages are
skipped rather than failing the run.

**Does it return ad spend or bid amounts?**
No. Google doesn't expose that publicly, and this scraper won't fabricate it.
You get real ad copy, URLs, and placement only.

**Can I schedule it?**
Yes — use Apify Schedules to run your keyword list on a cadence and diff the
results over time for competitor monitoring.

**What happens when Google changes its page markup?**
All parsing lives in one isolated file built around stable landmarks, so fixes
are quick to ship. If extraction ever looks off, report it and it gets patched.

**Is scraping Google allowed?**
Google's Terms restrict automated querying. This actor follows the same pattern
as other published Google Search/Maps/Trends scrapers on the Apify Store and is
intended for research and monitoring, not high-volume redistribution.

### Tech

Node.js + [Crawlee](https://crawlee.dev) `PlaywrightCrawler`, on Apify's
official `apify/actor-node-playwright-chrome` base image, with browser
fingerprint generation matched to the requested device.

# Actor input Schema

## `queries` (type: `array`):

One or more search queries to run. Each is scraped as a separate Google SERP.

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

Two-letter country code Google should localize results for, e.g. us, gb, ph.

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

Two-letter language code, e.g. en, es, fr.

## `device` (type: `string`):

Ad placements and SERP layout differ significantly between desktop and mobile.

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

Number of SERP pages (10 organic results each) to fetch per query.

## `extractAds` (type: `boolean`):

Extract paid (sponsored) ad results, including headline, description, and displayed/final URLs.

## `extractOrganic` (type: `boolean`):

Extract standard organic search results, including title, URL, and snippet.

## `extractPaa` (type: `boolean`):

Extract the 'People Also Ask' questions shown on the SERP.

## `extractRelatedSearches` (type: `boolean`):

Extract the 'Related searches' suggestions shown at the bottom of the SERP.

## `debugSnapshot` (type: `boolean`):

Save the rendered HTML of each SERP to the key-value store (SNAPSHOT-<query>-p<page>). Useful for fixing selectors when extraction breaks; leave off for normal runs.

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

Google aggressively blocks datacenter IPs. Use the GOOGLE\_SERP proxy group (Apify residential proxies tuned for Google) for reliable results.

## Actor input object example

```json
{
  "queries": [
    "project management software",
    "crm for small business"
  ],
  "countryCode": "us",
  "languageCode": "en",
  "device": "desktop",
  "maxPagesPerQuery": 1,
  "extractAds": true,
  "extractOrganic": true,
  "extractPaa": true,
  "extractRelatedSearches": true,
  "debugSnapshot": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All extracted ads, organic results, People Also Ask, and related searches.

# 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": [
        "project management software",
        "crm for small business"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapeforgehq/google-serp-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": [
        "project management software",
        "crm for small business",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapeforgehq/google-serp-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": [
    "project management software",
    "crm for small business"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}' |
apify call scrapeforgehq/google-serp-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapeforgehq/google-serp-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/JcacvpwYTFfkYrQ7v/builds/mMKnjzYCcMVemVT4w/openapi.json
