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

Scrape Google Shopping products and sponsored PLA ads by keyword — titles, prices, merchants, ratings, delivery, and direct retailer URLs. Multi-country, multi-query. Organic listings + ads in one run. Flat JSON/CSV for price monitoring, PPC research, and ecommerce intelligence.

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

## Pricing

from $2.50 / 1,000 shopping 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/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 & Sponsored Ads

Extract live Google Shopping results by keyword: organic product cards **and** sponsored PLA ads, with prices, merchants, ratings, delivery signals, and direct retailer URLs when Google exposes them.

Built for price monitoring, competitive research, and ecommerce intelligence — multi-query, multi-country, JSON or CSV out.

***

### Why Use This Scraper?

- **Organic + sponsored in one run** — most Shopping scrapers skip PLAs; this one returns both
- **Direct retailer URLs on sponsored ads** — when Google shows them (JBL, Walmart, Target, Best Buy, …)
- **Structured money fields** — `price` + numeric `priceValue` + currency for easy pipelines
- **Market + language targeting** — any `gl` / `hl` Google Shopping market
- **Flat dataset** — one product row per result, ready for sheets, warehouses, or agents

***

### Overview

This Actor scrapes Google Shopping search results (`udm=28`) for one or more buyer keywords. Each dataset item is a single product card — either an organic Shopping listing or a sponsored Product Listing Ad (PLA).

It does **not** scrape Google Ads Transparency Center, Merchant Center, CPC/spend, or organic web Search results.

***

### Supported Inputs

| Input | Supported |
|---|---|
| Keyword / product search (`queries`) | ✅ |
| Country market (`countryCode`) | ✅ |
| Language (`languageCode`) | ✅ |
| Price range + sort | ✅ |
| Sponsored / organic toggles | ✅ |
| Google Shopping product detail URLs | ❌ (search mode only) |
| EAN / GTIN / SKU lookup | ❌ (not in this version) |

Example keywords: `wireless headphones`, `office chair`, `nike running shoes`.

***

### Use Cases

| Audience | What you get |
|---|---|
| Ecommerce sellers | Competitor prices, merchants, discount signals |
| PPC / PLA teams | Sponsored ad creative, ranks, retailer destinations |
| Market researchers | Category assortments across countries |
| Price-monitoring tools | Repeatable keyword → product rows |
| AI agents / MCP | Flat JSON for RAG, alerts, and enrichment |

***

### How It Works

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

1. Submit one or more product keywords and pick a market / language.
2. The Actor builds Google Shopping URLs (`udm=28`) with optional sort and price filters.
3. Pages are fetched with anti-block defenses (residential attempt → unlocker fallback).
4. Organic cards and sponsored PLA units are parsed into flat product rows.
5. Results land in the default dataset — charge is per saved product.

***

### Input Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `queries` | string\[] | — | **Required.** Product / category keywords |
| `maxProductsPerQuery` | integer | `40` | Cap per keyword |
| `maxTotalProducts` | integer | — | Optional run-wide cap |
| `countryCode` | string | `US` | ISO market (US, GB, DE, …) |
| `languageCode` | string | `en` | UI language |
| `includeSponsored` | boolean | `true` | Collect PLA ads |
| `includeOrganic` | boolean | `true` | Collect organic cards |
| `sortBy` | enum | `relevance` | `relevance` / `price_low` / `price_high` / `rating` |
| `minPrice` / `maxPrice` | number | — | Price filters |
| `maxConcurrency` | integer | `3` | Parallel keywords |
| `maxRequestRetries` | integer | `3` | Retries per keyword |
| `saveHtml` | boolean | `false` | Debug: store raw HTML |
| `proxy` | object | — | Optional Apify/custom proxy |

#### Example — US headphones, 10 products

```json
{
  "queries": ["wireless headphones"],
  "maxProductsPerQuery": 10,
  "countryCode": "US",
  "languageCode": "en",
  "includeSponsored": true,
  "includeOrganic": true
}
```

#### Example — price band + sort

```json
{
  "queries": ["office chair"],
  "countryCode": "US",
  "languageCode": "en",
  "sortBy": "price_low",
  "minPrice": 50,
  "maxPrice": 250,
  "maxProductsPerQuery": 30
}
```

***

### Output Overview

