# Google Search Scraper — SERP, Qualified Leads & AI Overview (`memo23/google-search-scraper`) Actor

Scrape Google SERPs reliably and turn them into leads. Organic results, ads, People Also Ask, knowledge panels and AI Overview sources, plus opt-in contact-email enrichment with payment/Stripe qualification and a Perplexity AI answer. Free site:, filetype: and date operators. Pay per page.

- **URL**: https://apify.com/memo23/google-search-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** SEO tools, AI, Automation
- **Features:** Limited permissions
- **Stats:** 136 total users, 36 monthly users, 99.5% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.20 / 1,000 serp pages

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

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## Google Search Results Scraper

Scrape Google Search result pages (SERPs) and get clean, structured JSON — organic
results, related searches, People Also Ask, knowledge panels, and total result
counts — for any query, country, and language.

Built for reliability: a dual-engine HTTP fetcher with real browser TLS
impersonation, an 8-deep self-healing selector chain that survives Google's layout
rotations, and structural soft-block detection that won't false-reject a valid SERP.

![How the Google Search Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-google-search.png)

### What it extracts

- **Organic results** — position, title, URL, displayed URL, description, date,
  emphasized keywords, sitelinks, and inline product info (rating / reviews / price)
- **Paid ads** — the text ads above and below the results, with placement (top or
  bottom), title, the advertiser's landing URL, displayed URL, description and sitelinks
- **Related searches** — the "people also search for" / bottom-of-page queries
- **People Also Ask** — the expandable Q\&A questions (with answer text when present)
- **Knowledge panel** — title, subtitle, description, fact attributes (Born, Died,
  Address, Height, …), and source link
- **AI Overview** — detection + the cited **source domains** for GEO/AEO tracking
  (the generated prose itself is not available over the proxy — see **Limitations**)
- **Total results** — the "About N results" count
- **Contact emails (opt-in)** — turn a SERP into leads: scrape each result's own
  site for a contact email + people. See **Lead enrichment** below.
- **Perplexity AI answer (opt-in, BYOK)** — a grounded AI answer with citations per
  query, via Perplexity's official API with your key. See **Perplexity AI answer**.

### Coming from another Google search scraper?

If you're switching because another Google SERP scraper let you down, here's how this
one handles the things people most often run into:

| What tends to go wrong elsewhere | How this scraper handles it |
|---|---|
| Runs return 0 organic results on some queries, or sit empty for minutes | Dual HTTP engine (browser-grade TLS fingerprint + a fallback), an 8-deep self-healing selector chain that survives Google layout changes, and structural soft-block detection. An optional `residential` transport takes over if the SERP proxy struggles. |
| `site:` and other operators return unrelated domains | `site:`, `relatedToSite`, `intitle:`, `intext:`, `inurl:`, `filetype:`, date range and exact match are real input fields, folded into the query correctly — `site:github.com` returns only that domain. |
| Setting a results language (`lr=`) wipes out the organic results | `searchLanguage` returns a full results page — tested with German (`de`) returning 10 organic results. |
| Lead enrichment bills twice for the same contact in one run | Each business domain is scraped and billed **once per run**. A domain that shows up on several pages or queries reuses its cached contact for free — no second scrape, no second charge, and a page retry can't re-charge it. |
| AI Overview text comes back truncated or missing | You get AI Overview **detection plus the cited source domains** reliably (useful for GEO/AEO). The generated prose is produced client-side by Google and needs a JS browser, so the output says so plainly rather than passing a truncated "Show more" preview off as the answer. |

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `queries` | string\[] | — | One or more search terms. **Required.** |
| `maxPagesPerQuery` | integer | 1 | Pages to fetch per query (~10 results each). |
| `resultsPerPage` | integer | 10 | See the note under **Limitations** — Google caps this at ~10. |
| `countryCode` | string | `US` | Two-letter country (sets the Google domain, `gl` and the search location). |
| `languageCode` | string | `en` | Interface/results language (`hl`). |
| `safeSearch` | `off`/`medium`/`high` | `off` | SafeSearch level. |
| `includeRelated` | boolean | `true` | Extract related searches + People Also Ask. |
| `includeKnowledgePanel` | boolean | `true` | Extract the knowledge panel. |
| `includeAiOverview` | boolean | `true` | Detect AI Overview + extract its cited sources. Needs `appendUdm14: false`. |
| `includeAds` | boolean | `true` | Extract the text ads at the top and bottom of the page (see **Limitations**). |
| `appendUdm14` | boolean | `true` | Use Google's clean "Web" layout. **Set `false` to see AI Overviews.** Recommended on for max organic stability. |
| `useAdsBotUA` | boolean | `false` | Send the AdsBot-Google user agent. |
| `maxConcurrency` | integer | 5 | Parallel requests. |
| `maxRequestRetries` | integer | 5 | Retries per page before giving up. |
| `proxy` | object | GOOGLE_SERP | Proxy config. **Leave default** — see **Limitations**. |

