# Google SERP & SEO Scraper (`dxbear/google-serp-seo-scraper`) Actor

Scrape Google SERPs for organic rankings, paid ads, AI Overview, People Also Ask & keyword SEO metrics. Track competitors, domain traffic & ad spend. no proxies or CAPTCHAs. Perfect for SEO agencies, marketers & developers.

- **URL**: https://apify.com/dxbear/google-serp-seo-scraper.md
- **Developed by:** [Dxbear](https://apify.com/dxbear) (community)
- **Categories:** SEO tools, Automation, Lead generation
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $5.00 / 1,000 scraped search result pages

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## 🔍 Google SERP & SEO Scraper

![enter image description here](https://raw.githubusercontent.com/dx-bear/apify-actors-imgs/refs/heads/main/google-search-seo-scraper-banner2.png)

  

**A reliable Google search results scraper and SEO data API for developers, marketers, and growth teams.**

Google SERP tool handles web scraping Google search results for you. scrape organic rankings, paid ads, AI Overview, "People Also Ask," related searches, keyword difficulty scores, competitor rankings, domain traffic history, and advertiser intelligence, all returned as structured, ready-to-use JSON from a single API call.

Whether you're building a competitor keyword research tool, tracking rankings at scale, or just need clean SERP data without the infrastructure headache — no proxies to manage, no CAPTCHAs to solve, no HTML to parse. Just clean data.

---


### 🚀 What This Google SERP Scraper Does
 
Use this actor as your **rank tracking API** and **SEO data API** in one — every keyword you run returns a full SEO and SERP data package, no manual searching required:
 
| 📦 Data Point | 📝 What You Get |
|---|---|
| 🤖 **AI Overview** | Full text of Google's AI-generated answer box |
| 🏆 **Organic Search Results** | Ranked positions, titles, URLs, and snippets |
| 💰 **Paid / Sponsored Ads** | Scrape Google Ads copy, display URLs, and advertiser domains directly from live SERPs |
| ❓ **People Also Ask (PAA)** | Related questions Google surfaces for the query |
| 🔗 **Related Searches** | Suggested keyword variations at the bottom of the SERP |
| 📊 **Keyword SEO Metrics** | Keyword difficulty, click potential, domain diversity, top-100 breakdown |
| 🥇 **Competitor Ranking Analysis** | Built-in **competitor keyword research tool** data — who ranks where, position changes, estimated traffic value per competitor |
| 📈 **Domain Traffic Insights** | Historical organic/paid traffic, ad spend, and domain authority trends |
| 🗂️ **Historical Ad Archive** | Past ad creatives run against a keyword, with dates and advertiser domains |
| 📢 **Active Advertiser Domains** | Every domain currently bidding on a keyword |
 
Every field is documented in the [dataset schema](.actor/dataset_schema.json), and every field gracefully handles missing data — so your pipeline never breaks on an empty AI Overview or a keyword with no paid ads.


> **📍 Note:** `keyword_seo_metrics`, `serp_competitor_analysis`, `domain_traffic_insights`, `historical_paid_advertisements`, and `active_advertiser_domains` (the SEO/competitor intelligence fields) are currently available for **32 countries**. Other supported countries still return full SERP data (organic, ads, AI Overview, PAA, related searches) — just without SEO metrics.
 
### ⚙️ How It Works
 
1. **Input** your target keyword(s), along with optional location, language, and device settings
2. The actor requests the live Google SERP and parses every feature block.
3. **Output** lands in your Apify dataset — one structured item per keyword — ready to export or query via API
```json
{
  "ai_summary": "<string|null>",

  "organic_search_results": [
    {
      "name": "<string|null>",
      "link": "<string|null (uri)>",
      "text": "<string|null>",
      "position": "<integer|null>"
    }
  ],

  "paid_sponsored_results": [
    {
      "position": "<integer|null>",
      "title": "<string|null>",
      "displayUrl": "<string|null>",
      "url": "<string|null>",
      "domain": "<string|null>",
      "description": "<string|null>"
    }
  ],

  "frequently_asked_questions": [
    {
      "position": "<integer|null>",
      "question": "<string|null>"
    }
  ],

  "related_search_queries": [
    {
      "position": "<integer|null>",
      "text": "<string|null>",
      "link": "<string|null>"
    }
  ],

  "extracted_links": ["<string (uri)>"],

  "extracted_domains": ["<string>"],

  "raw_html_content": "<string|null>",

  "keyword_seo_metrics": {
    "keywordSEODifficulty": "<number|null>",
    "top100NumberOfHomepages": "<integer|null>",
    "top100GovEduMilDomains": "<integer|null>",
    "top100TitleContainsKeyword": "<integer|null>",
    "top100UrlContainsKeyword": "<integer|null>",
    "maxOrganicMonthlyClicks": "<number|null>",
    "maxOrganicMonthlyValue": "<number|null>",
    "top100DomainDiversity": "<number|null>",
    "top100Wiki": "<boolean|null>",
    "top100Facebook": "<boolean|null>",
    "top100Twitter": "<boolean|null>",
    "top100YouTube": "<boolean|null>",
    "top100Pinterest": "<boolean|null>",
    "top100Tumblr": "<boolean|null>",
    "top100LinkedIn": "<boolean|null>"
  },

  "serp_competitor_analysis": [
    {
      "keyword": "<string|null>",
      "domain": "<string|null>",
      "url": "<string|null>",
      "title": "<string|null>",
      "domainAppearances": "<integer|null>",
      "position": "<integer|null>",
      "positionChange": "<integer|null>",
      "searchVolume": "<number|null>",
      "totalMonthlyClicks": "<number|null>",
      "totalHomepages": "<integer|null>",
      "estimatedOrganicClicks": "<number|null>",
      "estimatedClickValue": "<number|null>",
      "rankingDifficulty": "<number|null>",
      "dateSearched": "<string|null (date-time)>",
      "uri": "<string|null (uri)>"
    }
  ],

  "domain_traffic_insights": [
    {
      "domain": "<string|null>",
      "domainStats": [
        {
          "searchDate": {
            "dateString": "<string|null>",
            "month": "<integer|null>",
            "year": "<integer|null>"
          },
          "averageOrganicRank": "<number|null>",
          "monthlyPaidClicks": "<number|null>",
          "averageAdRank": "<number|null>",
          "totalOrganicResults": "<number|null>",
          "monthlyBudget": "<number|null>",
          "monthlyOrganicValue": "<number|null>",
          "totalAdsPurchased": "<number|null>",
          "monthlyOrganicClicks": "<number|null>",
          "strength": "<number|null>",
          "totalInverseRank": "<number|null>",
          "hasData": "<boolean|null>"
        }
      ],
      "totalResults": "<integer|null>"
    }
  ],

  "historical_paid_advertisements": [
    {
      "keyword": "<string|null>",
      "position": "<integer|null>",
      "totalAds": "<integer|null>",
      "dateSearched": "<string|null (date-time)>",
      "title": "<string|null>",
      "bodyHtml": "<string|null>",
      "displayUrl": "<string|null>",
      "url": "<string|null>",
      "domain": "<string|null>",
      "searchVolume": "<number|null>",
      "keywordDifficulty": "<number|null>",
      "countryCode": "<string|null>",
      "costPerClick": "<number|null>",
      "isNsfw": "<boolean|null>"
    }
  ],

  "active_advertiser_domains": ["<string>"]
}
````

***

### ⚡ Getting Started

Ready to try this Google search results scraper? You'll be scraping your first SERP in under two minutes and Apify gives every new account **$5 in free credits**, so you can test it at zero cost.

1. **Create a free Apify account** — you'll get $5 in credits automatically, no card required
2. **Open the actor** at `apify.com/dxbear/Google-SERP-SEO-Scraper`, or just hit **Try for free**
3. **Go to the Input tab** and fill in your query. Here's a working example:

```json
{
    "country": "US",
    "includeSerpSeoData": true,
    "language": "en",
    "page": 10,
    "query": "Email Marketing",
    "returnRawHtml": false
}
```

4. There are also **`location`** and **`uule`** fields for advanced geo-targeting. you can leave these empty for now, they're optional
5. Click **Run**
   That's it. Within seconds you'll have a full SEO data API response for your keyword — organic rankings, paid ads, AI Overview, and every other data point covered below — landing straight in your dataset.

#### 🧾 Input Fields Explained

Every field you can configure on the Input tab, what it does, and when to use it:

| Field | Type | Required | What It Does |
|---|---|---|---|
| 🔍 **`query`** | string | ✅ Yes | Your search term — anything you'd type into Google (e.g. `"best proxy"`). This is the only required field. |
| 📱 **`device`** | select | Optional | Simulates **Desktop** or **Mobile** search results. Google serves different SERP layouts and features depending on device, so pick the one matching your target audience. Defaults to `desktop`. |
| 📄 **`page`** | integer (1–10) | Optional | Number of result pages to scrape. `1` returns just the first page; higher values page deeper into results for more organic listings. Defaults to `1`. |
| 🌍 **`language`** | select | Optional | Two-letter language code (`en`, `fr`, `de`, `es`, etc.) that controls the language Google returns results in. Defaults to `en` (English). 27 languages are supported. |
| 🗺️ **`country`** | select | Optional | Two-letter country code that controls which country's Google index and localized results you're querying. Defaults to `US`. This actor supports 90+ countries for standard SERP scraping — see the full list in the actor's country selector. Note: **SEO metrics** (via `includeSerpSeoData`) are limited to 32 of these countries — see the note below the feature table. |
| ⏱️ **`timeFilter`** | select | Optional | Restricts results to a specific freshness window: past hour, day, week, month, or year. Leave empty (`""`) for **Any time** — the default — if you don't need to filter by recency. |
| 📍 **`uule`** | string | Optional | Google's UULE parameter for pinpoint geographic targeting (encodes an exact physical location, down to the city/neighborhood level). Use this if you need hyper-local results beyond what `country` alone provides. Leave blank if not needed. |
| 🏙️ **`location`** | string | Optional | A human-readable location name (e.g. `"New York, NY"`) for localized results — a simpler alternative to `uule` when you don't have a pre-encoded UULE string. Leave blank if not needed. |
| 🗂️ **`returnRawHtml`** | boolean | Optional | When `true`, includes the raw, unparsed HTML of the Google SERP in the output — useful for debugging or building your own custom parser on top of this actor's results. Defaults to `false`. Adds significant payload size, so only enable it if you need it. |
| 📊 **`includeSerpSeoData`** | boolean | Optional | When `true`, adds keyword SEO metrics, competitor rankings, domain traffic history, ad archive, and active advertiser data to the output. ⚠️ Only available for 32 supported countries (see the note below the feature table) — results may be incomplete or unavailable elsewhere. Defaults to `false`. |

> 💡 **Tip:** The only field you *must* set is `query`. Everything else has a sensible default, so you can start with a minimal input like `{ "query": "best proxy" }` and add fields as you need more control.

***

***

### 🌍 Supported SEO Data Countries (32)

- 🇺🇸 `US` — United States
- 🇬🇧 `UK` — United Kingdom
- 🇩🇪 `DE` — Germany
- 🇫🇷 `FR` — France
- 🇦🇷 `AR` — Argentina
- 🇦🇹 `AT` — Austria
- 🇦🇺 `AU` — Australia
- 🇧🇪 `BE` — Belgium
- 🇧🇷 `BR` — Brazil
- 🇨🇦 `CA` — Canada
- 🇨🇱 `CL` — Chile
- 🇨🇿 `CZ` — Czech Republic
- 🇩🇰 `DK` — Denmark
- 🇫🇮 `FI` — Finland
- 🇮🇳 `IN` — India
- 🇮🇪 `IE` — Ireland
- 🇮🇹 `IT` — Italy
- 🇯🇵 `JP` — Japan
- 🇲🇽 `MX` — Mexico
- 🇳🇱 `NL` — Netherlands
- 🇳🇿 `NZ` — New Zealand
- 🇳🇴 `NO` — Norway
- 🇵🇱 `PL` — Poland
- 🇵🇹 `PT` — Portugal
- 🇸🇬 `SG` — Singapore
- 🇿🇦 `ZA` — South Africa
- 🇪🇸 `ES` — Spain
- 🇸🇪 `SE` — Sweden
- 🇨🇭 `CH` — Switzerland
- 🇹🇷 `TR` — Turkey
- 🇺🇦 `UA` — Ukraine
- 🇻🇪 `VE` — Venezuela

***

### 📤 Example Output

Once your run finishes, every keyword you scrape lands in your dataset as one structured item — clean JSON you can query, export, or pipe into your own tool. Raw HTML is excluded by default; it's only included if you enable the `returnRawHtml` input option.

Here's what a real run for the keyword **"Email Marketing"** produced:

![SERP scrape overview screenshot](https://raw.githubusercontent.com/dx-bear/apify-actors-imgs/refs/heads/main/google-search-seo-scraper-output-0.png)
![Dataset output screenshot](https://raw.githubusercontent.com/dx-bear/apify-actors-imgs/refs/heads/main/google-search-scraper-output-1.png)

#### 📝 Example data (trimmed)

**AI Overview:**

> Email marketing is a digital strategy that involves sending targeted commercial messages to customers who have opted in to receive them...

**Top organic results:**

| Position | Title | URL |
|---|---|---|
| 1 | Email Marketing: Everything you need to know | mailchimp.com/marketing-glossary/email-marketing |
| 2 | What Is Email Marketing? Benefits + Best Practices | coursera.org/articles/email-marketing |
| 7 | Email marketing | en.wikipedia.org/wiki/Email\_marketing |

**Paid ads captured on the same SERP:**

| Advertiser | Domain |
|---|---|
| Constant Contact | constantcontact.com |
| ActiveCampaign | activecampaign.com |
| Braze | braze.com |

**Keyword SEO metrics:**

| Metric | Value |
|---|---|
| Keyword difficulty | 32 / 100 |
| Max organic monthly clicks | 3,500 |
| Domain diversity | 0.53 |

**People Also Ask:**

- How do I start email marketing?
- What is the best free email marketing?
- What does email marketing do?
- Can I earn from email marketing?

#### 💻 JSON output example

```json
{
  "ai_summary": "Email marketing is a digital strategy that involves sending targeted commercial messages to customers who have opted in to receive them...",
  "organic_search_results": [
    {
      "name": "Email Marketing: Everything you need to know",
      "link": "https://mailchimp.com/marketing-glossary/email-marketing/",
      "position": 1
    },
    {
      "name": "Email marketing",
      "link": "https://en.wikipedia.org/wiki/Email_marketing",
      "position": 7
    }
  ],
  "paid_sponsored_results": [
    {
      "title": "Email Marketing",
      "url": "https://www.constantcontact.com/landing7/email-marketing-campaign",
      "domain": "constantcontact.com",
      "description": "Constant Contact® Email Marketing That Works — Send Better Emails, Grow Your Email List, And Get More Leads."
    }
  ],
  "keyword_seo_metrics": {
    "keywordSEODifficulty": 32,
    "maxOrganicMonthlyClicks": 3500,
    "top100DomainDiversity": 0.5263
  },
  "frequently_asked_questions": [
    { "position": 1, "question": "How do I start email marketing?" },
    { "position": 2, "question": "What is the best free email marketing?" }
  ]
}
```

Results are available as **JSON**, **JSONL**, **CSV**, or **Excel (XLSX)** — or query the dataset directly via the Apify API.

***

### 📋 Output Fields Reference

Every field in the dataset, fully documented. All fields are nullable and default to an empty value if that SERP feature wasn't present on the page — so a missing AI Overview or an empty ad list will never break your pipeline.

#### 🤖 `ai_summary`

| Field | Type | Description |
|---|---|---|
| `ai_summary` | `string \| null` | Raw text of Google's AI Overview / featured snippet block for the query, including embedded source labels. `null` if no AI Overview was present on the SERP. |

#### 🏆 `organic_search_results` (array)

| Field | Type | Description |
|---|---|---|
| `name` | `string \| null` | Result title as displayed on the SERP. |
| `link` | `string \| null` | Destination URL of the result. |
| `text` | `string \| null` | Snippet/description text shown under the result. May contain truncation markers. |
| `position` | `integer \| null` | 1-indexed organic rank position on the page. |

#### 💰 `paid_sponsored_results` (array)

| Field | Type | Description |
|---|---|---|
| `position` | `integer \| null` | Ad's rank position on the SERP. |
| `title` | `string \| null` | Ad headline text. |
| `displayUrl` | `string \| null` | Human-readable display URL shown in the ad. |
| `url` | `string \| null` | Actual destination/landing URL. |
| `domain` | `string \| null` | Advertiser's root domain. |
| `description` | `string \| null` | Ad body copy. |

`null` or an empty array when no ads were shown for this query/location/session.

#### ❓ `frequently_asked_questions` (array) — "People Also Ask"

| Field | Type | Description |
|---|---|---|
| `position` | `integer \| null` | 1-indexed display order of the question in the PAA box. |
| `question` | `string \| null` | The full question text as shown by Google. |

#### 🔗 `related_search_queries` (array)

| Field | Type | Description |
|---|---|---|
| `position` | `integer \| null` | 1-indexed display order. |
| `text` | `string \| null` | The suggested search phrase. |
| `link` | `string \| null` | Relative or absolute Google search URL for this related query. |

#### 🌐 `extracted_links` / `extracted_domains`

| Field | Type | Description |
|---|---|---|
| `extracted_links` | `array<string> \| null` | Flat, deduplicated list of every outbound URL found across all SERP features on the page. |
| `extracted_domains` | `array<string> \| null` | Flat, deduplicated list of root domains parsed from `extracted_links`. |

#### 🗂️ `raw_html_content`

| Field | Type | Description |
|---|---|---|
| `raw_html_content` | `string \| null` | Full raw HTML of the fetched SERP page — only populated if `returnRawHtml` was enabled on input. `null` by default to keep dataset size small. |

#### 📊 `keyword_seo_metrics` (object)

> ⚠️ Only populated when `includeSerpSeoData` is enabled on input, and only for [supported countries](#-what-this-google-serp-scraper-does).

| Field | Type | Description |
|---|---|---|
| `keywordSEODifficulty` | `number \| null` (0–100) | Composite difficulty score estimating how hard it is to rank organically for this keyword. |
| `top100NumberOfHomepages` | `integer \| null` | Count of homepage URLs (root domain only) within the top 100 ranking results. |
| `top100GovEduMilDomains` | `integer \| null` | Count of `.gov` / `.edu` / `.mil` domains within the top 100 results. |
| `top100TitleContainsKeyword` | `integer \| null` | Count of top-100 results whose page title contains the exact keyword. |
| `top100UrlContainsKeyword` | `integer \| null` | Count of top-100 results whose URL contains the exact keyword. |
| `maxOrganicMonthlyClicks` | `number \| null` | Estimated maximum monthly organic clicks achievable for the #1 ranking position. |
| `maxOrganicMonthlyValue` | `number \| null` | Estimated USD value of maximum monthly organic traffic, based on CPC. |
| `top100DomainDiversity` | `number \| null` (0–1) | Ratio of unique domains to total results in the top 100 — higher means less domain concentration. |
| `top100Wiki` / `top100Facebook` / `top100Twitter` / `top100YouTube` / `top100Pinterest` / `top100Tumblr` / `top100LinkedIn` | `boolean \| null` | Whether a result from that platform appears in the top 100. |

#### 🥇 `serp_competitor_analysis` (array)

| Field | Type | Description |
|---|---|---|
| `keyword` | `string \| null` | The keyword this ranking data applies to. |
| `domain` | `string \| null` | Root domain of the ranking competitor. |
| `url` | `string \| null` | Exact ranking URL. |
| `title` | `string \| null` | Page title of the ranking result. |
| `domainAppearances` | `integer \| null` | Number of times this domain appears anywhere in the tracked result set. |
| `position` | `integer \| null` | Current organic rank position. |
| `positionChange` | `integer \| null` | Change in rank position since the previous tracked check (positive = moved up). |
| `searchVolume` | `number \| null` | Estimated monthly search volume for the keyword. |
| `totalMonthlyClicks` | `number \| null` | Estimated total monthly clicks across all results for this keyword. |
| `totalHomepages` | `integer \| null` | Count of homepage-only URLs in the tracked result set. |
| `estimatedOrganicClicks` | `number \| null` | Estimated monthly organic clicks this specific result receives. |
| `estimatedClickValue` | `number \| null` | Estimated USD value per click (CPC-derived) for this position. |
| `rankingDifficulty` | `number \| null` (0–100) | Difficulty score for ranking at this position. |
| `dateSearched` | `string \| null` (date-time) | Timestamp this ranking snapshot was captured. May be a placeholder epoch value if unavailable. |
| `uri` | `string \| null` | Canonical URI, typically identical to `url`. |

#### 📈 `domain_traffic_insights` (array)

| Field | Type | Description |
|---|---|---|
| `domain` | `string \| null` | The domain this traffic data applies to. |
| `domainStats` | `array` | List of monthly traffic snapshots (see below). |
| `totalResults` | `integer \| null` | Total number of results recorded for this domain. |

**Each `domainStats` entry contains:**

| Field | Type | Description |
|---|---|---|
| `searchDate` | `object \| null` | `{ dateString, month, year }` — the period this snapshot covers. |
| `averageOrganicRank` | `number \| null` | Domain's average organic ranking position that month. |
| `monthlyPaidClicks` | `number \| null` | Estimated monthly clicks from paid ads. |
| `averageAdRank` | `number \| null` | Domain's average paid ad position that month. |
| `totalOrganicResults` | `number \| null` | Total organic results the domain appeared in. |
| `monthlyBudget` | `number \| null` | Estimated monthly paid-ad spend in USD. |
| `monthlyOrganicValue` | `number \| null` | Estimated USD value of monthly organic traffic. |
| `totalAdsPurchased` | `number \| null` | Total number of ads purchased that month. |
| `monthlyOrganicClicks` | `number \| null` | Estimated monthly clicks from organic results. |
| `strength` | `number \| null` (0–100) | Composite domain authority/strength score. |
| `totalInverseRank` | `number \| null` | Aggregate inverse-rank metric (higher favors better average positions). |
| `hasData` | `boolean \| null` | Whether real data was found for this domain/period. |

#### 🗃️ `historical_paid_advertisements` (array)

| Field | Type | Description |
|---|---|---|
| `keyword` | `string \| null` | The keyword this historical ad ran against. |
| `position` | `integer \| null` | Ad's rank position at capture time. |
| `totalAds` | `integer \| null` | Total number of ad extensions/sitelinks bundled with this ad. |
| `dateSearched` | `string \| null` (date-time) | When this ad creative was captured. |
| `title` | `string \| null` | Ad headline text. |
| `bodyHtml` | `string \| null` | Raw HTML markup of the ad body/extensions as rendered at capture time. |
| `displayUrl` | `string \| null` | Human-readable display URL shown in the ad. |
| `url` | `string \| null` | Actual destination/landing URL (may be a Google redirect wrapper). |
| `domain` | `string \| null` | Advertiser's root domain. Empty string if unresolvable (e.g. `about:blank`). |
| `searchVolume` | `number \| null` | Estimated monthly search volume at time of capture. |
| `keywordDifficulty` | `number \| null` (0–100) | Difficulty score at time of capture. |
| `countryCode` | `string \| null` | ISO country code the ad was captured in. |
| `costPerClick` | `number \| null` | Estimated CPC for this ad, where available. |
| `isNsfw` | `boolean \| null` | Whether the ad creative was flagged NSFW. |

#### 📢 `active_advertiser_domains` (array)

| Field | Type | Description |
|---|---|---|
| `active_advertiser_domains` | `array<string> \| null` | Flat list of domains currently bidding on this keyword. May contain duplicates, which reflect ad frequency/weight rather than being a data error. |

***

***

## Pricing

Google-SERP-SEO-Scraper uses simple, pay-per-result pricing. There are no subscriptions and no hidden fees — you only pay for what you scrape.

| Pricing | Free | Starter | Scale | Business |
|---|---|---|---|---|
| **Discount tier** | No discount | Bronze discount | Silver discount | Gold discount |
| **Scraped search result page** *(per 1,000)* | $5.00 | $5.00 | $5.00 | $5.00 |
| **Full SEO data** *(per run)* | $0.015 | $0.013 | $0.012 | $0.010 |
| **Actor start** *(per run)* | $0.001 | $0.0008 | $0.0007 | $0.0006 |
| **Platform usage** | Free ✅ | Free ✅ | Free ✅ | Free ✅ |

### How the pricing works

**Scraped search result page — $5.00 / 1,000 pages**
This is the core cost. You pay per search result page scraped, billed at a rate of $5.00 per 1,000 pages (i.e. $0.005 per page). Your discount tier doesn't change this rate — it's the same across all plans.

**Full SEO data — charged once per run, not per page**
This is a flat, one-time fee applied **once per Actor run**, regardless of how many pages you scrape in that run. Whether you scrape 1 page or 10 pages in a single run, you only pay this fee **one time** — it does not multiply per page. The rate drops as your discount tier increases (from $0.015 down to $0.010).

**Actor start — charged once per run**
Same principle as above: a small, flat fee for starting the Actor, charged once per run no matter how many pages are processed in that run.

**Platform usage — always free**
Unlike most Actors on the platform, you are **not charged for compute, memory, or platform usage**. This is fully included at no extra cost across every tier — so your total cost is just the sum of the page-scraping fee plus the one-time per-run fees above.

### Example

If you run the Actor once and scrape 10 pages on the Free tier:

- Scraped pages: 10 × $0.005 = **$0.05**
- Full SEO data (one-time, per run): **$0.015**
- Actor start (one-time, per run): **$0.001**
- Platform usage: **$0.00**
- **Total: $0.066**

Note that scraping 1 page instead of 10 in that same run would still only cost **$0.015** for SEO data and **$0.001** for Actor start — those two fees don't scale with page count.

### 🔑 SEO & Keyword Research Use Cases

- **Google SERP scraper** for rank tracking and position monitoring
- **Keyword research API** for search volume, difficulty, and click-value estimation
- **Competitor SEO analysis** to reverse-engineer who's ranking and why
- **PPC & Google Ads intelligence** to monitor competitor ad spend and creative
- **Content strategy research** using "People Also Ask" and related search data

### 🔌 API & Integrations

This actor isn't limited to the Apify Console — every feature is available programmatically, so you can plug it into your own app, automation, or AI agent.

#### 🌐 Apify API

Every actor on Apify runs behind a full REST API. Authenticate with a Bearer token and call it directly:

```bash
curl "https://api.apify.com/v2/acts/dxbear/Google-SERP-SEO-Scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "query": "your keyword here" }'
```

This runs the actor and returns the dataset items directly in the response — ideal for short runs (under 5 minutes). For longer jobs, run asynchronously and poll the run status, or attach a webhook to get notified on completion.

📚 **Resources:**

- [Apify API documentation](https://docs.apify.com/api/v2)
- [Run Actor and retrieve data via API (tutorial)](https://docs.apify.com/academy/api/run-actor-and-retrieve-data-via-api)

#### 🤖 MCP (Model Context Protocol) — Use This Actor as an AI Agent Tool

This actor can be exposed directly to AI agents and LLM-powered assistants (Claude, Cursor, VS Code, and any MCP-compatible client) via Apify's hosted MCP server. Once connected, your AI agent can discover this actor, understand its input schema automatically, run it, and read the results — no manual API wiring required.

Connect at **[mcp.apify.com](https://mcp.apify.com)** using your Apify API token, then point any MCP client at it.

📚 **Resources:**

- [Apify MCP server documentation](https://docs.apify.com/platform/integrations/mcp)
- [How to use MCP with Apify Actors](https://blog.apify.com/how-to-use-mcp/)
- [Apify MCP Server on GitHub](https://github.com/apify/apify-mcp-server)

#### 🔗 n8n Automation

Run this actor as a step in your n8n workflows — no code required. The official Apify node supports Run Actor, Run Task, and Get Dataset Items operations, and can feed results straight into Google Sheets, databases, Slack, or 1,000+ other n8n-connected apps.

```
Settings → Community Nodes → Install → @apify/n8n-nodes-apify
```

📚 **Resources:**

- [Apify n8n integration docs](https://docs.apify.com/platform/integrations/n8n)
- [Apify on the n8n integrations page](https://n8n.io/integrations/apify/)

#### 🧠 AI Agents & LLM Workflows

Beyond MCP, this actor's structured JSON output is built to be consumed directly by LLM pipelines and custom AI agents — feed the dataset into a RAG pipeline, use it as a tool call in a LangChain/LangGraph agent, or wire it into your own agent framework via the standard Apify API.

📚 **Resources:**

- [What are AI agents? (Apify)](https://docs.apify.com/academy)
- [How to build an AI agent on Apify](https://blog.apify.com/how-to-use-mcp/)

***

### 💬 Support

Questions, feature requests, or bug reports — reach out any time:

- 📧 **support@scravity.com**
- 🌐 **[scravity.com](https://scravity.com)**

***

**Built for SEO teams, marketers, and developers who need real Google data — not guesswork.** ⭐ If this actor saves you time, consider leaving a rating on the Apify Store.

# Actor input Schema

## `query` (type: `string`):

Google search query (e.g. 'best proxy')

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

Device type to simulate for the search.

## `page` (type: `integer`):

Number of result pages to return.

## `language` (type: `string`):

Two-letter language code for search results (e.g. 'en', 'fr').

## `country` (type: `string`):

Two-letter country code for localized results.

## `timeFilter` (type: `string`):

Filter results by time period.

## `uule` (type: `string`):

Google UULE parameter for exact location targeting. Encodes a physical location for localized results.

## `location` (type: `string`):

Physical location name for localized search results (e.g. 'New York, NY').

## `returnRawHtml` (type: `boolean`):

If enabled, the raw HTML of the Google Search results page will be included in the output <strong>before</strong> any parsing. Useful for debugging or building your own parser on top of the response.

## `includeSerpSeoData` (type: `boolean`):

If enabled, extracts additional SEO-related data from the SERP.<br><br>⚠️ <strong>Note:</strong> SERP SEO data is only available for a limited number of countries see the documentation. Results may be incomplete or unavailable for other countries.

## Actor input object example

```json
{
  "device": "desktop",
  "page": 1,
  "language": "en",
  "country": "US",
  "timeFilter": "",
  "returnRawHtml": false,
  "includeSerpSeoData": false
}
```

# Actor output Schema

## `overview` (type: `string`):

AI Overview, organic results, paid ads, People Also Ask, and related searches for each scraped keyword.

## `competitorIntelligence` (type: `string`):

SEO metrics, competitor rankings, domain traffic history, historical ad creatives, and active advertisers for each scraped keyword.

## `allResults` (type: `string`):

Full dataset with every field for each scraped keyword, unfiltered.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("dxbear/google-serp-seo-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 = {}

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

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

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

```

## CLI example

```bash
echo '{}' |
apify call dxbear/google-serp-seo-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=dxbear/google-serp-seo-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google SERP & SEO Scraper",
        "description": "Scrape Google SERPs for organic rankings, paid ads, AI Overview, People Also Ask & keyword SEO metrics. Track competitors, domain traffic & ad spend. no proxies or CAPTCHAs. Perfect for SEO agencies, marketers & developers.",
        "version": "0.0",
        "x-build-id": "aCPosCEN7RFB0hU0U"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/dxbear~google-serp-seo-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-dxbear-google-serp-seo-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/dxbear~google-serp-seo-scraper/runs": {
            "post": {
                "operationId": "runs-sync-dxbear-google-serp-seo-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/dxbear~google-serp-seo-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-dxbear-google-serp-seo-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "query"
                ],
                "properties": {
                    "query": {
                        "title": "🔍 Search Query",
                        "type": "string",
                        "description": "Google search query (e.g. 'best proxy')"
                    },
                    "device": {
                        "title": "📱 Device Type",
                        "enum": [
                            "desktop",
                            "mobile"
                        ],
                        "type": "string",
                        "description": "Device type to simulate for the search.",
                        "default": "desktop"
                    },
                    "page": {
                        "title": "📄 Number of Pages",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Number of result pages to return.",
                        "default": 1
                    },
                    "language": {
                        "title": "🌍 Language",
                        "enum": [
                            "en",
                            "fr",
                            "de",
                            "es",
                            "it",
                            "pt",
                            "nl",
                            "pl",
                            "ru",
                            "ar",
                            "zh",
                            "ja",
                            "ko",
                            "tr",
                            "sv",
                            "da",
                            "fi",
                            "no",
                            "cs",
                            "sk",
                            "hu",
                            "ro",
                            "bg",
                            "hr",
                            "uk",
                            "he",
                            "fa"
                        ],
                        "type": "string",
                        "description": "Two-letter language code for search results (e.g. 'en', 'fr').",
                        "default": "en"
                    },
                    "country": {
                        "title": "🗺️ Country",
                        "enum": [
                            "US",
                            "CA",
                            "MX",
                            "GT",
                            "BZ",
                            "SV",
                            "HN",
                            "NI",
                            "CR",
                            "PA",
                            "CU",
                            "DO",
                            "PR",
                            "JM",
                            "TT",
                            "BB",
                            "BS",
                            "BR",
                            "AR",
                            "CL",
                            "CO",
                            "PE",
                            "VE",
                            "EC",
                            "BO",
                            "PY",
                            "UY",
                            "GY",
                            "SR",
                            "GF",
                            "UK",
                            "IE",
                            "FR",
                            "DE",
                            "NL",
                            "BE",
                            "CH",
                            "AT",
                            "LI",
                            "SE",
                            "NO",
                            "DK",
                            "FI",
                            "IS",
                            "EE",
                            "LV",
                            "LT",
                            "ES",
                            "PT",
                            "IT",
                            "MT",
                            "GR",
                            "CY",
                            "TR",
                            "PL",
                            "CZ",
                            "SK",
                            "HU",
                            "RO",
                            "BG",
                            "HR",
                            "SI",
                            "RS",
                            "BA",
                            "ME",
                            "MK",
                            "AL",
                            "XK",
                            "RU",
                            "UA",
                            "BY",
                            "MD",
                            "GE",
                            "AM",
                            "AZ",
                            "KZ",
                            "UZ",
                            "TM",
                            "TJ",
                            "KG",
                            "IL",
                            "JO",
                            "LB",
                            "SY",
                            "IQ",
                            "IR",
                            "AE",
                            "SA",
                            "KW",
                            "BH",
                            "QA",
                            "OM",
                            "YE",
                            "PS",
                            "EG",
                            "LY",
                            "TN",
                            "DZ",
                            "MA",
                            "SD",
                            "SN"
                        ],
                        "type": "string",
                        "description": "Two-letter country code for localized results.",
                        "default": "US"
                    },
                    "timeFilter": {
                        "title": "⏱️ Time Filter",
                        "enum": [
                            "",
                            "h",
                            "d",
                            "w",
                            "m",
                            "y"
                        ],
                        "type": "string",
                        "description": "Filter results by time period.",
                        "default": ""
                    },
                    "uule": {
                        "title": "📍 UULE Location Code",
                        "type": "string",
                        "description": "Google UULE parameter for exact location targeting. Encodes a physical location for localized results."
                    },
                    "location": {
                        "title": "🏙️ Location",
                        "type": "string",
                        "description": "Physical location name for localized search results (e.g. 'New York, NY')."
                    },
                    "returnRawHtml": {
                        "title": "🗂️ Return Raw HTML",
                        "type": "boolean",
                        "description": "If enabled, the raw HTML of the Google Search results page will be included in the output <strong>before</strong> any parsing. Useful for debugging or building your own parser on top of the response.",
                        "default": false
                    },
                    "includeSerpSeoData": {
                        "title": "📊 Include SERP SEO Data",
                        "type": "boolean",
                        "description": "If enabled, extracts additional SEO-related data from the SERP.<br><br>⚠️ <strong>Note:</strong> SERP SEO data is only available for a limited number of countries see the documentation. Results may be incomplete or unavailable for other countries.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
