# Google Search Results Scraper (`dami_studio/google-search-results-scraper`) Actor

Scrape Google Search: organic results, ads, People Also Ask, related searches and pagination, with country, language and Google-domain controls. No API key. The proxy fallback is on by default because plain HTTP now hits Google's JavaScript gate. Blocked and empty runs cost only the start fee.

- **URL**: https://apify.com/dami\_studio/google-search-results-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** SEO tools, Marketing, Automation
- **Stats:** 3 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 search results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

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

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

# README

## Google Search Results Scraper

Search Google and return structured, deduplicated result rows without an API key. The actor requests ordinary Google HTML directly first, then falls back to the proxy lanes.

> **Since 2026 Google requires JavaScript for `/search`.** A plain HTTP request answers `200` with a ~90 KB challenge shell that contains no results, whatever address it comes from and whatever user agent it sends; following the shell lands on a page titled "Enable JavaScript to use search". This is reported as `JS_REQUIRED`, not as a block, because rotating IP addresses cannot fix it. `enableProxyFallback` is therefore on by default: the Google SERP lane is the transport that still returns server-rendered result HTML.

### Returned data

- `organic`: title, URL, domain, displayed URL, snippet, page, and rank.
- `ad`: detectable paid search result title, URL, domain, and snippet.
- `people_also_ask`: visible question and best-effort answer text.
- `related_search`: related phrase and its Google search URL.
- `transport`: `direct` when the direct request worked, or `proxy_fallback_serp`, `proxy_fallback_datacenter`, `proxy_fallback_isp` or `proxy_fallback_customer` when the fallback carried it, so downstream users can tell which path a row came from.

The actor supports `site:`, `intitle:`, quoted phrases, `OR`, negative terms, country (`gl`), language (`hl`), Google domain, and pagination. Duplicate URLs and repeated PAA/related phrases are removed across pages.

### Input

`query` is the only meaningful required runtime value. `maxResults` is 1-100 and `maxPages` is 1-10. Ads, PAA, and related searches can each be disabled.

`enableProxyFallback` is on by default, and with the JavaScript gate in place you need it on to get any rows back. The actor still makes the direct request first and only opens a proxy after that request comes back as a block, a rate limit, a CAPTCHA, unusual-traffic, or the JavaScript gate. The fallback tries the Google SERP lane first, because that is the one that still answers with parseable HTML, then rotating Apify datacenter addresses. `RESIDENTIAL` is not offered: ask for it and the run quietly moves to datacenter and says so in a `proxyNotice` field on the output rows. Supply `proxyConfiguration` when you need a specific country. Your own proxy servers passed as `proxyUrls` are used verbatim and take precedence.

An empty input returns a representative non-empty sample row. It is marked `_sample: true` and is never charged.

### Billing

`$0.01` to start a run, then `$0.001` per row returned — `$1.00` per 1,000 rows. Flat: the same rate on every plan, no volume tiers and no minimum spend.

Every row that lands in the dataset is charged once, whether it is an organic result, an ad, a People Also Ask entry or a related search. `maxResults` is the cap on all of them together, so it is also the cap on what a run can charge you: `maxResults: 10` cannot bill more than ten rows however many pages it reads.

What is never charged: the `_sample` row an empty input returns, and every diagnostic row. A search that is blocked, rate-limited, or simply finds nothing writes a diagnostic explaining which, and costs you the start charge and not a penny more.

The start charge counts once per gigabyte of run memory, so leaving the memory at its default keeps it at one.

### Example

```json
{
  "query": "best running shoes site:example.com",
  "countryCode": "US",
  "language": "en",
  "googleDomain": "google.com",
  "maxResults": 20,
  "maxPages": 2,
  "includeAds": true,
  "includePeopleAlsoAsk": true,
  "includeRelatedSearches": true,
  "enableProxyFallback": true
}
```

# Actor input Schema

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

Google query. Supports operators such as site:, intitle:, quotes, OR, and minus terms.

## `googleDomain` (type: `string`):

Google host without protocol, for example google.com, google.ca, or google.co.uk.

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

Google country edition passed as gl, for example US, CA, GB, or DE.

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

Google interface language passed as hl, for example en, fr, or de.

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

Maximum rows to return in total, counting organic results, ads, People Also Ask and related searches together. Google may provide fewer. This is also the cap on how many rows a run can charge for.

## `maxPages` (type: `integer`):

Follow Google pagination up to this many pages. Each page is fetched only as needed.

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

Return detectable paid search ads in addition to organic results.

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

Return visible PAA questions and answer text when present in the HTML.

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

Return related-search phrases from the bottom of each page.

## `enableProxyFallback` (type: `boolean`):

Retry through the proxy lanes when the direct request cannot be read. Google now serves its "Enable JavaScript to use search" gate to every plain-HTTP client on every address, so the direct lane alone returns no results and this must stay on for the Actor to produce rows.

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

Used only when the proxy fallback is enabled and the direct request could not be read. The Google SERP lane is tried first because it is the one that still returns parseable HTML, then rotating datacenter addresses. RESIDENTIAL is not offered and is automatically replaced with datacenter; supply your own proxy servers under Custom proxies if you need different exits.

## Actor input object example

```json
{
  "query": "best running shoes",
  "googleDomain": "google.com",
  "countryCode": "US",
  "language": "en",
  "maxResults": 10,
  "maxPages": 1,
  "includeAds": true,
  "includePeopleAlsoAsk": true,
  "includeRelatedSearches": true,
  "enableProxyFallback": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "BUYPROXIES94952"
    ]
  }
}
```

# Actor output Schema

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

One row per organic result, ad, People Also Ask question, related search, or uncharged diagnostic.

# 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 = {
    "query": "best running shoes",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "BUYPROXIES94952"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/google-search-results-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 = {
    "query": "best running shoes",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["BUYPROXIES94952"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/google-search-results-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 '{
  "query": "best running shoes",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "BUYPROXIES94952"
    ]
  }
}' |
apify call dami_studio/google-search-results-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/google-search-results-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/FlLBC8fTCJkS6vJZb/builds/n2eUgSDrP7PDWEMUC/openapi.json