#### Advanced search filters

Google search operators exposed as structured fields (all folded into the query /
URL — you can also type the operators directly inside a `queries` entry):

| Field | Type | Operator / param | Notes |
|---|---|---|---|
| `site` | string | `site:` | Restrict to one site. Wins over `relatedToSite`. |
| `relatedToSite` | string | `related:` | Pages related to a site. |
| `wordsInTitle` | string\[] | `intitle:` | Multi-word entries auto-quoted. |
| `wordsInText` | string\[] | `intext:` | Words required in body text. |
| `wordsInUrl` | string\[] | `inurl:` | Words required in the URL. |
| `fileTypes` | string\[] | `filetype:` | OR-combined (`pdf`, `docx`, …). |
| `forceExactMatch` | boolean | `"…"` | Wrap the query in quotes. |
| `searchLanguage` | string | `lr=lang_XX` | Results language (distinct from `hl`). |
| `locationUule` | string | `uule=` | Exact location: a uule code or a place name like `Berlin,Berlin,Germany`. Defaults to the country. |
| `quickDateRange` | string | `tbs=qdr:` | Relative recency: `h`, `d10`, `w`, `m6`, `y1`. |
| `afterDate` / `beforeDate` | string | `tbs=cdr:` | Absolute bounds (`YYYY-MM-DD` or `MM/DD/YYYY`). |
| `includeUnfilteredResults` | boolean | `filter=0` | Include Google's omitted near-duplicates (off by default). |
| `saveHtml` | boolean | — | Attach raw SERP HTML to each row under `html` (large). |
| `saveHtmlToKeyValueStore` | boolean | — | Save HTML to the KV store; add `htmlSnapshotUrl` to each row. |

#### Lead enrichment (opt-in)

Turn search results into leads. When `enrichEmails: true`, the top business domains
in each SERP get their **own site** scraped for a contact email + people; the hits
are attached to those organic results as `contactEmail` and `emailEnrichment`.

| Field | Type | Default | Notes |
|---|---|---|---|
| `enrichEmails` | boolean | `false` | Enable contact-email enrichment. |
| `maxEnrichedDomainsPerPage` | integer | `3` | Cap unique business domains enriched per page. |

- Best on **business-intent** queries (`"commercial plumbers chicago"`, `"B2B SaaS vendors"`).
- Non-business domains (search engines, social, Wikipedia, big marketplaces) are skipped;
  domains are de-duped per page.
- Best-effort and free (direct site scrape) — enrichment never fails a scrape.

#### Perplexity AI answer (opt-in, bring-your-own-key)

Attach a Perplexity (Sonar) AI answer to each query — grounded, with citations.
This calls Perplexity's **official API with your own key**, so **you are billed by
Perplexity** per request (it is not scraping). The answer lands on the page-1 row
under `perplexity` `{ answer, model, citations, searchResults?, relatedQuestions? }`.