Each row is one Shopping product. Sponsored rows carry `retailerUrl` (direct merchant link) and `googleAdUrl`. Organic rows carry `rating`, `reviewCount` and `delivery` when shown, plus **five of Google's own identifiers** — `productId` (`data-cid`), `googleGroupId`, `googleItemId`, `googleOfferId`, `googleProductId` — which are the durable handles to join a listing across runs.

> **Two fields are honestly limited on organic rows, and it is Google's page, not the parser.** The modern Shopping results page (`udm=28`) contains **no product anchor at all** — navigation is JavaScript-driven — so `productUrl` is `null` for organic rows. Constructed `google.com/shopping/product/<id>` forms were tested against every id the page exposes and all returned *Not available*, so none is emitted rather than shipping a link that 404s. `imageUrl` is populated when Google publishes the thumbnail as a URL (`google.ldi` → `encrypted-tbn…`); on many organic rows it inlines the thumbnail as a multi-kilobyte base64 JPEG instead, and that is left out rather than carried under a field named "URL". Sponsored rows are unaffected — they have real links.

***

### Output Samples

#### Sponsored PLA (with retailer URL)

```json
{
  "type": "sponsored",
  "position": 1,
  "searchQuery": "wireless headphones",
  "countryCode": "US",
  "languageCode": "en",
  "title": "JBL Tune 510BT Wireless On-Ear Headphones - White",
  "price": "$29.95",
  "priceValue": 29.95,
  "currency": "$",
  "originalPrice": "$50",
  "originalPriceValue": 50,
  "merchant": "JBL",
  "retailerUrl": "https://www.jbl.com/JBLT510BTWHTAM.html",
  "googleAdUrl": "https://www.google.com/aclk?…",
  "scrapedAt": "2026-07-22T22:41:00.000Z"
}
```

#### Organic Shopping card

```json
{
  "type": "organic",
  "position": 7,
  "searchQuery": "wireless headphones",
  "countryCode": "US",
  "languageCode": "en",
  "productId": "5636327565946258541",
  "title": "Sony WH-1000XM6 Wireless Noise Canceling Headphones",
  "price": "$458.00",
  "priceValue": 458,
  "currency": "$",
  "merchant": "Best Buy",
  "rating": 4.7,
  "reviewCount": "4.9K",
  "reviewCountValue": 4900,
  "delivery": "Free delivery by Fri",
  "scrapedAt": "2026-07-22T22:41:00.000Z"
}
```

***

### Key Output Fields

| Group | Fields |
|---|---|
| Context | `type`, `position`, `searchQuery`, `countryCode`, `languageCode`, `scrapedAt` |
| Product | `productId`, `googleGroupId`, `googleItemId`, `googleOfferId`, `googleProductId`, `title` |
| Pricing | `price`, `priceValue`, `currency`, `originalPrice`, `originalPriceValue` |
| Merchant | `merchant`, `rating`, `reviewCount`, `reviewCountValue`, `delivery` |
| Links | `retailerUrl`, `googleAdUrl` |

Optional values are `null` when Google does not display them.

***

### FAQ

**Does this scrape organic web Search or only Shopping?**\
Only Google Shopping (`udm=28`) — product cards and PLAs.

**Why is `retailerUrl` null on some organic rows?**\
Organic cards often open Google’s product viewer instead of a direct merchant link. Sponsored PLAs usually expose the retailer destination.

**Can I pass EAN / GTIN codes?**\
Not in this version — keyword search only.

**Do I need my own Google API key?**\
No. No Google login or Ads account is required.

***

### Support

