Free Google Shopping Scraper - Extract offers from any EAN/SKU
Pricing
from $8.00 / 1,000 google-skus
Free Google Shopping Scraper - Extract offers from any EAN/SKU
Grab all offers from all sellers of a Google Shopping EAN/SKU. Whether you're monitoring competitor prices, optimizing your pricing strategy, or tracking market trends, this scraper delivers the insights you need at scale.
Pricing
from $8.00 / 1,000 google-skus
Rating
0.0
(0)
Developer
SR
Maintained by CommunityActor stats
12
Bookmarked
499
Total users
57
Monthly active users
2.2 days
Issues response
14 hours ago
Last modified
Categories
Share
Google Shopping Scraper — Real-Time Price & Offer Data by EAN / GTIN
Extract live pricing data from Google Shopping for any product, identified by EAN or GTIN barcode. Get every seller offer — price, shipping, condition, seller identity — across 25+ countries, in one clean JSON output per product.
Products are looked up by EAN/GTIN or by Google Shopping SKU. Paste either, one per line; the type is detected automatically. Entries that are neither produce an error record.
What It Does
This actor resolves your EAN/GTIN codes against Google Shopping and returns a structured dataset of all seller offers. For each product you submit, you receive the full competitive landscape: who is selling it, at what price, with what shipping cost, and under what conditions.
If an EAN has never been scraped, the actor queues a scrape and returns a free queued_for_scrape record asking you to run again in about 2 hours — you are not charged for that. Once the EAN has been scraped you get either the offers (cached) or a verified "Google has no offers for this" verdict (scraped_no_offers); both are charged. See Pricing.
Output Schema
Each record in the dataset represents one product lookup. Every record carries a status telling you which of three outcomes it is — and whether it was charged:
status | Meaning | Charged? |
|---|---|---|
queued_for_scrape | Nothing known about this EAN yet. A scrape has been queued. | No — free |
scraped_no_offers | The scrape ran; Google Shopping has no offers for this EAN. | Yes |
cached | Offers found and returned. | Yes |
Product Record
| Field | Type | Description |
|---|---|---|
ean | string | null | EAN / GTIN barcode (null when looked up by SKU) |
sku | string | null | Google Shopping SKU / catalog id (null when looked up by EAN) |
status | string | queued_for_scrape, scraped_no_offers or cached (see above) |
found | boolean | false only for queued_for_scrape (the free case). true once the EAN has actually been scraped. |
gl | string | Country code (lowercase) the lookup ran against |
title | string | null | Product title as listed on Google Shopping |
brand | string | null | Brand name |
url | string | null | Google Shopping search URL for the product |
thumbnail | string | null | Product image URL |
currency | string | null | ISO 4217 currency code (e.g. EUR, GBP) |
offers_count | integer | Number of seller offers returned |
lowest_total_price | number | Lowest combined price + shipping across all offers |
highest_total_price | number | Highest combined price + shipping across all offers |
offers | array | Full list of seller offers — see below |
fetched_at | string | When the offers were scraped (cached only) |
checked_at | string | When the empty scrape ran (scraped_no_offers only) |
age_hours | number | How old the scrape result is, in hours |
no_offers_found | boolean | true on scraped_no_offers records |
message | string | Human-readable explanation (queued_for_scrape, scraped_no_offers) |
retry_after_hours | integer | Hours to wait before re-requesting (queued_for_scrape only) |
Offer Object
| Field | Type | Description |
|---|---|---|
sellerName | string | Shop or marketplace name (e.g. Amazon.fr, Zalando.fr) |
sellerReference | string | Direct URL to the product listing at the seller |
price | string | Base product price |
shippingPrice | string | null | Shipping cost, or null if unknown |
totalPrice | string | Price + shipping combined |
condition | string | Product condition (New, Used, Refurbished) |
availability | string | Stock availability (e.g. InStock) |
Example — Offers Found (Charged)
status: "cached" — the normal case.
{"ean": "0198376596101","gl": "fr","found": true,"status": "cached","title": "Sandales Skechers Desert Kiss Low Femme","brand": null,"url": "https://www.google.com/search?q=%2B%22Sandales+Skechers+Desert+Kiss+Low+Femme%22&num=10&udm=28&gl=fr","thumbnail": "https://encrypted-tbn3.gstatic.com/shopping?q=...","currency": "EUR","fetched_at": "2026-07-13T10:00:00","age_hours": 1.4,"offers_count": 7,"lowest_total_price": 35.99,"highest_total_price": 82.0,"offers": [{"sellerName": "Amazon.fr","sellerReference": "https://www.amazon.fr/Skechers-Femme-Desert-Sandale-Glissante/dp/B0DC8QSWVC","price": "35.99","shippingPrice": null,"totalPrice": "35.99","condition": "New","availability": "InStock"},{"sellerName": "obishoes.fr","sellerReference": "https://obishoes.fr/sandales/9624-sandales-skechers-bobs-desert-kiss-low-peak-look-114707-noir","price": "40.99","shippingPrice": "4.95","totalPrice": "45.94","condition": "New","availability": "InStock"}]}
Example — Scrape Queued (Free)
status: "queued_for_scrape" — nothing is known about this EAN yet, so a scrape has been queued. This record is free and does not appear in the default dataset: you will find it in the queued-and-skipped dataset, and the full retry list in the QUEUED_EANS key-value record. Run the actor again for these EANs in about 2 hours to get the offers.
{"ean": "5088809648017","gl": "uk","found": false,"status": "queued_for_scrape","message": "This product has not been scraped yet. A scrape has been queued and this request is free of charge. Please run the actor again for this EAN in about 2 hours to retrieve the offers.","retry_after_hours": 2,"offers_count": 0,"offers": []}
Example — Scraped, No Offers Exist (Charged)
status: "scraped_no_offers" — the scrape ran and Google Shopping has no offers for this EAN in this country. That is a real, verified verdict, so it is charged. No new scrape is queued. Use checked_at / age_hours to see how recent the "nothing exists" verdict is.
{"ean": "5088809648017","gl": "uk","found": true,"status": "scraped_no_offers","no_offers_found": true,"message": "This product was scraped but Google Shopping returned no offers for it in this country. No new scrape was queued.","title": null,"brand": null,"url": null,"thumbnail": null,"currency": null,"checked_at": "2026-07-13T13:05:12","age_hours": 3.2,"offers_count": 0,"offers": []}
Example — Input Without EAN (Error Record)
Entries that do not contain a valid EAN/GTIN are not processed. Instead, an error record is added to the dataset:
{"input": "not-an-ean","error": "EAN is required. Supply a valid EAN/GTIN (8, 12, 13 or 14 digits) for every product."}
Input Format
Select your target country from the dropdown (default: Netherlands), then enter one EAN/GTIN code per line:
87206483641814024074895542193575000923
Accepted formats: EAN-8 (8 digits), UPC-A (12 digits), EAN-13 (13 digits), GTIN-14 (14 digits), or a Google Shopping SKU (15+ digit catalog id). You can mix both in one run. Any entry that is neither is rejected with an error record (free, never charged).
There is also an optional Force fresh fetch toggle — see Caching and Forcing Fresh Data at the bottom.
Supported Countries
| Country | Code | Google Shopping Domain |
|---|---|---|
| Netherlands | NL | shopping.google.nl |
| Germany | DE | shopping.google.de |
| France | FR | shopping.google.fr |
| Belgium | BE | shopping.google.be |
| Austria | AT | shopping.google.at |
| Switzerland | CH | shopping.google.ch |
| Spain | ES | shopping.google.es |
| Italy | IT | shopping.google.it |
| Poland | PL | shopping.google.pl |
| Sweden | SE | shopping.google.se |
| Denmark | DK | shopping.google.dk |
| Norway | NO | shopping.google.no |
| Finland | FI | shopping.google.fi |
| Portugal | PT | shopping.google.pt |
| Ireland | IE | shopping.google.ie |
| Czech Republic | CZ | shopping.google.cz |
| Hungary | HU | shopping.google.hu |
| Romania | RO | shopping.google.ro |
| Greece | GR | shopping.google.gr |
| Slovakia | SK | shopping.google.sk |
| Croatia | HR | shopping.google.hr |
| Bulgaria | BG | shopping.google.bg |
| United Kingdom | UK | shopping.google.co.uk |
| United States | US | shopping.google.com |
| Australia | AU | shopping.google.com.au |
| Canada | CA | shopping.google.ca |
| Brazil | BR | shopping.google.com.br |
| India | IN | shopping.google.co.in |
| Japan | JP | shopping.google.co.jp |
Supported Product Identifiers
You can submit either identifier, mixed freely in the same run. The type is detected from the code, and the two formats never collide.
EAN / GTIN barcodes (8 to 14 digits). Our matching algorithm resolves these against Google Shopping automatically:
- EAN-8 (8 digits)
- UPC-A (12 digits)
- EAN-13 (13 digits, most common in Europe)
- GTIN-14 (14 digits)
Google Shopping SKU (15+ digits) — the long numeric catalog id, e.g. 15946942461803762490. Use this when you already know Google's product id and want to skip EAN matching entirely.
On the output record, ean is populated for EAN lookups and sku for SKU lookups; the other is null. Entries that are neither a valid EAN nor a SKU return an error record (free, never charged).
Item Limits and Plan Tiers
| Plan | Limit |
|---|---|
| Free | 20 products per dataset |
| Paid | Set via ACTOR_MAX_PAID_DATASET_ITEMS environment variable |
The actor tracks unique products by EAN. Re-submitting the same identifier in a single run does not count twice. Items already in the dataset from previous runs count toward the limit.
Configuring a paid limit:
- Apify Console → Your Actor → Settings → Environment variables
- Add
ACTOR_MAX_PAID_DATASET_ITEMSwith your desired value (e.g.5000)
Pricing
You are only charged once an EAN has actually been scraped. Queuing a scrape is free.
status | What happened | Charged? | Where it lands |
|---|---|---|---|
queued_for_scrape | First time we've seen this EAN. A scrape was queued; no data yet. | No, free. Re-run in ~2 hours. | queued-and-skipped dataset + QUEUED_EANS |
scraped_no_offers | The scrape ran and Google Shopping had no offers for this EAN. | Yes. | Default dataset |
cached | The scrape ran and offers were returned. | Yes. | Default dataset |
You are billed per item in the default dataset. Records you are not charged for never enter it:
- Queued EANs and rejected inputs go to a separate
queued-and-skippeddataset, plus aQUEUED_EANSrecord in the key-value store containing the exact list of EANs to retry. Both are free. - A run over 500 EANs where only 9 resolve therefore costs you 9 items, not 500.
scraped_no_offers is charged because it is a real result: confirming that a product has no listings in a market requires the same full scrape as finding offers. The checked_at / age_hours fields tell you how recent that verdict is, and no new scrape is queued for it, so re-requesting the same EAN will not put you in a re-billing loop.
Recommended two-pass flow
- Run A submits your full EAN list. You are charged only for the EANs that already have data.
- Read
QUEUED_EANSfrom the run's key-value store (or thequeued-and-skippeddataset) to get the EANs whose scrape was just queued. These cost nothing. - Run B, about 2 hours later, submits only that list. Now those EANs return
cachedorscraped_no_offers.
You can automate this with a scheduled Apify task, so you never orchestrate it by hand.
Use Cases
Retail price monitoring — track how your products are priced across all Google Shopping sellers in each of your markets. Identify undercutting, map-price violations, and grey-market listings.
Dynamic repricing — feed real-time competitor prices into your repricing engine to stay competitive without eroding margin.
Market entry research — before expanding to a new country, assess the competitive landscape by querying your catalogue against that market's Google Shopping.
Marketplace benchmarking — compare your prices against the lowest and highest offers across multiple sellers to understand your positioning.
Price drop alerts — schedule regular runs and compare lowest_total_price against a stored baseline to trigger alerts when a competitor drops price significantly.
Caching and Forcing Fresh Data
By default this actor serves cached offers up to 24 hours old. If a product was scraped within the last 24 hours, you get that result instantly and cheaply, without triggering a new scrape.
Turn on Force fresh fetch when you need the newest possible data (for example right after a price change) and don't want a cached copy. Forcing makes the actor demand fresh data and trigger a new scrape whenever the cache is stale.
How to force
In the Apify UI, tick the Force fresh fetch checkbox.
Via the API / JSON input, set force to true:
{"country": "NL","products": "8720648364181\n8720938897238","force": true}
Leave force out (or set it to false) to use the standard 24-hour cache.
Note: forcing runs a real scrape, so it can take longer to return and may be charged like any other scraped result.
Support
For questions, issues, or feature requests, open a ticket via the Apify platform.