| Field | Type | Default | Notes |
|---|---|---|---|
| `perplexitySearch` | boolean | `false` | Enable the Perplexity answer. |
| `perplexityApiKey` | string (secret) | — | Your key from [docs.perplexity.ai](https://docs.perplexity.ai). Required. |
| `perplexitySearchRecency` | `day`/`week`/`month`/`year` | — | Restrict grounding to recent content. |
| `perplexityRelatedQuestions` | boolean | `false` | Also return follow-up questions. |

Inert unless both the toggle is on **and** a key is supplied; a Perplexity error
never breaks the SERP scrape.

#### Example input

```json
{
  "queries": ["apify pricing 2026", "best web scraping tools"],
  "maxPagesPerQuery": 2,
  "countryCode": "US",
  "languageCode": "en"
}
```

### Output

One dataset item per `(query, page)`:

```json
{
  "query": "apify pricing 2026",
  "page": 1,
  "searchUrl": "http://www.google.com/search?q=apify+pricing+2026&...",
  "organicResults": [
    {
      "type": "organic",
      "position": 1,
      "title": "Apify pricing - plans for data collection at any scale",
      "url": "https://apify.com/pricing",
      "displayedUrl": "https://apify.com › pricing",
      "description": "...",
      "siteLinks": []
    }
  ],
  "paidResults": [],
  "relatedQueries": [{ "title": "apify free plan", "url": "https://www.google.com/search?q=..." }],
  "peopleAlsoAsk": [{ "question": "Is Apify free to use?", "answer": "...", "url": "https://..." }],
  "knowledgePanel": null,
  "aiOverview": { "detected": true, "textAvailable": false, "sources": [{ "url": "https://ibm.com/...", "domain": "ibm.com" }] },
  "totalResults": 1230000,
  "selectorUsed": "div.tF2Cxc",
  "scrapedAt": "2026-06-25T09:00:00.000Z"
}
```

`selectorUsed` tells you which parser variant matched — handy for spotting future
Google layout drift.

### How it works

- **Dual-engine fetch** — tries [`impit`](https://github.com/apify/impit) (Rust,
  real Chrome TLS + HTTP/2 fingerprint) first, falling back to `got-scraping`. Two
  independent fingerprints = two chances against bot detection.
- **`udm=14` clean layout** — by default the scraper requests Google's "Web" tab,
  which strips the AI Overview and returns stable, parseable markup.
- **Self-healing selectors** — organic results run through an 8-deep selector chain
  (2026 containers first, classic layouts as fallback, plus a class-agnostic
  `a:has(h3)` structural net), so a single Google class rename won't zero out a run.
- **Structural soft-block detection** — a page is only treated as blocked if it
  *doesn't* structurally look like a SERP, so benign `/sorry/` footer links never
  cause a false "blocked".

### Limitations & notes

- **Use the default GOOGLE_SERP proxy.** Google aggressively blocks datacenter and
  residential IPs for SERP scraping (JS-challenge / CAPTCHA interstitials). This
  actor is built around Apify's **GOOGLE_SERP** proxy group, which is purpose-built
  for Google and applied automatically. **Overriding `proxy` to RESIDENTIAL or
  datacenter groups will fail** with soft-blocks — leave the proxy at its default.

- **Paid ads (`paidResults`) appear when Google shows them.** Each entry is one text
  ad, in page order (`position`), with `placement: "top"` (above the organic results)
  or `"bottom"` (below them). `url` is the advertiser's landing page rather than
  Google's click link: the full landing URL when the ad carries one (Google's click
  IDs such as `gclid` removed), otherwise the advertiser's site. Sitelinks get the
  advertiser URL when the ad carries it, otherwise an absolute google.com click link.
  The actor never opens an ad link, so scraping does not register clicks the
  advertiser pays for.
  Google decides per page load whether to show ads, so the same commercial query can
  return ads on one run and an empty array on the next. Shopping, hotel and
  sponsored-places units are not included.

- **AI Overview prose is not available over the proxy.** Google server-renders the
  AI Overview *shell* (label + citation cards) but generates the answer text
  client-side, so a no-JS request receives a placeholder. `aiOverview` therefore
  returns `detected` + the cited `sources` (useful for GEO/AEO — which domains
  Google cites) with `textAvailable: false`. The prose itself needs a JS-rendering
  path. Requires `appendUdm14: false` (the default
  `udm=14` strips AI Overviews entirely).

- **`resultsPerPage` is effectively ~10.** Google ignores the `num` parameter on
  most modern SERP layouts and returns ~10 results per page. To collect more, raise
  `maxPagesPerQuery` rather than `resultsPerPage`. Pagination always steps by the
  real page size, so no results are skipped if you set a larger value.

- **Knowledge-panel images** are lazy-loaded by Google's JS, so `imageUrl` may be
  absent even when the panel is otherwise fully populated.

- **People Also Ask answers** are only present when Google pre-expands the card;
  for most queries you'll get the question and destination URL but no answer text.

- **AI Overview** is intentionally excluded by `appendUdm14: true`. Set it to
  `false` if you want the default SERP layout (which can include the AI Overview and
  more ad/PAA surfaces), at the cost of slightly less stable organic markup.

### Tips

- Keep `appendUdm14` on for the most reliable organic extraction.
- For deep coverage, set `maxPagesPerQuery` (e.g. 5) instead of `resultsPerPage`.
- Use `countryCode` + `languageCode` together for accurate localized results
  (e.g. `DE` + `de`, `JP` + `ja`).
