# Google Shopping Scraper & API: Prices, Sellers, Price Tracker (`varnmill/google-shopping-scraper`) Actor

Scrape Google Shopping by keyword or URL in 31 countries: price, old price and discount, seller, rating, reviews, delivery, product IDs and links, with optional product details and a scheduled price watcher for product links. No login, no browser; $1 per 1,000 products.

- **URL**: https://apify.com/varnmill/google-shopping-scraper.md
- **Developed by:** [Jay Novello](https://apify.com/varnmill) (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 $0.70 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 & API: Prices, Sellers, Price Tracker

Google Shopping results in **31 countries** as clean rows: price and currency, old price and discount when on sale, seller, rating and review count, delivery and returns text, image, Google's product page link and product, offer and merchant IDs. Add product details (specs, description, every seller's price and shop link) or price-check product links on a schedule and get only what changed. No login, no browser, no API key.

**Try it:** Click Start with the default input (`standing desk`, United States, 20 products): **20 products in 15 seconds for about $0.02** (run on October 21, 2026).

| # | Product | Price | Was | Seller | Rating (reviews) | Delivery |
|---|---|---|---|---|---|---|
| 1 | FlexiSpot E2 Standing Desk Best Value for Home Office | $109.99 | $290 (62% off) | FlexiSpot.com | 4.9 (1,400) | Free delivery by Fri |
| 3 | Vernal Core3 Standing Desk | $409.99 | $460 (11% off) | vernalspace.com | 4.8 (630) | Free delivery |
| 5 | FlexiSpot E7 Standing Desk Premium Dual Motor Electric | $299.99 | Usually $410 (27% off) | FlexiSpot.com | 4.7 (4,000) | Free delivery by Fri |
| 13 | Gilman Home Office Height Adjustable Standing Desk | $132.99 | $153 (13% off) | Wayfair | 4.4 (894) | Free delivery by Mon |
| 17 | FEZiBO Standing Desk Electric Height Adjustable | $89.99 | $260 (65% off) | fezibo.com | | Free delivery |

**Pricing:** $1 per 1,000 products, $6 per 1,000 product pages (the details add-on, or one price check of a product link), $0.00005 per run start. Platform usage and the Google SERP proxy are included. Failed runs, filtered products and error rows are not charged.

### Real example: 10 keywords, 929 products

Run on Apify on **October 17, 2026 (19:46 UTC)**: 10 US keywords, up to 100 products each. It returned 929 products in 108 seconds, which would cost a user $0.93. The first six rows for `air fryer`:

| # | Product | Price | Was | Seller | Rating (reviews) | Delivery |
|---|---|---|---|---|---|---|
| 1 | Our Place Wonder Oven Pro - Stainless Steel | $320+ (from, several sellers) | | | 3.4 (732) | |
| 2 | Lynzavix 32 Qt. Black Air Fryer Toaster Oven Combo with Roti... | $460.77 | | Home Depot | 5.0 (1) | Free delivery |
| 3 | Breville The Smart Oven Air Fryer - Compact | $240+ (from) | | | 5.0 (274) | |
| 4 | Gourmia 14qt All-in-One Digital Air Fryer Oven | $99.99 | | Target | 3.1 (1,000) | Free delivery |
| 5 | bella PRO - 12.6-qt. Air Fryer Oven | $110+ (from) | | | 3.7 (83) | |
| 6 | Cuisinart Air Fryer Toaster Oven 7-in-1 | $129.99 | $230 (43% off) | Target | 2.4 (426) | Same-day delivery $10 |

Row 6 in full:

