# SERP MCP Tracker + AI SEO — Ahrefs $129/mo Alt (`harvestlab/google-search-scraper`) Actor

Track SERP rankings daily — 99%+ run success. Skyfire/x402 payment-ready. AI SEO audits at $0.003/result. RAG pipeline tool for AI agents. Replaces Ahrefs ($129/mo), SEMrush ($139/mo), AccuRanker ($129/mo) at 10-100x cheaper. MCP/n8n. Tavily/Serper/Brave alt.

- **URL**: https://apify.com/harvestlab/google-search-scraper.md
- **Developed by:** [Nick](https://apify.com/harvestlab) (community)
- **Categories:** SEO tools, AI, MCP servers
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN 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/platform/actors/running/actors-in-store#pay-per-usage

## 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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## SERP Rank Tracker + AI SEO — Ahrefs $129/mo Alt

> 🤖 **MCP-Ready** — works as a tool for Claude, Cursor, ChatGPT, and other AI agents via the [Apify MCP Server](https://github.com/apify/apify-mcp-server). Typed inputs + structured outputs (dataset_schema) deployed in Cycle 73.

> 🧰 **Works with**: LangChain · LangGraph · CrewAI · LlamaIndex · PydanticAI · Mastra AI · Bee AI — call this actor as a tool from any [Apify MCP](https://github.com/apify/apify-mcp-server) or [actor-templates](https://github.com/apify/actor-templates)-backed AI framework.

> 💰 **Pay-per-result, not per compute unit** — you know your cost BEFORE pressing Run. No surprise compute charges, no monthly minimums, no SaaS subscription. Compare to Apify's default \$0.20/CU model where cost depends on actor runtime, memory, and data volume.

> 🔁 **Apify rental alternative** — Apify is sunsetting the rental pricing model in October 2026. This Actor is already 100% pay-per-event: drop in as a 1:1 replacement for any rental-based competitor without a contract or monthly minimum.

> 🍪 **No cookies, no OAuth, no API keys (for the scraping)** — runs on public data only. AI keys are optional and only needed when `enableAiAnalysis: true`.

Track SERP rankings and run AI SEO audits for **$0.003/query** — drop-in replacement for **Ahrefs ($129/mo), Semrush ($139/mo), and SERPRobot ($49/mo)** rank trackers. A daily 50-query rank-tracking schedule costs **~$4.50/month** here vs **$129+/mo** on Ahrefs (96% cheaper). Extracts organic listings, featured snippets, knowledge panels, People Also Ask, and related searches across 30+ countries, with cross-run diff mode, push webhooks, and optional 5-provider AI SEO analysis.

### What it does

Google Search Scraper runs headless Chromium via Playwright to render Google's search results pages exactly as a real browser would — defeating the JavaScript-only detection that blocks simple HTTP scrapers. For every query you provide, it extracts the full SERP: organic results with title, URL, snippet, and position; featured snippets; knowledge panel entities; People Also Ask questions; and related searches. Results are localized by country code (`gl`) and language code (`hl`), so you get the same page a user in Germany, Japan, or Brazil would see.

Beyond raw extraction, the actor solves three real problems without requiring a SaaS subscription:

**Rank tracking at a fraction of SaaS cost.** Enable diff mode (`trackSerpDiff: true`) to snapshot SERP positions across scheduler runs. On every run the actor compares top-10 URLs against the previous snapshot keyed by `(query, country, language)`, flags domains that moved 2+ positions, identifies new entries and dropped domains, and records featured-snippet source changes — the same functionality that drives $50–200/month in Ahrefs, Semrush, and SERPRobot subscriptions.

**Push-based webhook alerts.** Point `alertWebhookUrl` at any Slack incoming webhook, Zapier catch-hook, Make scenario, or custom endpoint. Whenever a tracked query's SERP shifts significantly, the actor POSTs a structured JSON diff payload — no polling, no dashboard refreshes. Wire into Slack for an ops-channel alert or into n8n/Make to route rank-drops to email and rank-climbs to a Notion log.

**AI SEO analysis per query.** Enable `enableAiAnalysis` and choose your LLM provider (OpenRouter, Anthropic, Google AI, OpenAI, or self-hosted Ollama). The actor classifies search intent, identifies content gaps against the current top-10, and produces keyword and content recommendations — functionality that typically requires a separate SEO audit tool.

SEOs, content strategists, growth teams, and rank-tracking SaaS builders use this actor to monitor competitive positions and automate SERP intelligence at scale.

### Features

- **Playwright browser rendering**: Uses headless Chromium to render Google's JavaScript-heavy pages, bypassing anti-bot measures that block simple HTTP requests
- **Full organic result extraction**: Title, URL, displayed URL, snippet text, and position for every ranking result
- **Featured snippet extraction**: Captures the answer box when Google serves one, including source URL and snippet text
- **Knowledge panel extraction**: Extracts entity facts, descriptions, and structured data from knowledge panels
- **People Also Ask**: Captures PAA questions shown alongside results — ideal for content planning and FAQ targeting
- **Related searches**: Extracts suggestions from the bottom of the SERP for keyword expansion
- **Multi-country support**: Pass any ISO 3166-1 alpha-2 country code (`us`, `gb`, `de`, `fr`, `jp`, `br`, `in`, etc.) to localize results
- **Multi-language support**: Pass any ISO 639-1 language code (`en`, `de`, `fr`, `es`, `ja`, `pt`, `zh`) to filter by result language
- **Bulk query processing**: Submit multiple queries in one run — each produces a separate output item
- **Pagination**: Automatically fetches up to 10 pages to collect up to 100 organic results per query
- **Rank-tracker diff mode**: Cross-run SERP snapshots stored per `(query, country, language)` triple with rank-change detection — replaces dedicated SaaS rank trackers
- **Webhook alerts**: Fire-and-forget POST to Slack / Zapier / Make / n8n / custom endpoints on significant SERP movements (2+ position shifts, new/dropped top-10 domains, featured-snippet flips)
- **AI SEO analysis**: Search intent classification, keyword insights, content gap analysis, and content structure recommendations via 5 LLM providers
- **Multi-LLM support**: OpenRouter (300+ models, recommended), Anthropic Claude, Google AI Gemini, OpenAI GPT, or self-hosted Ollama
- **Pay-per-query pricing**: Only billed for queries that return at least one organic result — blocked runs cost nothing

#### Head-to-head: vs `apify/google-search-scraper`

This Actor competes directly against Apify's official `apify/google-search-scraper` (~116K users, 4.8/5, 125 reviews). Where each wins:

| Feature | This Actor (harvestlab) | apify/google-search-scraper |
|---|---|---|
| **Cross-run rank-change tracker** | ✅ diff mode with per-(query, country, language) snapshots | ❌ not offered |
| **SERP-change webhook alerts** | ✅ Slack / Zapier / n8n / Make / custom on rank shifts | ❌ not offered |
| **AI SEO analysis** | ✅ 5-provider router (OpenRouter / Anthropic / Google / OpenAI / Ollama) for intent / gaps / content recommendations | ❌ has "AI search mode" (Perplexity / ChatGPT search) — different feature, not SEO |
| **Featured snippet + knowledge panel extraction** | ✅ both | ⚠️ PAA documented; featured snippets and knowledge panels not explicit |
| **People Also Ask** | ✅ full | ✅ full |
| **Multi-country** | ✅ 30+ countries | ✅ supported |
| **Per-result price** | $0.003 / query | $0.0018 / page |
| **Total users / rating** | New (volume gap) | 116K / 4.8/5 |

**Why pay 1.7× more per query?** Because `apify/google-search-scraper` is a SERP fetcher; this Actor is a **rank-tracker SaaS at SERP-scraper pricing**. A 50-keyword daily rank-tracker on Apify's actor costs ~$2.70/mo for raw SERPs that you'd then need to diff and alert on yourself. On this actor: ~$4.50/mo for diffed SERPs + Slack alerts already wired. Versus Ahrefs ($129/mo) or SEMrush ($139.95/mo): **30×+ cheaper** with the same rank-tracker outputs.

**If you only want raw SERP HTML and you'll do diffing/alerts yourself**, Apify's official actor is cheaper. **If you want a turnkey rank-tracker that fires Slack alerts when your competitor gains a featured snippet**, this Actor's $9/mo is the cheapest option on the Apify Store.

### Use Cases

Each use case below shows the SaaS tool you'd otherwise pay for and what this actor costs at the same workload — most replacements come in 10–100× cheaper.

- **Daily rank tracking** — Replace **Ahrefs Lite ($129/mo)**, **SEMrush Pro ($139.95/mo)**, **SE Ranking Essential ($65/mo)**, or **SERPRobot Pro ($49/mo)**. Schedule this actor daily for a 100-keyword list with `trackSerpDiff: true` and Slack alerts: ~$0.30/day = **~$9/month** vs $49–140/month subscriptions you don't fully use. The `serp_diff` item gives you the same rank-change feed those dashboards build their alerting on.
- **SERP competitor monitoring** — Replace the position-tracker tier of **Ahrefs ($129/mo)** or **SEMrush ($139.95/mo)**. Track which domains hold top-10 spots for your money keywords and POST to Slack/n8n when a competitor gains or drops 2+ positions. Real-time, push-based, no dashboard refresh required.
- **SEO keyword research at scale** — Replace **Ahrefs Keywords Explorer** or **SEMrush Keyword Magic Tool** for SERP-side research. 1,000 head-term SERPs (organic + PAA + related searches + featured snippet) cost **~$3** as one-shot data — you keep the raw JSON, not a locked dashboard. Pair with `enableAiAnalysis` for $0.05 per query of intent classification, content gaps, and recommended content structure (typical AI SEO tools like **Surfer SEO ($89/mo)** or **MarketMuse ($149/mo)** sell the same insight).
- **Content brief generation** — Pull PAA questions, related searches, and the current top-10 for a target keyword, then feed `enableAiAnalysis: true` to get a draft H2/H3 outline, target word count, and competitive gaps. Replaces the brief-builder feature of **Frase ($45/mo)**, **MarketMuse ($149/mo)**, or **Clearscope ($189/mo)** at $0.053/brief.
- **Featured-snippet & PAA opportunity hunting** — Filter datasets where `featured_snippet` is `null` to find queries where the answer box is unclaimed, or where it cites a weak source you can outrank. Replaces the "SERP features" report in **Ahrefs/SEMrush** at fractional cost.
- **Multi-market localized SEO** — Run the same query across `country: us / gb / de / fr / jp / br` and diff the SERPs to see which content travels and which markets need localized landing pages. Replaces the multi-location tier of **AccuRanker ($129/mo)** or **Wincher ($60/mo)**.
- **Affiliate & content-arbitrage discovery** — Score SERPs for commercial-intent queries where the top-10 are weak (low DR placeholders, AI-generated thin content). The `domain` and `snippet` fields plus AI competitive-gap analysis surface keywords where a real piece of content can rank — replaces parts of **Niche Hunter** workflows in **SEMrush** or **Ahrefs**.
- **Lead generation from local & niche queries** — Extract business URLs from `"plumber [city]"`, `"[industry] consultant near me"`, or B2B intent queries to feed into a CRM. SERP-based lead lists are an alternative to **ZoomInfo ($14,995/yr seat)** or **Apollo ($59/mo seat)** for top-of-funnel domain discovery.
- **Brand & reputation monitoring** — Schedule daily SERP runs for your brand name + variants and alert via webhook when a negative third-party page enters top-10 or your own domain drops. Replaces the brand-mention tier of **Brand24 ($99/mo)** or **Mention ($49/mo)** for SERP-specific monitoring.
- **AI SEO analysis without a separate tool** — `enableAiAnalysis` returns search intent, competition level, content recommendations, competitive gaps, and featured-snippet strategy in one pass for $0.05/query. Replaces buying both a rank tracker AND an AI SEO tool — typical stack is **Ahrefs ($129/mo) + Surfer SEO ($89/mo) = $218/mo**; this actor covers both surfaces.
- **Academic & data-journalism research** — SERP data for studies on information retrieval, search bias, media coverage patterns, election-cycle ranking, or localization effects. Pay only for the queries you actually run; no annual seat cost.

### Input

#### Search Parameters

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `queries` | string[] | — | One or more search queries. Each produces a separate output item. |
| `maxResults` | integer | 10 | Max organic results per query (1–100). Values above 10 require pagination (+2–3s per extra page). |
| `country` | string | `us` | ISO 3166-1 alpha-2 country code for geo-targeted results (`us`, `gb`, `de`, `jp`, etc.). |
| `language` | string | `en` | ISO 639-1 language code for result language (`en`, `de`, `fr`, `es`, `ja`, etc.). |
| `includePeopleAlsoAsk` | boolean | `true` | Extract PAA questions. |
| `includeRelatedSearches` | boolean | `true` | Extract related search suggestions. |
| `includeFeaturedSnippet` | boolean | `true` | Extract the featured snippet / answer box. |
| `includeKnowledgePanel` | boolean | `true` | Extract knowledge panel entity data. |

#### SERP Diff / Rank Tracker

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `trackSerpDiff` | boolean | `false` | Enable cross-run rank tracking. Snapshots top-10 URLs per `(query, country, language)` and emits a `serp_diff` item with rank changes on every subsequent run. |
| `alertWebhookUrl` | string | — | POST a JSON diff payload here when a tracked query's `change_score` meets the threshold. Auto-enables `trackSerpDiff`. |
| `alertMinChangeScore` | integer | 2 | Minimum change score to fire a webhook (1 = any change, higher = less noise). |

#### AI Analysis Settings

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enableAiAnalysis` | boolean | `false` | Enable AI-powered SEO analysis. Requires a provider API key. |
| `llmProvider` | string | `openrouter` | Provider: `openrouter` (recommended), `anthropic`, `google`, `openai`, or `ollama`. |
| `openrouterApiKey` | string | — | OpenRouter API key. Set via `OPENROUTER_API_KEY` env var or this field. |
| `anthropicApiKey` | string | — | Anthropic API key. Set via `ANTHROPIC_API_KEY` env var or this field. |
| `googleApiKey` | string | — | Google AI API key. Set via `GOOGLE_API_KEY` env var or this field. |
| `openAiApiKey` | string | — | OpenAI API key. Set via `OPENAI_API_KEY` env var or this field. |
| `ollamaBaseUrl` | string | `http://localhost:11434` | Ollama base URL for self-hosted inference. |
| `llmModel` | string | — | Optional model override. Leave empty for provider defaults. |

#### Proxy Settings

| Field | Type | Description |
|-------|------|-------------|
| `proxyConfiguration` | object | Proxy settings. Residential proxy is strongly recommended for popular head-term queries to avoid Google CAPTCHA blocks. Default: Apify RESIDENTIAL group. |

Google aggressively throttles common commercial queries (`"best CRM software"`, `"ai news 2026"`, `"buy laptop"`) from datacenter IPs and returns a reCAPTCHA / "unusual traffic" page. The default proxy is `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}` — each retry rotates to a fresh household IP. You are never charged for blocked queries.

**CLI aliases** (hidden from Console form): `query`, `searchQuery`, `searchTerm` all map to `queries[]`; `maxItems` maps to `maxResults`.

### Output

#### Per-query result item

Each query produces one output item pushed to the Apify dataset:

| Field | Type | Description |
|-------|------|-------------|
| `query` | string | The search query used |
| `country` | string | Country code used |
| `language` | string | Language code used |
| `total_results_text` | string | Google's "About X results" count text |
| `organic_results_count` | integer | Number of organic results extracted |
| `organic_results` | object[] | Ranked list of organic results (see below) |
| `people_also_ask` | string[] | PAA questions (empty array if none or disabled) |
| `related_searches` | string[] | Related search suggestions (empty array if none or disabled) |
| `featured_snippet` | object\|null | Featured snippet data if Google serves one |
| `knowledge_panel` | object\|null | Knowledge panel entity data if present |
| `scraped_at` | string | ISO 8601 timestamp of the scrape |

#### Organic result object

| Field | Type | Description |
|-------|------|-------------|
| `position` | integer | Rank position (1 = top) |
| `title` | string | Page title as shown in search results |
| `url` | string | Full canonical URL |
| `domain` | string | Root domain extracted from the URL (e.g. `forbes.com`) |
| `displayed_url` | string | URL as displayed by Google (breadcrumb format) |
| `snippet` | string | Description text under the title |

#### SERP diff item (rank-tracker mode)

When `trackSerpDiff: true`, an additional `serp_diff` item is emitted per query:

| Field | Type | Description |
|-------|------|-------------|
| `type` | string | Always `"serp_diff"` |
| `query` | string | Search query |
| `change_score` | integer | Total significant changes detected |
| `rank_changes` | object[] | Domains that moved 2+ positions (`rank_now`, `rank_previous`, `rank_delta`, `direction`) |
| `new_entries` | object[] | Domains new to the tracked top-10 |
| `dropped_entries` | object[] | Domains that left the tracked top-10 |
| `featured_snippet_changed` | boolean | Whether the featured snippet source flipped |
| `snapshot_at` | string | ISO 8601 timestamp |
| `hours_since_last_snapshot` | number | Hours elapsed since the prior snapshot |

#### AI analysis fields (when enabled)

When `enableAiAnalysis: true`, each query result includes an `ai_analysis` object with:
- `search_intent` — informational / commercial / transactional / navigational
- `competition_level` — low / medium / high
- `keyword_insights` — primary intent, long-tail opportunities, PAA-derived questions
- `content_recommendations` — optimized title, H2/H3 outline, target word count
- `competitive_gaps` — opportunities the current top-10 is missing
- `featured_snippet_strategy` — how to win the answer box for this query

#### Pricing

| Event | When charged | Price |
|-------|-------------|-------|
| `serp-result-scraped` | Once per query returning ≥1 organic result | **$0.003** |
| `ai-analysis-completed` | Per query when AI SEO analysis runs | **$0.05** |
| `serp-change-detected` | Per query with a significant SERP change vs prior run | **$0.002** |
| `alert-dispatched` | Per successfully delivered webhook alert (2xx response) | **$0.002** |

Blocked queries (CAPTCHA / 0 results) are **never charged**. A typical 50-keyword daily rank-tracker costs ~$0.15/day ($4.50/month) vs $50–200/month for SaaS alternatives.

#### Output example

```json
{
    "query": "best project management software 2026",
    "country": "us",
    "language": "en",
    "total_results_text": "About 142,000,000 results",
    "organic_results_count": 10,
    "organic_results": [
        {
            "position": 1,
            "title": "Best Project Management Software of 2026 - Forbes Advisor",
            "url": "https://www.forbes.com/advisor/business/best-project-management-software/",
            "domain": "forbes.com",
            "displayed_url": "forbes.com › advisor › business",
            "snippet": "We tested and compared 20+ project management tools..."
        }
    ],
    "people_also_ask": [
        "What is the best project management tool in 2026?",
        "Is Monday.com better than Asana?"
    ],
    "related_searches": [
        "project management software free",
        "best project management software for small teams"
    ],
    "featured_snippet": null,
    "knowledge_panel": null,
    "scraped_at": "2026-04-24T10:30:00Z"
}
````

### Quick Start

**Basic SERP scrape — 10 results for one keyword:**

```json
{
    "queries": ["best CRM software 2026"],
    "maxResults": 10,
    "country": "us",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"]
    }
}
```

Cost: $0.003. Returns title, URL, snippet, position for 10 results + PAA + related searches.

**Multiple queries in one run:**

```json
{
    "queries": [
        "best project management software",
        "asana vs monday vs clickup",
        "project management tools for agencies"
    ],
    "maxResults": 20,
    "country": "us"
}
```

**Localized search (Germany):**

```json
{
    "queries": ["beste Projektmanagement Software"],
    "maxResults": 10,
    "country": "de",
    "language": "de"
}
```

**Daily rank tracker with Slack alerts:**

```json
{
    "queries": ["my target keyword", "competitor keyword"],
    "trackSerpDiff": true,
    "alertWebhookUrl": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
    "alertMinChangeScore": 2,
    "country": "us"
}
```

Schedule this run daily via Apify Scheduler. The first run establishes the baseline (not charged). Subsequent runs emit a `serp_diff` item and POST to Slack whenever positions shift 2+ places, new domains enter top 10, or a featured snippet flips. Cost: ~$7–10/month for 50 tracked keywords vs $50–200/month for SaaS rank trackers.

**With AI SEO analysis:**

```json
{
    "queries": ["email marketing platforms"],
    "maxResults": 30,
    "enableAiAnalysis": true,
    "llmProvider": "openrouter",
    "openrouterApiKey": "sk-or-..."
}
```

Returns full SERP data plus `ai_analysis` with intent classification, content gaps, keyword opportunities, and a recommended content structure.

#### MCP Quickstart — call this actor from Claude / Cursor / ChatGPT

Install the Apify MCP server in your AI agent of choice:

```bash
## Claude Code
claude mcp add apify -- npx -y @apify/actors-mcp-server --token YOUR_APIFY_TOKEN

## Claude Desktop / Cursor (add to mcp.json):
{"mcpServers":{"apify":{"command":"npx","args":["-y","@apify/actors-mcp-server","--token","YOUR_APIFY_TOKEN"]}}}
```

Then prompt the agent:

> "Use the harvestlab/google-search-scraper actor on Apify to track our Google rankings for \['ai code editor', 'ai pair programming'] across US/UK/DE/FR with featured snippet detection — fire a webhook on rank changes. Push the results back as JSON."

The agent will discover the actor's `dataset_schema.json`, generate the right input, run it, and pipe the typed output back into your conversation.

### Use with AI agents

This actor's output (organic SERP results, featured snippets, PAA, knowledge panels, plus optional AI SEO analysis as JSON) is agent-ready — drop it into a research agent, RAG pipeline, or SEO auditor as a tool. It's a direct **Tavily / Serper / Brave Search API alternative** at $0.003/query, and the same run replaces Ahrefs ($129/mo) for rank tracking. Reference templates live at [apify/actor-templates → js-langchain](https://github.com/apify/actor-templates/tree/master/templates/js-langchain) and [js-langgraph-agent](https://github.com/apify/actor-templates/tree/master/templates/js-langgraph-agent).

**LangChain — wrap as a `Tool` for a research / RAG agent:**

```python
from apify_client import ApifyClient
from langchain.tools import Tool

client = ApifyClient("YOUR_APIFY_TOKEN")

def google_search(args: dict) -> list:
    run = client.actor("harvestlab/google-search-scraper").call(run_input={
        "queries": args["queries"],
        "country": args.get("country", "us"),
        "maxResults": args.get("maxResults", 10),
    })
    return list(client.dataset(run["defaultDatasetId"]).iterate_items())

google_search_tool = Tool(
    name="google_search",
    description="Fresh Google SERP results + featured snippets. Use for research, RAG context, or SEO checks.",
    func=google_search,
)
## agent.invoke({"input": "..."}) -> agent calls google_search_tool.invoke({"queries": ["ai code editors 2026"], "country": "us"})
```

**LangGraph — node in a research-agent graph:**

```python
from apify_client import ApifyClient
from langgraph.graph import StateGraph

client = ApifyClient("YOUR_APIFY_TOKEN")

def serp_node(state: dict) -> dict:
    run = client.actor("harvestlab/google-search-scraper").call(run_input={
        "queries": [state["query"]],
        "country": state.get("country", "us"),
        "maxResults": 10,
    })
    item = next(client.dataset(run["defaultDatasetId"]).iterate_items())
    return {
        "urls": [r["url"] for r in item["organic_results"]],
        "snippets": [r["snippet"] for r in item["organic_results"]],
        "featured_answer": (item.get("featured_snippet") or {}).get("snippet"),
    }

graph = StateGraph(dict)
graph.add_node("search", serp_node)
## wire into your research / synthesis / writer nodes downstream
```

### Troubleshooting

**CAPTCHA or "unusual traffic" block**
Google blocks datacenter IPs on popular commercial queries. Always use `proxyConfiguration` with `RESIDENTIAL` proxy group. You are never charged for blocked queries — only successful scrapes bill. If blocks persist on a specific query, rephrase as a long-tail variant (`"ai news april 2026"` instead of `"ai news 2026"`) or reduce run frequency.

**Fewer results than expected (e.g. 7 instead of 10)**
Google serves fewer organic results for navigational queries, rare queries, or when it fills space with Knowledge Panels, Shopping carousels, or AI Overviews. Try broadening the search term or removing quotes. AI Mode / AI Overview layouts (new generative-answer pages rolling out for commercial-intent queries) may return fewer `<h3>` headings — rephrase as a long-tail or informational query to get the traditional organic SERP.

**Featured snippet not appearing in output**
Not all queries trigger featured snippets. The `featured_snippet` field is `null` when Google doesn't serve one. Question-format queries (`"how to X"`, `"what is Y"`) are more likely to trigger answer boxes.

**Results differ from my browser**
Google personalizes results based on cookies, location, and search history. This actor uses a clean browser session with no cookies. Set `country` and `language` to match your target audience. Results for the same query may also vary by Google data center.

**Rank tracking shows no diff on second run**
Confirm `trackSerpDiff: true` in both runs and that `country`/`language` match exactly between runs — the snapshot key is `(query, country, language)`. Also verify the actor has permission to write to the `google-serp-rank-history` named key-value store.

**AI analysis returns an error**
Confirm the API key is set either as an environment variable (`OPENROUTER_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, or `OPENAI_API_KEY`) or in the corresponding input field. The error message names both paths. For Ollama, confirm `ollamaBaseUrl` is reachable from the Apify runner (self-hosted Ollama is not reachable from cloud runs unless tunneled).

**Webhook not firing**
`alertWebhookUrl` requires `trackSerpDiff: true` (auto-enabled when a URL is set) and a prior baseline run. Webhooks fire only when `change_score >= alertMinChangeScore` (default 2). Check the actor log for `[alert]` lines — they show whether the webhook was dispatched, skipped (below threshold), or failed (timeout / non-2xx). Failed webhooks never fail the run and are not charged.

### Legal and Compliance

This actor is provided as a technical tool. Users are solely responsible for ensuring their use complies with applicable laws and platform policies, including:

- **Google's Terms of Service** — Google's ToS restricts automated access to their services. Use this tool responsibly and at your own risk.
- **Data protection regulations** — GDPR (EU), CCPA (California), and equivalent local laws govern the collection and processing of any personal data encountered in search results.
- **Local laws** — Web scraping legality varies by jurisdiction. Users must verify compliance with applicable laws in their region and the region of the target data.

This actor extracts only publicly visible search result information — titles, URLs, and snippet text that Google displays to any anonymous visitor. It does not bypass authentication, access private data, or circumvent paywalls.

The developer of this actor is not responsible for any misuse, ToS violations, or legal consequences arising from its use. No personal data is stored by the actor beyond what Apify's standard dataset storage provides; consult the [Apify Privacy Policy](https://apify.com/privacy-policy) for data handling details.

#### Related Actors

- **[News Monitor](https://apify.com/harvestlab/news-monitor)** — Track news mentions on the same competitor brand keywords you scrape SERPs for. Pair Google's organic / featured-snippet picture with real-time press coverage so SEO and PR teams see search rank shifts and the news cycles driving them in one workflow.
- **[Contact Extractor](https://apify.com/harvestlab/contact-extractor)** — Turn top-ranking SERP URLs into a lead list. Pipe `result.url` from Google Search Scraper into Contact Extractor to harvest SMTP-verified emails, phones, and tech-stack signals from every domain that ranks for your target query — link-building outreach and ICP discovery in one pass.
- **[Reddit Scraper](https://apify.com/harvestlab/reddit-scraper)** — Layer community sentiment onto SERP keyword research. Run the same competitor and category terms through Reddit to see how real users discuss them, surfacing pain points and feature gaps that pure SERP data hides.

# Actor input Schema

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

One or more search queries to scrape Google results for.

## `searchQuery` (type: `string`):

CLI alias for a single-query run. Collapsed into queries\[]. Hidden from Console form.

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

CLI alias for a single-query run. Collapsed into queries\[]. Hidden from Console form.

## `searchTerm` (type: `string`):

CLI alias for a single-query run. Collapsed into queries\[]. Hidden from Console form.

## `maxResults` (type: `integer`):

Maximum organic results to scrape per query (1-100). Google shows ~10 results per SERP page, so values above 10 require pagination (slower: +2-3s per extra page). Typical SEO audits use 10-30; deep keyword research uses 50-100.

## `maxItems` (type: `integer`):

CLI alias for maxResults. Hidden from Console form.

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

Two-letter ISO 3166-1 alpha-2 country code for localized results. Controls the 'gl' parameter Google uses for geo-targeting. Pair with a matching language for best results (e.g. 'us'+'en', 'de'+'de', 'jp'+'ja').

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

Two-letter ISO 639-1 language code for result language. Controls the 'hl' parameter Google uses to filter results and UI language. Common values: 'en', 'de', 'fr', 'es', 'it', 'ja', 'pt', 'nl'.

## `includePeopleAlsoAsk` (type: `boolean`):

Extract 'People Also Ask' questions from search results.

## `includeRelatedSearches` (type: `boolean`):

Extract related search suggestions from bottom of results.

## `includeFeaturedSnippet` (type: `boolean`):

Extract the featured snippet / answer box if Google shows one for the query.

## `includeKnowledgePanel` (type: `boolean`):

Extract knowledge panel data (entity info, facts) when available.

## `trackSerpDiff` (type: `boolean`):

Persist the top 10 organic URLs per query across runs and emit a `serp_diff` item on every run with rank changes, new/dropped domains, and featured-snippet flips. Pair with Apify scheduler to build a daily rank-tracker without any external service. Charges a small fee ($0.002) only when a significant change is detected (>=2-position shift, new/dropped top-10 domain, or featured-snippet flip). First run establishes the baseline and is NOT charged. Cross-run state is stored in a named Apify key-value store (one snapshot slot per query/country/language triple).

## `alertWebhookUrl` (type: `string`):

POST a compact JSON payload to this URL whenever a tracked query's SERP diff change\_score meets the threshold below. Turns the actor into a real-time rank-movement alert service — pipe into Slack/Discord/Zapier/Make/n8n/your own endpoint. Fire-and-forget: 5s timeout, 1 retry on failure, webhook errors never fail the run. Only fires on second-run-onward (needs a prior snapshot for deltas). Setting this automatically enables trackSerpDiff. Adds an `alert-dispatched` charge ($0.002) per successful webhook. Leave empty to disable.

## `alertMinChangeScore` (type: `integer`):

Minimum SERP-diff change\_score required to fire a webhook. Default 2 means at least two significant changes (rank shifts of >=2 positions, new/dropped top-10 domains, or featured-snippet flips) must occur before an alert is sent. Raise to reduce noise on volatile commercial queries; lower to 1 for sensitive monitoring. Only applies when alertWebhookUrl is set.

## `enableAiAnalysis` (type: `boolean`):

Run AI-powered SEO and SERP analysis. Requires an LLM API key.

## `llmProvider` (type: `string`):

Which AI provider to use for analysis.

## `openrouterApiKey` (type: `string`):

OpenRouter API key — alternative: set OPENROUTER\_API\_KEY env var. Get one at openrouter.ai/keys

## `anthropicApiKey` (type: `string`):

Anthropic API key — alternative: set ANTHROPIC\_API\_KEY env var. Get one at console.anthropic.com/settings/keys

## `googleApiKey` (type: `string`):

Google AI (Gemini) API key — alternative: set GOOGLE\_API\_KEY env var. Get one at aistudio.google.com/app/apikey

## `openaiApiKey` (type: `string`):

OpenAI API key — alternative: set OPENAI\_API\_KEY env var. Get one at platform.openai.com/api-keys

## `ollamaBaseUrl` (type: `string`):

Base URL for Ollama API. Default: http://localhost:11434

## `llmModel` (type: `string`):

Specific model to use. Leave empty for the provider default (google/gemini-2.0-flash-001 for OpenRouter, claude-sonnet-4-20250514 for Anthropic, gemini-2.0-flash for Google AI, gpt-4o-mini for OpenAI, llama3.1 for Ollama).

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

Proxy settings. Strongly recommended — enable Apify residential proxy to avoid Google's CAPTCHA / 'unusual traffic' blocks, especially for popular head-term queries. Datacenter proxy or no proxy may trigger reCAPTCHA on common queries.

## Actor input object example

```json
{
  "queries": [
    "best AI coding assistants 2026"
  ],
  "maxResults": 10,
  "country": "us",
  "language": "en",
  "includePeopleAlsoAsk": true,
  "includeRelatedSearches": true,
  "includeFeaturedSnippet": true,
  "includeKnowledgePanel": true,
  "trackSerpDiff": false,
  "alertMinChangeScore": 2,
  "enableAiAnalysis": false,
  "llmProvider": "openrouter",
  "ollamaBaseUrl": "http://localhost:11434",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `datasetOutput` (type: `string`):

Dataset containing scraped Google SERP results, SERP-diff rank-tracker records, AI SEO analysis, and webhook alert dispatch summaries.

# 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 AI coding assistants 2026"
    ],
    "ollamaBaseUrl": "http://localhost:11434",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("harvestlab/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 AI coding assistants 2026"],
    "ollamaBaseUrl": "http://localhost:11434",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("harvestlab/google-search-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 '{
  "queries": [
    "best AI coding assistants 2026"
  ],
  "ollamaBaseUrl": "http://localhost:11434",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call harvestlab/google-search-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SERP MCP Tracker + AI SEO — Ahrefs $129/mo Alt",
        "description": "Track SERP rankings daily — 99%+ run success. Skyfire/x402 payment-ready. AI SEO audits at $0.003/result. RAG pipeline tool for AI agents. Replaces Ahrefs ($129/mo), SEMrush ($139/mo), AccuRanker ($129/mo) at 10-100x cheaper. MCP/n8n. Tavily/Serper/Brave alt.",
        "version": "1.9",
        "x-build-id": "P1u2oaBtprRs7AQ18"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/harvestlab~google-search-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-harvestlab-google-search-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/harvestlab~google-search-scraper/runs": {
            "post": {
                "operationId": "runs-sync-harvestlab-google-search-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/harvestlab~google-search-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-harvestlab-google-search-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",
                "properties": {
                    "queries": {
                        "title": "Search Queries",
                        "type": "array",
                        "description": "One or more search queries to scrape Google results for.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchQuery": {
                        "title": "Search Query (CLI alias)",
                        "type": "string",
                        "description": "CLI alias for a single-query run. Collapsed into queries[]. Hidden from Console form."
                    },
                    "query": {
                        "title": "Search Query (CLI alias)",
                        "type": "string",
                        "description": "CLI alias for a single-query run. Collapsed into queries[]. Hidden from Console form."
                    },
                    "searchTerm": {
                        "title": "Search Query (CLI alias)",
                        "type": "string",
                        "description": "CLI alias for a single-query run. Collapsed into queries[]. Hidden from Console form."
                    },
                    "maxResults": {
                        "title": "Max Results Per Query",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum organic results to scrape per query (1-100). Google shows ~10 results per SERP page, so values above 10 require pagination (slower: +2-3s per extra page). Typical SEO audits use 10-30; deep keyword research uses 50-100.",
                        "default": 10
                    },
                    "maxItems": {
                        "title": "Max Items (CLI alias)",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "CLI alias for maxResults. Hidden from Console form."
                    },
                    "country": {
                        "title": "Country",
                        "type": "string",
                        "description": "Two-letter ISO 3166-1 alpha-2 country code for localized results. Controls the 'gl' parameter Google uses for geo-targeting. Pair with a matching language for best results (e.g. 'us'+'en', 'de'+'de', 'jp'+'ja').",
                        "default": "us"
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "Two-letter ISO 639-1 language code for result language. Controls the 'hl' parameter Google uses to filter results and UI language. Common values: 'en', 'de', 'fr', 'es', 'it', 'ja', 'pt', 'nl'.",
                        "default": "en"
                    },
                    "includePeopleAlsoAsk": {
                        "title": "Include People Also Ask",
                        "type": "boolean",
                        "description": "Extract 'People Also Ask' questions from search results.",
                        "default": true
                    },
                    "includeRelatedSearches": {
                        "title": "Include Related Searches",
                        "type": "boolean",
                        "description": "Extract related search suggestions from bottom of results.",
                        "default": true
                    },
                    "includeFeaturedSnippet": {
                        "title": "Include Featured Snippet",
                        "type": "boolean",
                        "description": "Extract the featured snippet / answer box if Google shows one for the query.",
                        "default": true
                    },
                    "includeKnowledgePanel": {
                        "title": "Include Knowledge Panel",
                        "type": "boolean",
                        "description": "Extract knowledge panel data (entity info, facts) when available.",
                        "default": true
                    },
                    "trackSerpDiff": {
                        "title": "Track SERP changes (rank-tracker mode)",
                        "type": "boolean",
                        "description": "Persist the top 10 organic URLs per query across runs and emit a `serp_diff` item on every run with rank changes, new/dropped domains, and featured-snippet flips. Pair with Apify scheduler to build a daily rank-tracker without any external service. Charges a small fee ($0.002) only when a significant change is detected (>=2-position shift, new/dropped top-10 domain, or featured-snippet flip). First run establishes the baseline and is NOT charged. Cross-run state is stored in a named Apify key-value store (one snapshot slot per query/country/language triple).",
                        "default": false
                    },
                    "alertWebhookUrl": {
                        "title": "SERP Alert Webhook URL (optional)",
                        "type": "string",
                        "description": "POST a compact JSON payload to this URL whenever a tracked query's SERP diff change_score meets the threshold below. Turns the actor into a real-time rank-movement alert service — pipe into Slack/Discord/Zapier/Make/n8n/your own endpoint. Fire-and-forget: 5s timeout, 1 retry on failure, webhook errors never fail the run. Only fires on second-run-onward (needs a prior snapshot for deltas). Setting this automatically enables trackSerpDiff. Adds an `alert-dispatched` charge ($0.002) per successful webhook. Leave empty to disable."
                    },
                    "alertMinChangeScore": {
                        "title": "Minimum Change Score to Alert",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Minimum SERP-diff change_score required to fire a webhook. Default 2 means at least two significant changes (rank shifts of >=2 positions, new/dropped top-10 domains, or featured-snippet flips) must occur before an alert is sent. Raise to reduce noise on volatile commercial queries; lower to 1 for sensitive monitoring. Only applies when alertWebhookUrl is set.",
                        "default": 2
                    },
                    "enableAiAnalysis": {
                        "title": "Enable AI Analysis",
                        "type": "boolean",
                        "description": "Run AI-powered SEO and SERP analysis. Requires an LLM API key.",
                        "default": false
                    },
                    "llmProvider": {
                        "title": "LLM Provider",
                        "enum": [
                            "openrouter",
                            "anthropic",
                            "google",
                            "openai",
                            "ollama"
                        ],
                        "type": "string",
                        "description": "Which AI provider to use for analysis.",
                        "default": "openrouter"
                    },
                    "openrouterApiKey": {
                        "title": "OpenRouter API Key",
                        "type": "string",
                        "description": "OpenRouter API key — alternative: set OPENROUTER_API_KEY env var. Get one at openrouter.ai/keys"
                    },
                    "anthropicApiKey": {
                        "title": "Anthropic API Key",
                        "type": "string",
                        "description": "Anthropic API key — alternative: set ANTHROPIC_API_KEY env var. Get one at console.anthropic.com/settings/keys"
                    },
                    "googleApiKey": {
                        "title": "Google AI API Key",
                        "type": "string",
                        "description": "Google AI (Gemini) API key — alternative: set GOOGLE_API_KEY env var. Get one at aistudio.google.com/app/apikey"
                    },
                    "openaiApiKey": {
                        "title": "OpenAI API Key",
                        "type": "string",
                        "description": "OpenAI API key — alternative: set OPENAI_API_KEY env var. Get one at platform.openai.com/api-keys"
                    },
                    "ollamaBaseUrl": {
                        "title": "Ollama Base URL",
                        "type": "string",
                        "description": "Base URL for Ollama API. Default: http://localhost:11434"
                    },
                    "llmModel": {
                        "title": "LLM Model",
                        "type": "string",
                        "description": "Specific model to use. Leave empty for the provider default (google/gemini-2.0-flash-001 for OpenRouter, claude-sonnet-4-20250514 for Anthropic, gemini-2.0-flash for Google AI, gpt-4o-mini for OpenAI, llama3.1 for Ollama)."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Proxy settings. Strongly recommended — enable Apify residential proxy to avoid Google's CAPTCHA / 'unusual traffic' blocks, especially for popular head-term queries. Datacenter proxy or no proxy may trigger reCAPTCHA on common queries.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