- Google search operators work inside `queries` (`site:`, `intitle:`, `"exact"`,
  `OR`, `-exclude`, `filetype:`).

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/google-search-scraper`).

**Purpose:** Scrape structured Google SERPs for any query, country and language — organic results, related searches, People Also Ask, knowledge panel, AI-Overview cited sources and total counts — with a self-healing selector chain that survives Google's layout rotations.

**Minimal input:**

```json
{
  "queries": ["best web scraping tools"],
  "maxPagesPerQuery": 1
}
```

**Output:** one row per (query, page) — query, page, searchUrl, organicResults {type, position, title, url, displayedUrl, description, siteLinks}, paidResults {type, position, placement, title, url, displayedUrl, description, siteLinks}, relatedQueries {title, url}, peopleAlsoAsk {question, answer, url}, knowledgePanel, aiOverview {detected, textAvailable, sources {url, domain}}, totalResults, selectorUsed, scrapedAt.

**Behaviors an agent should know:**

- `queries` is the only required field; one row per query × page. To collect more results, raise `maxPagesPerQuery` (default 1) — Google caps `resultsPerPage` at ~10 regardless of the value set.
- Leave `proxy` at its default GOOGLE_SERP group; overriding to residential/datacenter groups fails with soft-blocks.
- `appendUdm14` (default true) gives stable organic markup but strips AI Overview; set it false (with `includeAiOverview`) to get the AI-Overview `sources` — the generated prose is never available over the proxy.
- `paidResults` lists the page's text ads with `placement` "top" or "bottom"; `url` is the advertiser's landing page rather than Google's click link, and ad links are never opened. Google shows ads on some page loads and not others, so an empty array is normal even for commercial queries.
- `enrichEmails` (opt-in, best-effort, free) scrapes top business domains' own sites for `contactEmail`; `perplexitySearch` (opt-in, bring-your-own-key) attaches a Perplexity answer and is billed by Perplexity, not this actor.
- Pay-per-event billing — see the Pricing tab on the actor page.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Google LLC or any of its subsidiaries. All trademarks mentioned, including Google and Google Search, are the property of their respective owners.

The scraper accesses only publicly available Google search results pages — no authenticated endpoints, paid features, or content behind any google.com login wall. Users are responsible for ensuring their use complies with google.com's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

### SEO Keywords

google search scraper, scrape google, google serp scraper, google search API, google.com scraper, Apify google, serp scraper, search results scraper, organic results scraper, seo rank tracking, keyword research data, competitor serp analysis, ai overview extraction, people also ask data, search engine intelligence, serp data export, marketing analytics data

# Actor input Schema

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

One or more search queries. Each query produces one or more SERP rows.

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

How many organic results per SERP page (Google's effective cap is 10 on most pages since Sept 2025).

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

Paginate through this many SERP pages per query.

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

Two-letter country code, e.g. DE, GB, AU. Searches that country's own Google (google.de, google.co.uk, google.com.au ...) as a searcher located in that country, so results and ads are local. US and unrecognised codes search google.com.

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

Two-letter language code (hl param). Controls the SERP UI language.

## `safeSearch` (type: `string`):

Safe search level.

## `includeAds` (type: `boolean`):

Parse and return sponsored results alongside organic.

## `includeRelated` (type: `boolean`):

Include 'Related searches' and 'People also ask' boxes.

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

Parse the right-rail knowledge panel if present.

## `includeAiOverview` (type: `boolean`):

Detect the AI Overview block and extract its cited source links (great for GEO/AEO). Note: the generated prose is created client-side and is NOT available over the HTTP proxy — only detection + sources are returned. Requires appendUdm14 = false (udm=14 strips AI Overviews).

## `useAdsBotUA` (type: `boolean`):

Use AdsBot-Google UA to attempt to receive the legacy SERP layout. As of May 2026 Google serves a 'browser unsupported' page to this UA on most IPs — leave OFF unless you have a specific proxy where it works.

## `appendUdm14` (type: `boolean`):

Append \&udm=14 to disable AI Overviews. Stacks with AdsBot UA for maximum parser stability.

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

How many queries to process in parallel.

## `maxRequestRetries` (type: `integer`):

Retries per SERP page request when soft-blocked.

## `serpTransport` (type: `string`):

How Google is fetched. `apify-serp` (default) uses Apify's GOOGLE_SERP proxy: ~99.7% success, one request per page, and $0.0025 per query billed to the run. `residential` races our own US residential sessions instead, which measured ~83% success per round at roughly 1/20th the proxy cost, with a little more latency. Experimental — leave on the default unless you are comparing the two. Either way the run log ends with a \[SERP-TRANSPORT] line showing what was actually spent.

## `proxy` (type: `object`):

Apify GOOGLE_SERP proxy group is strongly recommended for Google scraping.

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

Limit results to one site, e.g. `example.com` (applies the `site:` operator). Takes precedence over 'Related to site'.

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

Find pages related to a site, e.g. `example.com` (applies the `related:` operator). Ignored if 'Site' is set.

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

Each entry must appear in the page title (`intitle:`). Multi-word entries are auto-quoted.

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

Each entry must appear in the page body text (`intext:`).

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

Each entry must appear in the page URL (`inurl:`).

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

Restrict to file types, OR-combined (e.g. `pdf`, `docx`). Applies the `filetype:` operator.

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

Wrap the query in quotes for an exact-phrase match.

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

Restrict results to a language via the `lr` parameter, e.g. `de` or `lang_de`. Distinct from the `hl` interface language.

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

Exact location for the search, narrower than the country: a Google `uule` code, or a place name in Google's format such as `Berlin,Berlin,Germany`. Leave empty to search from the whole country set in Country code.

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

Relative recency filter (`tbs=qdr:`). Examples: `h` (past hour), `d10` (10 days), `w`, `m6`, `y1`. Wins over Before/After if both set.

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

Only results after this date. Absolute date `YYYY-MM-DD` or `MM/DD/YYYY`.

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

Only results before this date. Absolute date `YYYY-MM-DD` or `MM/DD/YYYY`.

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

Include the near-duplicate results Google normally omits (`filter=0`). Off by default for cleaner output.

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

Attach the raw SERP HTML to each dataset row under `html`. Makes the dataset large — use for debugging.

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

Save each SERP's raw HTML to the key-value store and add a `htmlSnapshotUrl` to the dataset row.

## `enrichEmails` (type: `boolean`):

Opt-in, best-effort lead enrichment: for the top business domains in each SERP, scrape the result's OWN site for contact emails and people. Adds `contactEmail` + `emailEnrichment` to those organic results. Skips non-business domains (search/social/Wikipedia/marketplaces). Best on business-intent queries (e.g. 'plumbers chicago', 'B2B SaaS vendors').

## `qualifyByPayment` (type: `boolean`):

Requires "Enrich with contact emails". Scans each business's website — reusing the pages already fetched for email discovery, so no extra cost or time — for payment processors and e-commerce platforms (Stripe, Shopify, PayPal, Paddle, Lemon Squeezy, WooCommerce, Square, Chargebee and more). Adds takesPayments (is this a real paying business?), paymentProcessors (which stack), stripeLiveKey (the public key if exposed) and paymentConfidence. Turn raw contacts into monetization-qualified leads. No extra charge — included with each enriched company.

## `maxEnrichedDomainsPerPage` (type: `integer`):

Cap how many unique business domains to enrich per SERP page (bounds cost/time). Only applies when 'Enrich results with contact emails' is on.

## `perplexitySearch` (type: `boolean`):

Also fetch a Perplexity (Sonar) AI answer per query, attached to the page-1 row as `perplexity`. Bring your own Perplexity API key below — you are billed by Perplexity per request.

## `perplexityApiKey` (type: `string`):

Your Perplexity API key (from docs.perplexity.ai). Required for the Perplexity answer; runs are billed to YOUR Perplexity account. Leave blank to disable.

## `perplexitySearchRecency` (type: `string`):

Restrict Perplexity's web grounding to recent content.

## `perplexityRelatedQuestions` (type: `boolean`):

Ask Perplexity to also return follow-up questions.

## Actor input object example

```json
{
  "queries": [
    "best CRM software 2026",
    "apify scraper alternatives"
  ],
  "resultsPerPage": 10,
  "maxPagesPerQuery": 1,
  "countryCode": "US",
  "languageCode": "en",
  "safeSearch": "off",
  "includeAds": true,
  "includeRelated": true,
  "includeKnowledgePanel": true,
  "includeAiOverview": true,
  "useAdsBotUA": false,
  "appendUdm14": true,
  "maxConcurrency": 5,
  "maxRequestRetries": 3,
  "serpTransport": "apify-serp",
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  },
  "forceExactMatch": false,
  "includeUnfilteredResults": false,
  "saveHtml": false,
  "saveHtmlToKeyValueStore": false,
  "enrichEmails": false,
  "qualifyByPayment": false,
  "maxEnrichedDomainsPerPage": 3,
  "perplexitySearch": false,
  "perplexityRelatedQuestions": false
}
```

# 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 CRM software 2026",
        "apify scraper alternatives"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "GOOGLE_SERP"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/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 CRM software 2026",
        "apify scraper alternatives",
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["GOOGLE_SERP"],
    },
}

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

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

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

```

## CLI example

```bash
echo '{
  "queries": [
    "best CRM software 2026",
    "apify scraper alternatives"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  }
}' |
apify call memo23/google-search-scraper --silent --output-dataset

```

## MCP server setup

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

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

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5whUZMSnCaBMa6VpS/builds/AwwHdRp8b5BCnCPHx/openapi.json