```json
{
  "type": "product",
  "position": 6,
  "query": "air fryer",
  "title": "Cuisinart Air Fryer Toaster Oven 7-in-1",
  "price": 129.99,
  "currency": "USD",
  "priceIsFrom": false,
  "pricePeriod": null,
  "oldPrice": 230,
  "discountPercent": 43,
  "merchant": "Target",
  "moreSellers": true,
  "rating": 2.4,
  "reviewCount": 426,
  "delivery": "Same-day delivery $10",
  "freeDelivery": false,
  "returns": "90-day returns",
  "badge": "43% OFF",
  "shelf": "Countertop Air Fryers",
  "thumbnail": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9GcQv75PkmMyKBmPtgoNfxmzrpS_yllV7OODvjSpF14B_5UGM66-FC6fhlVVITBuUnpGN4Yg4oeWZL3wSlycoquMfazfbw-jZVQ",
  "productLink": "https://www.google.com/search?ibp=oshop&q=Cuisinart+Air+Fryer+Toaster+Oven+7-in-1&prds=catalogid:2859839068288404989,headlineOfferDocid:4564352975176009582,imageDocid:10585568315564802316,rds:PC_14498152716962017142%7CPROD_PC_14498152716962017142,gpcid:14498152716962017142,mid:576462512313334871,pvt:hg,pvo:3&hl=en&gl=us&udm=28",
  "productId": "2053481929927986275",
  "offerId": "4564352975176009582",
  "catalogId": "2859839068288404989",
  "groupId": "14498152716962017142",
  "imageId": "10585568315564802316",
  "merchantId": "576462512313334871",
  "priceText": "$129.99",
  "oldPriceText": "$230",
  "page": 1,
  "country": "us",
  "language": "en",
  "scrapedAt": "2026-10-17T19:47:12+00:00"
}
```

With **product details** on (same day, `iphone 16`, 5 products, 24 seconds), each row also gets a `details` object. Shortened here to 4 of 23 specs, 2 of 7 review themes and 2 of 3 sellers:

```json
"details": {
  "title": "Apple iPhone 16",
  "description": "The first iPhone built for Apple Intelligence, the iPhone 16, with 6.1 (diagonal) all-screen OLED display, helps you write, express yourself, and get things don...",
  "rating": 4.5,
  "reviewCount": 13567,
  "ratingBreakdown": {"1": 1016, "2": 231, "3": 405, "4": 1327, "5": 10588},
  "specs": {"Brand": "Apple", "Operating System": "iOS", "Carrier": "T-Mobile, Unlocked", "Smartphone": "Yes"},
  "variantOptions": {"Color": ["Black", "Pink", "Teal", "Ultramarine", "White"], "Storage": ["128GB", "256GB", "512GB"]},
  "selectedVariant": {"Color": "Black", "Storage": "128GB"},
  "insights": [{"theme": "Camera (Video, Lens, Zoom)", "summary": null}, {"theme": "Design (Back, Color, Size)", "summary": null}],
  "offers": [
    {"merchant": "Walmart - BREED", "price": 548.99, "currency": "USD", "delivery": "Delivery $29.99",
     "link": "https://www.walmart.com/ip/Unlocked-Apple-iPhone-16-A3081-Cell-Phone-128GB-3561-mAh-128GB-RAM-Black/20464464864?wmlspartner=wlpa&selectedSellerId=442&veh=seo_fpl&cn=google"},
    {"merchant": "Apple", "price": 829, "currency": "USD", "delivery": "Free delivery",
     "link": "https://www.apple.com/us/xc/product/MYAP3LL/A?cppart=UNLOCKED&cid=aos-us-seo-pla-iphone"}
  ],
  "images": ["https://encrypted-tbn3.gstatic.com/shopping?q=tbn:ANd9GcS46dur9Te7_YA5-tLcKOjNSMJxGe9DsqlwR2o8FXDlNjdNINpO12Y9lH1cJKS2M3xT_sNyyWC4Ln9xfE-sB-2cKRUVTEG_eQ"]
}
```

The seller `link` goes straight to the shop, not through a Google redirect.

### What you can do with it

- **Price monitoring and competitor tracking**: follow specific products through their Google product links and get every price drop, price rise and seller change since the last run (`productUrls` + `onlyChanged`).
- **Market and assortment research**: see which brands, sellers and price points Google shows first for a keyword, in any of 31 countries, in the local currency.
- **Product catalog enrichment**: add descriptions, specs and rating breakdowns from Google's product pages (`includeDetails`).
- **Feeds for AI agents and dashboards**: one flat row per product with stable field names, ready for Sheets, BigQuery, n8n, Make or an LLM.

### Input

| Field | What it does |
|---|---|
| `queries` | Keywords, one per line, exactly as you would type them into Google Shopping. You can paste Google Shopping URLs here too. |
| `startUrls` | Google Shopping URLs from your browser. Use them to keep any filter you clicked on google.com (price range, store, brand, on sale, nearby). |
| `productUrls` | Google product links (the `productLink` of a search row) to price-check: every seller, price and shop link, plus the lowest price. |
| `country` | One of 31 countries (US, UK, Canada, Australia, Germany, France, Japan, Brazil, ...). Prices, sellers and currency follow it. |
| `language` | Optional interface language (`en`, `de`, `fr`, `ja`, ...). |
| `maxProductsPerQuery` | Unique products per search (default 40). Google shows about 80 to 100 per search. |
| `maxItems` | Cap for the whole run (default 1,000). |
| `minPrice`, `maxPrice`, `onSaleOnly` | Keep only products in a price range or on sale. Dropped products are not charged. |
| `includeDetails` | Paid add-on: description, specs, rating breakdown and review themes for each product. |
| `onlyChanged`, `watcherName` | Price watcher for scheduled price checks of `productUrls` (see below). |