- Open an issue on the Actor’s **Issues** tab in Apify Console
- Website: [apify.com/memo23](https://apify.com/memo23)
- Custom scrapers / exports: contact via Apify

***

### Additional Services

Need EAN→offers lookup, scheduled price monitoring, or a custom schema? Reach out for a tailored build or enrichment pipeline.

***

### Explore More Scrapers

Browse the full portfolio: [apify.com/memo23](https://apify.com/memo23)

***

### 🤖 For AI Agents & LLM Apps

**Purpose:** Scrape Google Shopping product listings + sponsored PLA ads by keyword.

**Minimal input:**

```json
{
  "queries": ["wireless headphones"],
  "maxProductsPerQuery": 10,
  "countryCode": "US",
  "languageCode": "en"
}
```

**Output fields (flat):** `type`, `position`, `searchQuery`, `countryCode`, `languageCode`, `productId`, `googleGroupId`, `googleItemId`, `googleOfferId`, `googleProductId`, `title`, `price`, `priceValue`, `currency`, `originalPrice`, `originalPriceValue`, `merchant`, `rating`, `reviewCount`, `reviewCountValue`, `delivery`, `productUrl`, `retailerUrl`, `googleAdUrl`, `imageUrl`, `scrapedAt`

**Billing:** Pay-per-event — charged per dataset item (`apify-default-dataset-item`) plus actor start. One row = one product card.

**Agent notes:** Prefer short keyword lists; set `maxProductsPerQuery` explicitly; treat null `retailerUrl` as expected on many organic rows; `type` is `organic` or `sponsored`.

***

### ⚠️ Disclaimer

This Actor is **not affiliated with, endorsed by, or sponsored by Google LLC**. Google Shopping™ and Google™ are trademarks of Google LLC. All trademarks remain the property of their respective owners.

This tool collects **publicly available** Shopping listing data for research and monitoring. You are responsible for complying with Google’s Terms of Service, applicable laws (including GDPR/CCPA where relevant), and your own use-case policies. Use responsibly and at your own risk.

***

### SEO Keywords

google shopping scraper, google shopping api, scrape google shopping, google shopping products, google shopping prices, PLA scraper, product listing ads scraper, google shopping merchant, price monitoring scraper, competitor price scraper, ecommerce intelligence, shopping results scraper, google udm=28 scraper, sponsored shopping ads, product price comparison scraper, google shopping dataset, apify google shopping, shopping keyword scraper, retailer url extractor, multi country shopping scrape

# Actor input Schema

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

Product or category searches to run on Google Shopping. Each keyword is scraped as its own query. Examples: wireless headphones, office chair, nike running shoes.

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

Maximum number of product rows (organic + sponsored combined) to save for each keyword.

## `maxTotalProducts` (type: `integer`):

Optional run-wide cap across all keywords. Leave empty to use the per-keyword limit only.

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

Google Shopping market as an ISO 3166-1 alpha-2 country code. Affects currency, merchants, and available offers.

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

Google page language as an ISO 639-1 code (for example: en, de, fr, es, ja).

## `includeSponsored` (type: `boolean`):

When enabled, also collect the paid Product Listing Ads shown above organic Shopping results. Sponsored rows include direct retailer URLs when Google exposes them.

## `includeOrganic` (type: `boolean`):

When enabled, collect organic Google Shopping product cards (title, price, merchant, rating, delivery).

## `sortBy` (type: `string`):

How Google should order Shopping results.

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

Only include products at or above this price in the local market currency. Leave empty for no minimum.

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

Only include products at or below this price in the local market currency. Leave empty for no maximum.

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

How many keywords to fetch in parallel. Keep low (2–4) to reduce Google soft-blocks.

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

Retry attempts for a keyword when Google soft-blocks or returns an empty page.

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

Store the raw Shopping HTML for each keyword in the default key-value store (debugging only — increases storage use).

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

Optional Apify or custom proxy. The actor already escalates to a built-in unlocker when residential proxies are soft-blocked by Google; leave empty unless you need a specific country pool.

## Actor input object example

```json
{
  "queries": [
    "wireless headphones",
    "office chair"
  ],
  "maxProductsPerQuery": 40,
  "countryCode": "US",
  "languageCode": "en",
  "includeSponsored": true,
  "includeOrganic": true,
  "sortBy": "relevance",
  "maxConcurrency": 3,
  "maxRequestRetries": 3,
  "saveHtml": 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": [
        "wireless headphones",
        "office chair"
    ],
    "maxProductsPerQuery": 40,
    "countryCode": "US",
    "languageCode": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/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 headphones",
        "office chair",
    ],
    "maxProductsPerQuery": 40,
    "countryCode": "US",
    "languageCode": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/google-shopping-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": [
    "wireless headphones",
    "office chair"
  ],
  "maxProductsPerQuery": 40,
  "countryCode": "US",
  "languageCode": "en"
}' |
apify call memo23/google-shopping-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/qW4PofSxqL5qhTY3G/builds/Qbg9Xiz41Hq3qrQPD/openapi.json
