# Google Shopping Scraper (`cornflower_vision/google-shopping-scraper`) Actor

Scrape Google Shopping: prices, discounts, stores, ratings, exact review counts, brands, images and product pages. 100+ products per search, no duplicates. Pay only per product.

- **URL**: https://apify.com/cornflower_vision/google-shopping-scraper.md
- **Developed by:** [Jason Todd](https://apify.com/cornflower_vision) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.20 / 1,000 products

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 Shopping Scraper

Scrape product listings from **Google Shopping**: titles, prices, discounts, stores, delivery and return terms, ratings with **exact review counts**, brands, images and a link to Google's product page for every product.

- **100+ products per search.** Google's first Shopping page had 45-64 products in our tests, and each further page about 40 more; the Actor fetches the next pages and merges them without duplicates (up to 318 different products for one query in our tests).
- **Price range filter.** Set a minimum and/or maximum price and the Actor uses Google's own price filter, so you get full pages of matching products, not the few that happen to fall in range on unfiltered pages. Products outside your range are always left out, free of charge.
- **Clean numbers.** Prices come as text and as numbers with a currency code (`priceValue`, `currency`), plus the price before a discount and the discount in percent.
- **Exact review counts.** Google's cards say "6.2K reviews"; the Actor reads the exact number (6213) from the data Google embeds in the page.
- **Prices in your country's currency.** Google sometimes answers as if the visitor were in another country (prices in rupees, or New Zealand dollars written as "$"); the Actor notices from the page itself and fetches such a page again.
- **Pay only for products.** No charge for pages without products, retries, duplicates or products your filters leave out.
- **Fast and light.** No browser; a page takes a few seconds.

### What you can use it for

- Track prices and discounts of products or competitors across stores.
- Find which stores sell a product, and at what delivery and return terms.
- Build product catalogs and price comparison feeds with images and brands.
- Research a market: best-rated products, review counts, price ranges.

### Input

| Field | What it does | Default |
|---|---|---|
| **Search queries** (`queries`) | What you would type into Google Shopping, one per line, e.g. `wireless earbuds` or `nike pegasus 41`. | required |
| **Max products per query** (`maxProductsPerQuery`) | 1-1000. The Actor stops a query earlier when Google has no more products. | 100 |
| **Country** (`country`) | Two-letter code of the market, e.g. `us`, `gb` (or `uk`), `ca`, `au`, `de`. Prices come in that country's currency. For the country's own shops, write the query in its language, e.g. `tai nghe không dây` rather than `wireless earbuds` with `vn`: an English query brings more sellers from abroad (see **Skip offers from sellers abroad**). | `us` |
| **Language** (`language`) | Google's interface language. See [Limitations](#limitations). | `en` |
| **Min price** (`minPrice`) | Only products priced at least this much, in the country's currency (US dollars for `us`, pounds for `gb`...). Decimals are fine. | none |
| **Max price** (`maxPrice`) | Only products priced at most this much, in the same currency. | none |
| **Skip offers from sellers abroad** (`skipForeignOffers`) | Leave out products sold from another country (see `foreignPrice`). | off |
| **Skip used and refurbished products** (`skipUsedProducts`) | Leave out products marked Pre-owned, Refurbished or Used. | off |
| **Pages at the same time** (`maxConcurrency`) | 1-20. With 256 MB of memory (the default) the Actor fetches at most 8 pages at once; give the run more memory for more. | 5 |

Example:

```json
{
    "queries": ["wireless earbuds", "air fryer"],
    "maxProductsPerQuery": 100,
    "country": "us",
    "minPrice": 50,
    "maxPrice": 150,
    "skipForeignOffers": true
}
```

### Output

One item per product. Example:

```json
{
  "query": "wireless earbuds",
  "rank": 2,
  "page": 1,
  "title": "Beats Solo Buds Wireless Earbuds",
  "brand": "Beats",
  "price": "$69.99",
  "priceValue": 69.99,
  "currency": "USD",
  "originalPrice": "$80",
  "originalPriceValue": 80,
  "discountPercent": 12,
  "foreignPrice": null,
  "condition": null,
  "merchant": "Best Buy",
  "moreMerchants": true,
  "delivery": "Free delivery by Fri",
  "returns": "15-day returns",
  "rating": 3.8,
  "reviewCount": 6213,
  "badges": [],
  "imageUrl": "https://encrypted-tbn2.gstatic.com/shopping?q=tbn:ANd9GcSQnGg6ee9gh0KOOWZFMqbmbUGjWa3kZ5V5...",
  "productUrl": "https://www.google.com/search?ibp=oshop&q=wireless+earbuds&prds=catalogid:10506635979914339716,...",
  "productId": "6916146097244474512",
  "catalogId": "10506635979914339716",
  "offerId": "14423844132016158567",
  "groupId": "549048356659243400",
  "scrapedAt": "2026-10-22T03:36:21Z"
}
```

Notes on some fields:

- Fields Google does not show for a product are `null` or empty (`[]`).
- `merchant` is the store Google shows first; `moreMerchants` is `true` when other stores sell the product too. A product sold by several stores at different prices shows its lowest price with a plus (`$99+`) and often no single store; `moreMerchants` is then `true`.
- `foreignPrice` is set for sellers in another country: `price` is then Google's conversion to your country's currency, and `foreignPrice` the seller's own price (e.g. `€131`). These offers appear mostly on later pages.
- `condition` is `Pre-owned`, `Refurbished` or `Used` when Google marks it, or when the title says so ("Refurbished", "Renewed", "Pre-owned"); otherwise `null`.
- `productUrl` opens Google's page for the product, with its description, specifications, reviews and prices from many stores.
- `page` is the Google Shopping page the product was on; `rank` is the order in which products were found for the query.
- `productId` is Google's id of the product. Use it to spot the same product in later runs.

In the **Output** tab, the **Products** and **Prices** views show the most useful columns. You can download everything as JSON, CSV, Excel, XML or HTML, or get it through the [Apify API](https://docs.apify.com/api/v2).

The key-value store also has a `SUMMARY` record: for each query, how many products and pages it got and why it stopped.

### Pricing

This Actor uses **pay-per-event** pricing: you pay for each product in your results, **$2.20 per 1,000 products** at the time of writing (see the **Pricing** tab for the current price). Products found twice are charged once. Pages without products, retries (including pages Google priced in another currency or showed without your price filter), Google's blocks, products skipped by your filters and products Google lists without a price (cards still loading, monthly payment plans; they are left out) cost you nothing.

A few examples:

- 1 query, 100 products: about $0.22
- 50 queries × 100 products: about $11
- 1,000 products per day for a month: about $66

You can set a maximum cost per run in the run options. The Actor then stops at or just under that amount (it does not open another page whose results it could not charge for) and keeps everything found so far.

### Limitations

- The data is what Google Shopping shows. Direct links to the stores are not in Google's results page; `productUrl` leads to Google's product page, which links to them.
- The price range uses Google's own price filter, which goes by the price Google shows on the card (`price`). Now and then Google ignores the filter on a page (about 1 page in 4 in our tests): the Actor asks for that page again, up to 3 times. It also checks every product and leaves out, free of charge, any outside your range. `SUMMARY` shows `outsidePriceRange` (products left out for their price) and `pagesWithoutPriceFilter` per query.
- Later pages hold more offers from sellers abroad and used products. Use the two skip options if you only want local, new products.
- Prices, stores, delivery and returns are read from labels Google writes in English, so keep language `en` (the default). Numbers written the local way ("Rated 4,5 out of 5" on German pages) are read correctly. Google does not show delivery terms in every country (none on German pages in our tests), so `delivery` can be empty there.
- One run takes up to 2,000 queries and 250,000 products (queries × max products per query); split bigger jobs into several runs. A run has 1 hour by default: for hundreds of queries, raise the timeout in the run options or the pages at the same time.
- The Actor was tested on searches in the US, the UK, Canada and Germany (October 2026); other countries should work the same way. Each Google page goes through Apify's Google SERP proxy, from the country you choose; the Actor does not log in anywhere.

### FAQ

**Why are some products unrelated to my query?**
For a query it cannot match (a typo, a made-up word), Google Shopping still lists popular products. When Google asks "Did you mean ...?", the Actor logs a warning and the `SUMMARY` record shows Google's suggestion as `didYouMean` for that query.

**Why did a query return fewer products than I asked for?**
Google had no more products for it, or more pages kept showing products already found. The `SUMMARY` record says why each query stopped.

**Can I monitor prices every day?**
Yes: schedule the Actor and compare `priceValue` by `productId` between runs.

**Is it legal to scrape Google Shopping?**
The Actor only collects product listings that are publicly shown in Google search results. You are responsible for how you use the data. If in doubt, ask a lawyer.

**Something doesn't work or a field is missing.**
Please open an issue in the **Issues** tab with the run ID. Google changes its pages from time to time; the Actor saves a copy of any page that looks unusual, which makes fixes quick.

# Actor input Schema

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

What you would type into Google Shopping, one per line, for example <code>wireless earbuds</code> or <code>nike pegasus 41</code>. Each query is searched separately.

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

The first Google Shopping page has about 45-60 products; each further page has about 40 more. The Actor stops a query earlier when Google has no more products or new pages repeat the ones it already has.

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

Two-letter country code of the market to search, for example <code>us</code>, <code>gb</code>, <code>ca</code>, <code>au</code>, <code>de</code>. Prices come in that country's currency.

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

Language of the Google interface, for example <code>en</code>. Prices, stores and delivery are read from labels Google writes in English, so keep <code>en</code> for complete results.

## `minPrice` (type: `number`):

Only products priced at least this much, in the currency of the country above (US dollars for <code>us</code>, pounds for <code>gb</code>...). The Actor uses Google's own price filter, so you get full pages of products in your range. Leave empty for no lower limit.

## `maxPrice` (type: `number`):

Only products priced at most this much, in the same currency. Leave empty for no upper limit. Products outside the range that Google still shows are left out, and you don't pay for them.

## `skipForeignOffers` (type: `boolean`):

Google also lists sellers in other countries, with a converted price and the original one in <code>foreignPrice</code>. Turn on to leave them out (you don't pay for skipped products).

## `skipUsedProducts` (type: `boolean`):

Leave out products marked Pre-owned, Refurbished or Used (you don't pay for skipped products).

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

How many Google Shopping pages are fetched in parallel. With 256 MB of memory (the default) at most 8 are; give the run more memory for more.

## Actor input object example

```json
{
  "queries": [
    "wireless earbuds"
  ],
  "maxProductsPerQuery": 100,
  "country": "us",
  "language": "en",
  "skipForeignOffers": false,
  "skipUsedProducts": false,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `products` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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": [
        "wireless earbuds"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cornflower_vision/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": ["wireless earbuds"] }

# Run the Actor and wait for it to finish
run = client.actor("cornflower_vision/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": [
    "wireless earbuds"
  ]
}' |
apify call cornflower_vision/google-shopping-scraper --silent --output-dataset

```

## MCP server setup

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