# Google Shopping Scraper — Products, Prices & Sellers (`experthasan/google-shopping-scraper`) Actor

Scrape Google Shopping product listings, prices, merchants, ratings and every seller offer for a product. No API key, no headless browser.

- **URL**: https://apify.com/experthasan/google-shopping-scraper.md
- **Developed by:** [Mahmudul Hasan](https://apify.com/experthasan) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product scrapeds

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/platform/actors/running/actors-in-store#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 Shopping Scraper — Products, Prices & Sellers

Pull live product listings and seller prices from Google Shopping. No API key, no Google
Cloud project, no headless browser — the Actor talks to Google's shopping vertical directly.

### What you get

| Action | What it returns |
| ------ | --------------- |
| **Product search** | Every product tile for a query: title, price, original price, merchant, rating, review count, product and catalog IDs, link and image |
| **Seller offers** | Every seller carrying a product, with each one's price — the "compare prices" panel |

Results land in the run's dataset and export to JSON, CSV, Excel, XML or via the API.

### Pricing

| You pay for | Price |
| ----------- | ----- |
| Each product scraped | **$1.00 per 1,000** |
| Each seller offer scraped | **$0.80 per 1,000** |
| Each page requested from Google | $0.004 |
| Actor start | $0.05 per 1,000 runs |

Google returns 10 products per page, so a 40-product search is 4 pages: 4 × $0.004 + 40 ×
$0.001 = **$0.056**, or about **$1.40 per 1,000 products** — cheaper than comparable Google
Shopping scrapers on the Store.

**About the page fee.** Google Shopping is the most aggressively bot-protected Google surface,
and every page fetch consumes a paid proxy request whether or not Google returns results. The
$0.004 page fee covers that. A query that comes back empty still costs the page fee — you are
not charged the per-product fee, only the request.

Set a **maximum cost per run** in the run options and the Actor stops cleanly when it gets
there. Platform compute and proxy are included — you are never billed separately for usage.

### Input

Product search:

```json
{
  "action": "search",
  "queries": ["mechanical keyboard", "iphone 16 case"],
  "maxProductsPerQuery": 40,
  "minPrice": "50",
  "maxPrice": "150",
  "sort": "price_asc",
  "country": "us",
  "language": "en"
}
```

Seller offers — the IDs come from the `catalog_id` and `product_id` fields of a search run:

```json
{
  "action": "offers",
  "products": [
    { "catalogId": "1234567890123456789" },
    { "productId": "9876543210987654321" }
  ]
}
```

| Field | Description |
| ----- | ----------- |
| `action` | `search` or `offers` |
| `queries` | Search terms, one per line (`search` only) |
| `products` | Products to look up, each with `catalogId` or `productId` (`offers` only) |
| `maxProductsPerQuery` | How many results to request per query (10–100, default 40) |
| `minPrice` / `maxPrice` | Optional price filters |
| `sort` | `relevance`, `price_asc`, `price_desc` or `rating` |
| `country` / `language` | Google `gl` and `hl` codes — sets the storefront and currency |
| `proxyConfiguration` | Google SERP proxy is on by default. Leave it on. |
| `requestDelaySeconds` | Pause between requests (default 2) |

### Output

One dataset item per product:

```json
{
  "type": "product",
  "query": "mechanical keyboard",
  "title": "Keychron K2 Wireless Mechanical Keyboard",
  "price": "$89.00",
  "price_value": 89.0,
  "currency": "$",
  "original_price": "$99.00",
  "original_price_value": 99.0,
  "condition": "New",
  "merchant": "Keychron",
  "rating": 4.6,
  "reviews": 2841,
  "product_id": "1234567890123456789",
  "catalog_id": "9876543210987654321",
  "link": "https://www.google.com/shopping/product/...",
  "image": "https://api.apify.com/v2/key-value-stores/.../records/image-6e500831fbffe8fb.webp"
}
```

Prices come both as Google displayed them (`price`) and parsed into a number you can sort and
compare (`price_value` + `currency`).

`image` is always a real, linkable URL. Google serves most Shopping thumbnails as inline data
rather than as URLs, so those are saved to the run's key-value store and the item points at
them — no multi-kilobyte blobs in your CSV. Identical thumbnails are stored once. Set
`storeImages` to `false` if you don't need images.

Offer items carry `product_title`, `merchant`, `price` and `link`. Queries that return
nothing are written as `{"type": "empty", ...}` and failures as `{"type": "error", ...}`,
so a bad query never kills the run.

### Common uses

- Track competitor pricing on your SKUs across every merchant carrying them
- Find the cheapest seller for a product before buying or reselling
- Build a price-comparison dataset for a category or brand
- Monitor MAP compliance across your retail partners
- Feed live retail prices to an AI shopping assistant (this Actor supports agentic payments
  via x402 and Skyfire)

### Integrations

Run on a schedule, or send the output to Google Sheets, Airtable, Slack, Make, Zapier or your
own webhook. Everything is reachable through the [Apify API](https://docs.apify.com/api/v2)
and the JavaScript and Python clients.

### Notes and limits

- This is an **unofficial scraper**. Google changes Shopping markup frequently and per region;
  the parser uses several fallback strategies, but when a page parses to zero products the
  Actor logs it and moves on rather than failing the run.
- **Keep the proxy on.** Without it you will be CAPTCHA-blocked within a handful of requests.
- Seller offers work best with `catalogId`. A bare `productId` sometimes lands on a
  not-available page, in which case the item comes back empty with a note explaining why.
- Prices are what Google displays for your `country` and `language`; they can differ from the
  merchant's own site and move between the scrape and a purchase.
- Scrape only public data and use the output in line with Google's terms and applicable law.

### Support

Found a bug or need a field that is not extracted yet? Open an issue on the Actor's **Issues**
tab.

# Actor input Schema

## `action` (type: `string`):

What to extract. `search` finds products; `offers` lists every seller for one product.

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

Only used by the `search` action. One query per line, e.g. `iphone 16 case`.

## `products` (type: `array`):

Only used by the `offers` action. One object per product: `{ "catalogId": "..." }` or `{ "productId": "..." }`. Both IDs come from the `catalog_id` and `product_id` fields of a `search` run — `catalogId` is more reliable.

## `maxProductsPerQuery` (type: `integer`):

How many results to request per query. Google returns 10 per page, so this rounds up to whole pages — 40 means 4 pages. Each page is billed as one `google-request` and each product returned as one `product-scraped`.

## `minPrice` (type: `string`):

Optional price floor, in the currency Google shows for your country. Leave empty for no filter.

## `maxPrice` (type: `string`):

Optional price ceiling. Leave empty for no filter.

## `sort` (type: `string`):

How Google should order the results.

## `storeImages` (type: `boolean`):

Google serves most Shopping thumbnails as inline data rather than URLs. With this on, those thumbnails are saved to the run's key-value store and `image` holds a real, linkable URL. Turn it off if you don't need images — it costs a fraction of a cent per 1,000 images.

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

Two-letter country code — sets the storefront and currency, e.g. `us`, `gb`, `de`.

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

Two-letter language code for the results, e.g. `en`, `de`, `bn`.

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

Google Shopping is heavily bot-protected. The Google SERP proxy is enabled by default and is what makes runs succeed — turning it off will get you CAPTCHA-blocked quickly.

## `requestDelaySeconds` (type: `integer`):

Seconds to wait between consecutive Google requests. Raise this if you still see blocked responses.

## Actor input object example

```json
{
  "action": "search",
  "queries": [
    "mechanical keyboard"
  ],
  "products": [
    {
      "catalogId": ""
    }
  ],
  "maxProductsPerQuery": 40,
  "sort": "relevance",
  "storeImages": true,
  "country": "us",
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "GOOGLE_SERP"
    ]
  },
  "requestDelaySeconds": 2
}
```

# Actor output Schema

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

One item per product: title, price as shown plus a numeric price\_value and currency, original price, merchant, rating, review count, condition, product and catalog IDs, link and image URL.

## `offers` (type: `string`):

The same dataset opened on the offers view — every seller carrying a product, with each one's price.

## `images` (type: `string`):

Product thumbnails saved during the run. Google serves most Shopping thumbnails inline rather than as URLs, so they are stored here and each dataset item's `image` field points at the corresponding record.

# 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": [
        "mechanical keyboard"
    ],
    "products": [
        {
            "catalogId": ""
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("experthasan/google-shopping-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": ["mechanical keyboard"],
    "products": [{ "catalogId": "" }],
}

# Run the Actor and wait for it to finish
run = client.actor("experthasan/google-shopping-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": [
    "mechanical keyboard"
  ],
  "products": [
    {
      "catalogId": ""
    }
  ]
}' |
apify call experthasan/google-shopping-scraper --silent --output-dataset

```

## MCP server setup

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