Google Shopping Scraper β Product Prices & Merchants
Pricing
from $2.72 / 1,000 product scrapeds
Google Shopping Scraper β Product Prices & Merchants
Compare product prices across merchants on Google Shopping: titles, prices, numeric price, merchants, ratings, delivery info, product URLs, country/language targeting, and exports.
Pricing
from $2.72 / 1,000 product scrapeds
Rating
0.0
(0)
Developer
Automation Lab
Maintained by CommunityActor stats
3
Bookmarked
545
Total users
76
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
π What does Google Shopping Scraper do?
Google Shopping Scraper extracts structured product listing data from Google Shopping search results β no API key required, no login needed. Enter any search query and get back product titles, prices, merchants, ratings, review counts, delivery info, images, and direct product URLs in seconds.
The scraper uses a GOOGLE_SERP proxy primary / Playwright browser fallback architecture for reliable, fast extraction. The HTTP+SERP path is the default β bypassing CAPTCHA natively and returning results in seconds. The browser fallback kicks in automatically if needed. It supports pagination, country-verified results, multiple languages, price range, on-sale and free-shipping filters, and four sort orders β so you get exactly the slice of data you need. The easiest way to try it is to open the actor on Apify Store, click Try for free, and run a search query with default settings.
Price monitoring workflow
Use Google Shopping Scraper as the cross-merchant comparison hub for price-monitoring workflows. Schedule recurring product or category queries, capture current price, priceNumeric, merchant, delivery text, product URL, position, and scrapedAt, then export each dataset to CSV/JSON, Google Sheets, webhooks, or BI dashboards.
Example: monitor 20β100 SKU-like product queries daily, compare priceNumeric by merchant against prior exported datasets or retailer-specific scrapers, and trigger downstream alerts for price drops, new low-price merchants, or MAP-policy violations. For retailer-specific depth, pair it with Amazon Scraper, eBay Scraper, Walmart Scraper, and Target Scraper.
Automated market research workflow on Apify
Use this actor as one source in a broader competitor-intelligence and market-research workflow:
- Monitor ads and messaging with Google Ads Scraper, Google Ads Transparency Center Scraper, and LinkedIn Ad Library Scraper.
- Track reviews and sentiment with G2 Reviews & Products Scraper, Trustpilot Reviews Scraper, and Amazon Reviews Scraper.
- Watch demand and category trends with Google Trends Scraper, Google News Scraper, and TikTok Trends Scraper.
- Benchmark ecommerce pricing and products with Amazon Scraper, Google Shopping Scraper, and Shopify Store Scraper.
- Map companies to people with LinkedIn Company Employees Scraper when you need account or team context.
Schedule runs, export datasets to CSV/Excel/JSON, or connect the outputs to Google Sheets, webhooks, Make, Zapier, BI tools, and LLM reporting workflows.
π€ Who is it for?
E-commerce businesses & brands
- Monitor competitor pricing across hundreds of merchants for any product category
- Track how your own products appear (position, price, merchant) in Google Shopping listings
- Detect unauthorized sellers or pricing violations on your products
Price comparison platforms & marketplaces
- Aggregate product data from multiple merchants into a unified catalog
- Build real-time price feeds without relying on merchant APIs
- Identify the lowest-price sources for any product at scale
Dropshippers & wholesale buyers
- Discover profitable price gaps between merchants for arbitrage opportunities
- Find trending products with high ratings and review counts in any niche
- Identify the merchants consistently winning top positions for target queries
Market researchers & data analysts
- Map the competitive landscape for any product category across countries
- Analyze how prices shift seasonally, during promotions, or after supply chain events
- Build benchmarks for product pricing decisions with real market data
SEO & marketing agencies
- Track which merchants appear for client-relevant product queries
- Audit paid shopping placements and organic product visibility
- Monitor competitors' Google Shopping presence over time
β Why use this scraper?
- No API key or account required β Google Shopping is fully public; just run and get data
- GOOGLE_SERP proxy primary β purpose-built for Google, bypasses CAPTCHA natively; browser fallback for edge cases
- Multi-country & multi-language β localize results to 40+ countries and dozens of languages
- Results pinned to your country β pages Google answers for another country (it happens, even with a country code set) are retried, and a row whose price shows another currency is never saved or charged
- Filters that Google applies β price range, on sale, free shipping and four sort orders are sent to Google, so a narrow range still returns a full result set. Price range and on sale are also checked on every row, and a sorted search is delivered in the requested order. Free shipping relies on Google's filter alone, so an occasional row may show paid delivery
- One row per offer β pages overlap on Google; repeated offers are dropped and never charged, while the same product from another merchant stays as its own row
- Discounts and IDs β original price, discount percent, catalog ID and offer ID on every row where Google shows them
- Structured, flat output β every field is a primitive (number, string), ready for spreadsheets or databases
- Numeric price field β
priceNumericenables sorting, filtering, and arithmetic without string parsing - Scheduled runs β Apify Scheduler lets you run recurring price-monitoring exports daily or weekly for downstream comparisons and alerts
- Export to any format β JSON, CSV, Excel, XML, and Parquet out of the box
- Full Apify ecosystem β API access, webhooks, Google Sheets integration, Zapier/Make workflows
- Automatic proxy management β GOOGLE_SERP as primary, residential proxy with browser as fallback; no configuration needed
Fast-start recipe
- Paste the smallest input that matches your job: one keyword, one URL, one listing ID, one username, or a short domain list.
- Keep the first run small (result limit of 10-50) to validate fields and cost.
- Export the dataset as CSV/Excel for spreadsheet review, or use the Apify API/webhooks for scheduled monitoring.
- Scale the same input pattern once the sample output matches your workflow.
First run recommendation
Start with 1-3 product queries, maxResults: 20, country: us, language: en, and optional minPrice / maxPrice after the first sample.
Data handling and diagnostic privacy
Failed operations send sanitized diagnostic input, exceptions, and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL query strings are removed, and reports are retained for 30 days. Bounded lifecycle counters record the route, phase, attempt, page, and number of products saved; they do not contain query text or response bodies. Shortly before a finite run deadline, one diagnostic-only snapshot sends these counters and elapsed/remaining time to the same service, without input text. This observation does not stop work or mean the run failed. If a run stops early to finish before its timeout, one report with the same counters and the number of incomplete searches is sent.
The Actor does not use an AI model or send input or product data to an AI provider. Google and Apify proxy services receive search requests; their operating costs are included in the documented event prices. Product output, diagnostic HTML snapshots, and logs are stored in your Apify run storage under your account's retention settings and can be deleted there. Browser sessions are not persisted between runs. This independent tool is not affiliated with or endorsed by Google.
FAQ: keyword vs SKU/EAN
This actor is strongest for keyword and category searches. If you need offers for a known SKU/EAN, test with a very specific product query first and confirm the returned merchant fields match your workflow.
Use Amazon Scraper, eBay Scraper, Walmart Scraper, and Target Scraper when you need retailer-specific price/list-price/seller fields after Google Shopping identifies cross-merchant offers. Use Google Search Results Scraper for SEO/category demand, eBay Sold Listings Scraper for realized resale comps, and Pinterest Scraper for product trend discovery.
π What data can you extract from Google Shopping?
| Field | Type | Description |
|---|---|---|
title | string | Product title as shown on Google Shopping |
price | string | Displayed price string (e.g., "$228.00") |
priceNumeric | number | Numeric price value for filtering and arithmetic |
currency | string | Currency code (e.g., USD, EUR, GBP) |
originalPrice | string or null | Struck-through price as Google shows it (e.g., "$59.99"), sometimes in another currency than price. Installments are not included |
originalPriceNumeric | number or null | Original price as a number, in the row's currency. Null when originalPrice shows a different or unclear currency |
discountPercent | number or null | Discount from the original price, in percent. Null when the two prices are not in the same currency, as we never convert |
merchant | string | Store or seller name (e.g., "Amazon.com") |
productUrl | string | Google Shopping product page with this product's details and seller offers. A direct merchant URL is used when Google shows one. Empty when Google gives the result no catalog ID (often marketplace or resale listings), so a link never opens a different product |
imageUrl | string | Product image URL (Google CDN). Google embeds some images directly in the page with no link, so this is empty on part of the rows, often the top ones |
rating | number | Average star rating (0β5 scale) |
reviewCount | number | Total number of customer reviews |
delivery | string | Delivery information (e.g., "Free delivery", "Get it by Mon") |
catalogId | string or null | Google catalog ID of the product, stable across runs |
offerId | string or null | Google ID of this seller offer |
groupId | string or null | Google product group ID (gpcid) |
position | number | Position in the delivered results for this query (1 = first) |
query | string | The search query that produced this result |
scrapedAt | string | ISO 8601 timestamp of when the item was extracted |
19 fields per product. All data points are flat primitives β no nested objects, no arrays to unwrap.
π° How much does it cost to scrape Google Shopping?
This actor uses pay-per-event pricing β you pay only for what you scrape. No monthly subscription. All platform costs (compute, proxies, storage) are included.
Each run has a start charge plus a charge for each saved product. Current event rates in USD:
| Apify tier | Per run started | Per product |
|---|---|---|
| Free | $0.01 | $0.0034 |
| Bronze | $0.01 | $0.0034 |
| Silver | $0.01 | $0.00306 |
| Gold | $0.01 | $0.00272 |
| Platinum | $0.01 | $0.00272 |
| Diamond | $0.01 | $0.00272 |
Total event charges = start charge + saved products Γ per-product rate. A confirmed empty result has no product charge; the start charge still applies.
Real-world cost examples:
| Query | Results | Approx. Duration | Cost (Free tier) |
|---|---|---|---|
| "wireless earbuds" (default) | 20 products | ~30s | ~$0.08 |
| "running shoes" | 50 products | ~60s | ~$0.18 |
| "mechanical keyboard" | 100 products | ~90s | ~$0.35 |
| 5 queries Γ 50 products each | 250 products | ~3 min | ~$0.90 |
On the Free plan, the $5 monthly credit covers roughly 1,400 products β enough to evaluate the tool fully.
π How to scrape Google Shopping step by step
- Open Google Shopping Scraper on the Apify Store
- Click Try for free β this opens the actor in Apify Console (free account required)
- In the Search queries field, enter one or more product search terms, e.g.
["wireless earbuds", "noise cancelling headphones"] - Set Max results per query β start with
20to test, increase for bulk collection - Optionally set Country and Language to localize results (e.g.,
"de"for Germany,"fr"for France) - Optionally add Min price and Max price filters to narrow results to a specific price range
- Choose a Sort order:
relevance(default),price_low,price_high, orreview_score. Turn on On sale only or Free shipping only for deals - Click Save & Start and wait 30β90 seconds for results to appear
- Click Export to download as JSON, CSV, or Excel β or connect to Google Sheets, webhooks, or your API
Input example β price comparison across multiple queries:
{"queries": ["sony wf-1000xm5", "apple airpods pro", "bose quietcomfort earbuds"],"maxResults": 50,"country": "us","language": "en","sortBy": "price_low"}
Input example β finding top-rated budget products:
{"queries": ["wireless earbuds under 50"],"maxResults": 100,"country": "us","language": "en","minPrice": 10,"maxPrice": 50,"sortBy": "review_score"}
Input example β international price research:
{"queries": ["iPhone 16 Pro"],"maxResults": 30,"country": "de","language": "de"}
βοΈ Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
queries | array of strings | (required) | Product search queries. Each query runs independently and results are labeled with the query that produced them. Example: ["wireless earbuds"]. |
maxResults | integer | 50 (form prefill 20) | Maximum number of products per query, up to 500. One search on Google stops at about 130 products. With sortBy: relevance, the scraper also reads the price-sorted views of the same search to go further; with another sort, expect about 130 to 200. |
country | string | "us" | Two-letter country code for localized results. Affects which products, merchants, currencies, and prices are shown. Examples: "us", "uk", "de", "fr", "jp", "au", "ca", "in". |
language | string | "en" | Language code for result language. Examples: "en", "de", "fr", "es", "ja". |
minPrice | number | (none) | Minimum price filter in the local currency. Leave empty for no lower bound. |
maxPrice | number | (none) | Maximum price filter in the local currency. Leave empty for no upper bound. |
onSale | boolean | false | Only products Google shows with a discount. |
freeShipping | boolean | false | Ask Google for products with free shipping only. Best effort: this relies on Google's filter and is not checked on each row. |
sortBy | string | "relevance" | Sort order for results. Options: relevance (Google's default ranking), price_low (cheapest first), price_high (most expensive first), review_score (highest rating first; products with no rating last). A sorted search is ordered across all its pages, so its rows appear in the dataset when that search finishes. |
π¦ Output example
Each scraped product is returned as a flat JSON object. Here is a representative sample from a query for "wireless earbuds" sorted by relevance:
{"title": "Sony WF-1000XM5 Truly Wireless Noise Cancelling Earbuds","price": "$228.00","priceNumeric": 228.0,"currency": "USD","merchant": "Amazon.com","productUrl": "https://www.google.com/search?ibp=oshop&q=wireless+earbuds&prds=catalogid:...,gpcid:...,pvt:hg,pvo:3&hl=en&gl=us&udm=28","imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=tbn:ANd9Gc...","rating": 4.5,"reviewCount": 12847,"delivery": "Free delivery","position": 1,"query": "wireless earbuds","scrapedAt": "2026-03-22T12:00:00.000Z"}
Output from a price-comparison run (multiple queries, sorted by price_low):
[{"title": "Apple AirPods Pro (2nd Generation)","price": "$189.00","priceNumeric": 189.0,"currency": "USD","merchant": "Walmart","productUrl": "https://www.google.com/search?ibp=oshop&q=airpods&prds=catalogid:...,gpcid:...,pvt:hg,pvo:3&hl=en&gl=us&udm=28","imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=...","rating": 4.8,"reviewCount": 38221,"delivery": "Free shipping, arrives tomorrow","position": 1,"query": "apple airpods pro","scrapedAt": "2026-03-22T12:00:05.000Z"},{"title": "Bose QuietComfort Earbuds II","price": "$199.00","priceNumeric": 199.0,"currency": "USD","merchant": "Best Buy","productUrl": "https://www.google.com/search?ibp=oshop&q=headphones&prds=catalogid:...,gpcid:...,pvt:hg,pvo:3&hl=en&gl=us&udm=28","imageUrl": "https://encrypted-tbn0.gstatic.com/shopping?q=...","rating": 4.6,"reviewCount": 5104,"delivery": "Free shipping","position": 1,"query": "bose quietcomfort earbuds","scrapedAt": "2026-03-22T12:00:10.000Z"}]
π‘ Tips for best results
- Start with a small maxResults β run 20 items first to confirm the query and filters are set correctly before scaling to hundreds. This saves time and credit.
- Use specific queries β
"sony wf-1000xm5"returns more targeted results than"earbuds". Specific queries are also less likely to hit Google's result-count limits. - Combine price filters with sort β setting
minPrice/maxPricewithsortBy: "review_score"quickly surfaces the best-rated products in a price band. - Find real deals β set
onSale: trueand sort your export bydiscountPercentto see the deepest discounts first. - Track the same product across runs β use
catalogIdas the stable key; titles and offers change. - Try different countries for arbitrage β the same product often has significantly different prices across regions. Run the same query for
"us","uk","de", and"au"to map price disparities. - Schedule for price monitoring β use Apify Scheduler to run the scraper daily or weekly on a fixed set of queries, then compare each exported dataset in Google Sheets or your warehouse.
- Use
priceNumericfor math β all sorting, filtering, and price-change calculations should usepriceNumeric, not thepricestring. - Limit concurrent queries β if you are running 10+ queries in a single run, start with
maxResults: 20per query to keep run duration and cost predictable. - Give short runs enough time β if you set a short run timeout (for example under 60 seconds), the scraper stops starting new pages, retries or searches when they cannot finish in time. It keeps the products already saved and sets a status message listing incomplete searches. If a search got no results in time, the run finishes as failed (saved products stay in the dataset); if only later result pages were skipped, it finishes successfully. Searches with few or no Shopping results can need several retries, so allow 2β3 minutes per search for complete results.
- Check
reviewCountβ a highratingwith a very lowreviewCount(< 10) is often unreliable. Filter forreviewCount > 100when quality matters.
π Integrations
Google Shopping Scraper connects to the full Apify ecosystem. Here are specific workflow patterns that teams use:
Google Shopping β Google Sheets (daily price tracking)
Schedule the scraper to run each morning on your tracked product queries. Connect the output dataset to Google Sheets via the Apify integration. Use conditional formatting to highlight cells where priceNumeric dropped more than 10% since yesterday.
Google Shopping β Slack (price drop alerts)
Set up a webhook on the actor run. When a run completes, filter results downstream where priceNumeric < threshold and post a Slack message such as: "MacBook Pro 16 dropped to $2,199 at B&H Photo." Zapier, Make, or your own webhook handler can own the alert logic.
Google Shopping β Make/Zapier (competitor monitoring) Build a Make scenario: Google Shopping Scraper β filter for competitor merchant names β log to a Google Sheet β send weekly summary email. Automate brand-map audits without any servers.
Google Shopping β Amazon Scraper (cross-platform price comparison) Run Google Shopping Scraper to find which merchants are selling a product and at what prices, then pass the ASINs or product names to Amazon Scraper to get the full Amazon detail page with additional review data.
Scheduled monitoring runs
Use Apify Scheduler to run weekly sweeps of an entire product category (e.g., "bluetooth speaker" across 10 countries). Export each timestamped run to your sheet, database, or warehouse for longitudinal market analysis.
Webhooks for real-time pipelines Trigger a webhook on run completion to push results directly into your data warehouse (BigQuery, Snowflake, Redshift) via your ETL pipeline or a Zapier zap.
π€ API Usage β Using the Apify API
You can trigger Google Shopping Scraper programmatically from any language via the Apify API.
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });const run = await client.actor('automation-lab/google-shopping-scraper').call({queries: ['wireless earbuds', 'noise cancelling headphones'],maxResults: 50,country: 'us',language: 'en',sortBy: 'price_low',});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(`Scraped ${items.length} products`);console.log(items[0]);
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_API_TOKEN')run = client.actor('automation-lab/google-shopping-scraper').call(run_input={'queries': ['wireless earbuds', 'noise cancelling headphones'],'maxResults': 50,'country': 'us','language': 'en','sortBy': 'price_low',})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(f"Scraped {len(items)} products")print(items[0])
cURL
# Start the runcurl -X POST "https://api.apify.com/v2/acts/automation-lab~google-shopping-scraper/runs?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"queries": ["wireless earbuds"],"maxResults": 50,"country": "us","sortBy": "price_low"}'# Fetch results (replace DATASET_ID with the defaultDatasetId from the run response)curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN&format=json"
Get your API token from Apify Console β Settings β API & Integrations.
π§ Use with AI agents via MCP
Google Shopping Scraper is available as a tool for AI assistants that support the Model Context Protocol (MCP).
Add the Apify MCP server to your AI client β this gives you access to all Apify actors, including this one:
Setup for Claude Code
$claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/google-shopping-scraper"
Setup for Claude Desktop, Cursor, or VS Code
Add this to your MCP config file:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/google-shopping-scraper"}}}
Your AI assistant will use OAuth to authenticate with your Apify account on first use.
Example prompts
Once connected, try asking your AI assistant:
- "Use automation-lab/google-shopping-scraper to find the top 20 wireless earbuds under $100 on Google Shopping, sorted by review score"
- "Scrape Google Shopping for 'standing desk' products and compare prices across Amazon, Walmart, and Best Buy"
- "Search Google Shopping for 'mechanical keyboard' in Germany and give me the three cheapest options with ratings above 4 stars"
Learn more in the Apify MCP documentation.
π§Ύ Cite an observed price in agent answers without letting the model type it
Language models can invent or misremember prices. If your agent quotes prices from this Actor, let plain code pick one row and build the price sentence from that row's fields. The model then only repeats that sentence or reports that no price is available.
This example has no dependencies. It needs Node.js 18 or newer and works with the dataset items from the API examples above.
- You choose the row. Pass the
queryandpositionof the listing you want. The example does not guess by title, because a similar title can be a different model, variant, size, or condition. - It refuses gaps. A missing or non-numeric
priceNumeric, a wrong or missingcurrency, an emptymerchant, an emptyproductUrl, an invalid or oldscrapedAt, or a selection that matches no row givesstatus: "unavailable"with a reason. Missing values never become0. A real0price is shown as a zero price and flagged. - An empty
productUrlis normal output. The scraper leaves it empty when Google gives no catalog ID, often for marketplace or resale offers. Such a row has no source link, so the example does not quote it. - You set the age limit.
scrapedAtis when the scraper saw the listing. It does not show when the merchant last changed the price. - It is a listing price. It is the price Google Shopping showed in search results. It may differ from the merchant's checkout total with shipping, tax, or discounts.
// Builds a price sentence from one Google Shopping Scraper row selected by the caller.// Returns { status: 'observed', text, observation } or { status: 'unavailable', reason }.function renderPriceObservation(items, { query, position } = {}, { currency, maxAgeMinutes, now = new Date() } = {}) {const unavailable = (reason) => ({ status: 'unavailable', reason });if (!(now instanceof Date) || !Number.isFinite(now.getTime())) return unavailable('now must be a valid Date');if (!Array.isArray(items)) return unavailable('items must be the dataset items array');if (typeof query !== 'string' || !Number.isInteger(position) || position < 1) {return unavailable('select a row with a query string and a positive integer position');}if (typeof currency !== 'string' || !/^[A-Z]{3}$/.test(currency)) {return unavailable('pass the expected ISO 4217 currency code, for example "USD"');}if (typeof maxAgeMinutes !== 'number' || !Number.isFinite(maxAgeMinutes) || maxAgeMinutes <= 0) {return unavailable('pass a positive maxAgeMinutes freshness limit');}const matches = items.filter((row) => row && row.query === query && row.position === position);if (matches.length === 0) return unavailable(`no row for query "${query}" at position ${position}`);if (matches.length > 1) return unavailable(`${matches.length} rows match query "${query}" at position ${position}`);const row = matches[0];const price = row.priceNumeric;if (typeof price !== 'number' || !Number.isFinite(price)) return unavailable('the listing has no numeric price');if (price < 0) return unavailable('the listing price is negative');if (row.currency !== currency) {return unavailable(`the listing currency is "${row.currency ?? ''}", expected "${currency}"`);}const merchant = typeof row.merchant === 'string' ? row.merchant.trim() : '';if (!merchant) return unavailable('the listing has no merchant');const title = typeof row.title === 'string' ? row.title.trim() : '';if (!title) return unavailable('the listing has no title');let sourceUrl;try {sourceUrl = new URL(row.productUrl);} catch {return unavailable('the listing has no source link (productUrl is empty or invalid)');}if (sourceUrl.protocol !== 'https:' && sourceUrl.protocol !== 'http:') {return unavailable('the listing source link is not an http(s) URL');}const observedMs = typeof row.scrapedAt === 'string' ? Date.parse(row.scrapedAt) : NaN;if (!Number.isFinite(observedMs)) return unavailable('the listing has no valid scrapedAt time');const ageMinutes = (now.getTime() - observedMs) / 60000;if (ageMinutes < -5) return unavailable('scrapedAt is in the future');if (ageMinutes > maxAgeMinutes) {return unavailable(`the observation is ${Math.round(ageMinutes)} minutes old (limit ${maxAgeMinutes})`);}const observedAt = new Date(observedMs).toISOString();const amount = `${price.toFixed(2)} ${currency}`;const zeroNote = price === 0 ? ' Google Shopping showed a zero price; check the listing before relying on it.' : '';return {status: 'observed',text: `"${title}" was listed at ${amount} by ${merchant} on Google Shopping at ${observedAt} (${sourceUrl.href}).`+ `${zeroNote} This is a search-result listing price, not a checkout total, and may not match a specific variant or condition.`,observation: { title, price, currency, merchant, sourceUrl: sourceUrl.href, observedAt, query, position, isZeroPrice: price === 0 },};}
Example call. The row below is made up to show the format; it is not real market data:
const items = [{title: 'Example Wireless Earbuds', price: '$49.99', priceNumeric: 49.99, currency: 'USD',merchant: 'Example Store', productUrl: 'https://www.google.com/search?ibp=oshop&q=earbuds&prds=catalogid:123&udm=28',position: 1, query: 'wireless earbuds', scrapedAt: '2026-11-03T12:00:00.000Z',}];const result = renderPriceObservation(items, { query: 'wireless earbuds', position: 1 },{ currency: 'USD', maxAgeMinutes: 60, now: new Date('2026-11-03T12:30:00.000Z') });// result.status === 'observed'// result.text === '"Example Wireless Earbuds" was listed at 49.99 USD by Example Store on Google Shopping// at 2026-11-03T12:00:00.000Z (https://www.google.com/search?ibp=oshop&q=earbuds&prds=catalogid:123&udm=28).// This is a search-result listing price, not a checkout total, and may not match a specific variant or condition.'
Give the model result.text when status is "observed". Otherwise tell it that no verified price is available and pass result.reason. Fetch fresh data with a new run instead of asking the model to fill the gap.
βοΈ Legality β Is it legal to scrape Google Shopping?
Web scraping of publicly available data is generally considered legal based on multiple court rulings, including the landmark HiQ Labs v. LinkedIn case decided by the US Court of Appeals. Google Shopping product listings are fully public β any person can see the same data in a browser without logging in.
Key points:
- The scraper accesses only public product listing data β no login, no personal data, no private information
- Data is collected for legitimate business purposes β market research, price comparison, competitive intelligence
- The scraper uses residential proxies and polite delays to avoid overloading Google's infrastructure
- Apify is a GDPR-compliant platform β data is processed and stored in accordance with European privacy law
Always review and comply with Google's Terms of Service and any applicable laws in your jurisdiction before using scraped data commercially. For enterprise use cases with specific compliance requirements, consult your legal team.
β FAQ
How many products can I scrape per query?
One search on Google Shopping stops at about 130 products. With the default relevance order, the scraper also reads the price-sorted views of the same search, which reached 300 of 300 and 365 of 500 on a broad search in testing. With a price or rating sort, expect about 130 to 200. Very specific queries may return fewer. The final status of each run says how many products it delivered against what you asked for, and why it stopped: Google confirmed no more products, or its next page could not be read, so more may exist.
How much does scraping cost on the free plan?
Each run costs a flat $0.01 start fee plus $0.0034 per product at the Free tier. A default run of 20 products costs roughly $0.08. With $5 in free monthly credits, you can run many searches before spending a cent.
Is this better than the Google Shopping API?
Google does not offer a public Shopping product-listing API. The Google Shopping API is a merchant-facing tool for managing your own listings β it does not give you access to competitor or market-wide data. This scraper is the practical alternative for market research and competitive intelligence.
Why are some results missing prices or ratings?
Google Shopping sometimes shows products with incomplete data β for example, a product may not have any reviews yet (reviewCount: 0, rating: null) or may show a price range instead of a single price. In these cases, priceNumeric may be null if no single price can be parsed. This is expected behavior that reflects the actual state of the listing on Google Shopping.
Why am I getting empty results or fewer results than expected?
A few common causes:
- Overly specific or rare query β very niche product names may genuinely have few or no Google Shopping results. Try a broader search term.
- Country restriction β some products are not listed in Google Shopping for certain countries. Try
"us"if results for another country are sparse. - Price filter too narrow β if
minPriceandmaxPriceexclude most products, results will be few. Relax the range or remove filters. - Spending limit β a run stops at your maximum cost per run and says so in its status message.
- Temporary Google-side issue β retry the run a few minutes later if results are unexpectedly empty.
Can I run multiple queries in parallel?
Yes β the queries array accepts any number of search terms. The scraper processes them sequentially within a single run, labeling each result with the query that produced it via the query field. For large batches (50+ queries), consider splitting into multiple runs to stay within the actor's memory limit.
How often should I run the scraper for price monitoring?
Daily runs are typical for active price monitoring β Google Shopping prices update frequently, especially for consumer electronics and seasonal goods. Use Apify Scheduler with a daily cron (e.g., 0 6 * * * to run at 6 AM) and push results to Google Sheets for automatic tracking.
π Other e-commerce scrapers
Looking to scrape specific merchant platforms or compare pricing across marketplaces? Check out these related actors from automation-lab:
- Amazon Scraper β extract product listings, prices, ratings, and reviews from Amazon
- eBay Scraper β scrape eBay listings including auctions, Buy It Now prices, and seller info
- Walmart Scraper β collect product data from Walmart's online store
- Newegg Scraper β extract tech product listings from Newegg
- Target Scraper β scrape product data from Target's e-commerce site
- Etsy Scraper β collect handmade and vintage product listings from Etsy
- Shopify Store Scraper β extract product catalogs from any Shopify-powered store
- Google Search Results Scraper β scrape organic and paid Google Search results for any keyword
Use with AI agents via x402 (no Apify account)
Agent workflows can run this actor through Apify MCP without an Apify account when the MCP client uses a funded x402 wallet. Use the actor-specific MCP endpoint:
https://mcp.apify.com?tools=automation-lab/google-shopping-scraper&payment=x402
This keeps existing Apify MCP/API usage unchanged; x402 only changes payment/authentication for clients that support it. Learn more in Apify's x402 integration docs.