Example input:

```json
{
  "queries": ["standing desk", "office chair"],
  "country": "us",
  "maxProductsPerQuery": 50,
  "onSaleOnly": false
}
```

### Output fields

`position`, `query`, `title`, `price`, `currency`, `priceIsFrom` (a "from" price such as "$320+" across several sellers), `pricePeriod` ("month" for instalment prices), `oldPrice`, `discountPercent`, `merchant`, `moreSellers`, `rating`, `reviewCount`, `delivery`, `freeDelivery`, `returns`, `badge`, `shelf`, `thumbnail`, `productLink`, `productId`, `offerId`, `catalogId`, `groupId`, `imageId`, `merchantId`, `priceText`, `oldPriceText`, `page`, `country`, `language`, `scrapedAt`. With `includeDetails`: `details` (`description`, `specs`, `ratingBreakdown`, `insights`, `variantOptions`, `selectedVariant`, `images`, and `offers`: the sellers on the product page with price, delivery and a direct shop link). Price checks (`productUrls`) return `type: "product-page"` rows with `title`, `lowestPrice`, `currency`, `lowestPriceMerchant`, `lowestPriceLink`, `sellerCount`, `offers`, `rating`, `reviewCount`, `details` and `productLink`; with the watcher also `changeType`, `previousLowestPrice`, `priceChange`, `previousLowestPriceMerchant`.

A search that finds nothing returns one row with `type: "error"` and the reason. Error rows are not charged.

### Price checks and the price watcher

Search results are not a good basis for tracking: Google reshuffles Shopping results on every load (two loads of `standing desk` a few minutes apart shared fewer than 1 product in 10) and hands out new product and offer IDs each time. A **product page** is stable, so tracking works on product links instead:

1. Run a search and copy the `productLink` of the products you want to follow.
2. Put those links in `productUrls`, turn on `onlyChanged`, name the watcher and schedule the run.

Each link returns one `product-page` row with every seller Google shows, their prices and direct shop links, the lowest one-off price and its seller. The watcher remembers the lowest price, its seller and every seller's price, and on later runs returns only links where something changed: `changeType` is `new`, `price-down`, `price-up`, `seller-changed` (the previous cheapest seller is still listed but now above the lowest price) or `offers-changed` (another seller's price moved, or sellers came or went), with `previousLowestPrice` and `priceChange`.

Real run on **October 17, 2026 (19:55 UTC)**: six product links taken from the search example above, first watcher run (`watcherName: readme-prices`), 44 seconds:

| Product | Lowest price | Cheapest seller | Sellers shown | Rating (reviews) |
|---|---|---|---|---|
| Philips 3300 Fully Automatic Espresso Machine | $549.00 | homecoffeesolutions.com | 5 (others $599.95 to $599.99) | 4.2 (1,311) |
| Roborock Q10 X5+ Robot Vacuum and Mop | $319.99 | Roborock | 3 | 4.3 (495) |
| Vitamix Nano Personal Blender | $199.95 | Vitamix | 5 (all $199.95) | 3.8 (37) |
| Jade Yoga Voyager Mat | $49.95 | Mukha Yoga | 5 (all $49.95) | 4.5 (204) |
| Status Pro X | $249.00 | Status Audio | 1 | |
| Moonlight Desk Lamp | $224.96 | Evolution Beauty Technologies | 1 | |

The second run a few minutes later read all six pages again and returned nothing: "6 of 6 product link(s) checked, 6 unchanged and left out". Each link is a Google page read, so it is charged on every run, changed or not; the watcher only keeps unchanged products out of your results.

Real change, **October 18, 2026**: the same watcher read the links at 07:39 UTC and again at 19:18 UTC (6 of 6 checked, 28 seconds). Four products were unchanged and left out. The Roborock vacuum came back because its sellers changed while the lowest price stayed the same:

| Run | Lowest price | Sellers shown |
|---|---|---|
| 07:39 UTC | $319.99 | Roborock $319.99, Home Outlet Direct $319.99, Zulily.com $320.99 |
| 19:18 UTC | $319.99 | Wellbots $319.99, Linens N Things $319.99, The Robot Direct $319.99, Roborock $319.99 |

```json
{"type": "product-page", "title": "Roborock Q10 X5+ Robot Vacuum and Mop with Auto-Empty Dock",
 "changeType": "offers-changed", "lowestPrice": 319.99, "previousLowestPrice": 319.99, "priceChange": 0,
 "lowestPriceMerchant": "Wellbots", "previousLowestPriceMerchant": "Roborock", "sellerCount": 4, "rating": 4.3, "reviewCount": 495}
```

A third read two minutes later showed the 07:39 sellers again, so Google rotates between seller lists for the same product at the same price. That is why the watcher reports `seller-changed` only when the previous cheapest seller is still listed but above the lowest price; tied sellers swapping places is no change, and a different seller list is `offers-changed`. For a pure price alert, act on `price-down` and `price-up` only. (Build 0.1.7 labelled this row `seller-changed`; 0.1.9 labels it `offers-changed`.)

### Pricing

Pay per event: you pay only for what you get.

| Event | Price |
|---|---|
| Product (one row) | $0.001 ($1 per 1,000) |
| Product page: details add-on (`includeDetails`) or one price check of a product link (`productUrls`) | $0.006 per product ($6 per 1,000) |
| Actor start | $0.00005 |

Products dropped by your price or sale filters, product pages Google does not have, and error rows cost nothing. A price check is charged each time the page is read, also when the watcher leaves an unchanged product out. Apify's free plan includes $5 of usage every month, which covers about 5,000 products.

### Accuracy and limits

- **Depth**: Google Shopping returns about 80 to 100 unique products per search (two pages of 40 plus themed shelves on page one). For more, split the search (brands, models, price ranges) or paste filtered Google Shopping URLs.
- **Price filters** (`minPrice`, `maxPrice`, `onSaleOnly`) are applied to the products Google returns. Google's own price filter lives in the URL: set it on google.com and paste the URL.
- **Results rotate**: Google reshuffles Shopping results and reissues product and offer IDs on every load, so `position` and the IDs belong to this run. Track products through `productUrls`, not through repeated searches.
- **Seller lists rotate**: for the same product and the same lowest price, Google can show a different set of 3 to 5 sellers on loads minutes apart. The lowest price is the stable signal; `offers-changed` rows can come from this rotation.
- **Review counts** are as rounded as Google shows them (3.2K becomes 3200).
- **IDs**: `catalogId`, `groupId` and `merchantId` are empty in some countries (for example Germany and the UK), where Google ties cards to the offer instead. `productId` and `offerId` are always filled.
- **Country**: every page is checked against the country you asked for (page language region and currency). Pages Google serves from another country are retried, never returned.
- **Product pages exist for most US catalog products**, but many single-seller listings outside the US (in a German test 4 of 6) have none. Those rows get `detailsError` and are not charged.
- **Product details**: `details.offers` holds the 3 to 5 sellers Google shows on the product page. The "More stores" list needs an extra click on google.com and is not included. Instalment offers ("$16.66 for 36 mo") show the monthly amount; check `priceText`.
- **Ratings** are the ones Google shows on the card at that moment. Google sometimes shows a different average for the same product on another page load; `details.rating` and `details.reviewCount` (exact count) come from the product page.
- **Gibberish or very rare keywords**: Google fills the page with unrelated popular products instead of saying "no results". Check that titles match your keyword.

### FAQ

**Is there an official Google Shopping API?** Not for search results. The Content API and Merchant API are for merchants managing their own products. This actor gives you the public Shopping results as an API: call it from Python, JavaScript, n8n, Make, Zapier or any HTTP client through the Apify API.

**Do I need proxies or a Google account?** No. The actor uses Apify's Google SERP proxy, which is included in the price.

**How do I track prices of the same products every day?** Run a search once, copy the `productLink` values you care about into `productUrls`, turn on `onlyChanged`, give the watcher a name, and schedule the actor (Apify Console > Schedules). The first run returns every product as `new`; later runs return only changes.

**Can I search by GTIN, EAN or model number?** Yes, type it as the keyword. Google matches it like any other text, so check the title of the first result.

**Why does the watcher not work on keyword searches?** Because Google shows a different mix of products, with new IDs, on every load of the same search. Product links stay stable, so the watcher uses them.

**Does it work in other languages?** Yes. Titles, delivery and returns text come in the language of the country (or the `language` you set); numbers, currency codes and IDs are normalised.

Watcher scheduling: use a separate `watcherName` for each independent workflow and keep its filters/location consistent. Runs using the same name wait up to 50 seconds for the previous run; if it is still busy, retry after it finishes. Local and cloud baselines are separate. A failed or interrupted delivery can appear again on retry, so deduplicate downstream by product ID and observation time. Existing names keep their baselines, but a baseline previously shared by colliding names cannot be disentangled automatically.

### Changelog

- **0.1.11 (2026-10-21)**: First public release. README restructured: default-input timing, a table from the October 21 default run and a pricing line at the top. No code changes.
- **0.1.10 (2026-10-19)**: Watcher runs with the same name now wait for each other before loading and saving their baseline. Losing the lock stops the run without saving stale state. Price checks and details now respect the spending cap; an undelivered change remains available on retry. Cancelled runs keep only confirmed output in watcher state.
- **0.1.9** (October 18, 2026): the watcher reports `seller-changed` only when the previous cheapest seller is still listed above the lowest price, not when tied sellers swap places or Google shows a different seller list (`offers-changed`); real change example added.
- **0.1** (October 2026): first release. Keyword and URL searches in 31 countries, pagination, price and sale filters, product details add-on with sellers and direct shop links, price checks of product links with a watcher.

# Actor input Schema

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

What you would type into Google Shopping, one per line (for example 'standing desk' or 'airpods pro 2'). Each keyword is one search. You can also paste Google Shopping URLs here.

## `startUrls` (type: `array`):

Optional. Paste Google Shopping result URLs from your browser to keep any filter you clicked there (price range, store, brand, 'on sale', 'nearby'). The URL's own country (gl) and language (hl) are used when present.

## `productUrls` (type: `array`):

Optional. Google product links (the 'productLink' field of a search row). Each link is opened and returns the product with every seller Google shows, their prices and direct shop links, and the lowest price. Use this with the price watcher to track the same products every day. Charged as 'product-details' per link.

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

Google Shopping country. Prices, sellers and currency are the ones shoppers in that country see.

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

Optional interface language code (hl), such as en, de, fr or ja. Empty uses the country's main language.

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

Stop each search after this many unique products. Google Shopping shows about 80 to 100 products per search (two pages of 40 plus themed shelves); asking for more returns what Google has.

## `maxItems` (type: `integer`):

Stop the whole run after this many products across all searches.

## `minPrice` (type: `integer`):

Optional. Drop products cheaper than this (in the country's currency). Filtering happens after Google's results come back, so it narrows the ~100 products a search returns; for a deeper price-filtered list, set the price filter on google.com and paste the URL into 'Google Shopping URLs'. Filtered products are not charged.

## `maxPrice` (type: `integer`):

Optional. Drop products more expensive than this (in the country's currency). Filtered products are not charged.

## `onSaleOnly` (type: `boolean`):

Keep only products that show an old (struck-through) price. Filtered products are not charged.

## `includeDetails` (type: `boolean`):

Also open each product's Google product page and add its description, specifications, rating breakdown and review themes under 'details'. One extra Google request per product, charged as the 'product-details' event.

## `onlyChanged` (type: `boolean`):

For scheduled runs with 'Product links to price-check'. Remembers each product's lowest price, its seller and every seller's price under the watcher name, and returns only products that are new or changed since the last run (changeType, previousLowestPrice, priceChange). Each link is still read and charged on every run; unchanged ones are just left out of the results. Keyword searches always return all products, because Google reshuffles them on every load.

## `watcherName` (type: `string`):

Name of the price watcher's memory (stored in your key-value store 'google-shopping-scraper-state'). Use a different name for each schedule you run.

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

How many Google pages to fetch at the same time.

## Actor input object example

```json
{
  "queries": [
    "standing desk"
  ],
  "country": "us",
  "maxProductsPerQuery": 20,
  "maxItems": 1000,
  "onSaleOnly": false,
  "includeDetails": false,
  "onlyChanged": false,
  "watcherName": "default",
  "maxConcurrency": 8
}
```

# Actor output Schema

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

No description

## `productsCsv` (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": [
        "standing desk"
    ],
    "maxProductsPerQuery": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("varnmill/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": ["standing desk"],
    "maxProductsPerQuery": 20,
}

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

```

## MCP server setup

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