Google Shopping Scraper - Extra Offers
Pricing
from $1.99 / 1,000 results
Google Shopping Scraper - Extra Offers
Google Shopping Scraper - Extra Offers retrieves merchant offers by EAN or SKU - title, brand, thumbnail, currency, offer count and lowest and highest total price with freshness timestamps. ๐ท๏ธ For price comparison and MAP monitoring.
Pricing
from $1.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapers Hub
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
๐๏ธ Google Shopping Scraper โ Extra Offers, Seller Prices & EAN Lookup
The Google Shopping Scraper โ Extra Offers takes a list of product identifiers, looks each one up on Google Shopping for a chosen country, and returns a structured offer record containing every seller listing it finds. Rather than a page of search results, you get a normalised object per product: the product title and brand, the currency, the number of offers, the full offers array, and the lowest and highest total prices across those offers.
This Google Shopping scraper is aimed at price monitoring, marketplace intelligence and retail analytics workflows where the unit of analysis is a product rather than a keyword. You feed it EANs or product codes, one per line, and it produces a dataset you can join straight onto your own catalogue. Each record is stamped with the country code it was checked against and a timestamp, so historical price series stay unambiguous.
๐ What Data Can You Extract with This Google Shopping Scraper?
Every record returned by the Google Shopping scraper covers six areas: how the product was identified, whether the lookup succeeded, what the product is, what the offers look like, how prices are distributed, and when the check happened.
| Category | Fields | What it tells you |
|---|---|---|
| ๐ Product identifiers | ean, sku | The identifier you supplied and any stock keeping unit associated with the record |
| ๐ Market context | gl, currency | The country code the lookup targeted and the currency the prices are quoted in |
| โ Lookup outcome | found, status, no_offers_found, message | Whether the product resolved, what state the check ended in, and a human-readable explanation |
| ๐งพ Product attributes | title, brand, url, thumbnail | The product name, its brand, the canonical URL for the lookup and a thumbnail image |
| ๐ฐ Offers and pricing | offers, offers_count, lowest_total_price, highest_total_price | The full array of seller offers plus the count and the price envelope across them |
| โฑ๏ธ Freshness | checked_at, fetched_at, age_hours | When the product was checked, when the page was fetched and how old the data is in hours |
The most operationally useful pairing is lowest_total_price with offers_count. A low floor price backed by many offers means a genuinely competitive product where undercutting is expensive; a low floor with one or two offers usually means a single aggressive seller you can monitor individually.
๐ Key Features of the Google Shopping Scraper
| Feature | Description |
|---|---|
| ๐ข Identifier-driven lookups | Supply products as a newline-separated list in the products field; each line is looked up independently and returned as its own dataset record |
| ๐ Country targeting | The country input sets the Google Shopping locale (gl), so prices and available sellers reflect the market you actually sell in |
| ๐ฆ Full offers array | The offers field carries the seller-level detail behind the summary numbers, rather than only a single headline price |
| ๐ Price envelope | lowest_total_price and highest_total_price are computed across the offers so you get the spread without post-processing |
| ๐ฆ Explicit outcome flags | found, status and no_offers_found distinguish "product not resolved" from "resolved but no sellers listed" โ two very different situations |
| ๐ฌ Diagnostic messages | The message field explains unusual outcomes in plain language, which makes triaging a large batch far quicker |
| โฑ๏ธ Freshness metadata | checked_at, fetched_at and age_hours are attached to every record, so downstream systems can decide whether to trust or refresh a value |
| ๐ Force refresh flag | The force input lets you re-run a lookup rather than accepting a previously cached outcome |
| ๐งฑ Stable record shape | Every product returns the same keys whether or not offers were found, so the dataset loads cleanly into a fixed-schema table |
๐ Why Choose This Google Shopping Scraper?
Product-level, not keyword-level. Keyword scrapers give you whatever Google decides is relevant. This actor works from identifiers you control, so each row maps deterministically onto a row in your own product master. That is the difference between a research dump and a dataset you can join.
The offer spread comes precomputed. Most pipelines end up recalculating minimum and maximum totals from a raw offers list. Here lowest_total_price and highest_total_price arrive alongside offers_count, so a simple dashboard needs no transformation layer at all.
Failure states are first-class data. found, status, no_offers_found and message mean an unsuccessful lookup still produces a usable record. You can measure your own coverage โ how many catalogue items Google actually lists in a given country โ instead of silently losing rows.
Country is explicit on every row. Because gl and currency are stored per record, you can run the same product list against several markets and stack the results in one table without ambiguity about which price belongs to which country.
๐ฅ Input
{"products": "8720648364181\n8712345678901\n4006381333931","country": "NL","force": false}
๐ง Google Shopping Scraper Input Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
products | string | Yes | "" | Product identifiers to look up, one per line. Blank lines are ignored. If no products are supplied the run ends immediately. |
country | string | No | NL | Country code used as the Google Shopping locale for the lookup. It is lower-cased and returned on each record as gl. |
force | boolean | No | false | Force the lookup to run rather than accepting a previously stored result. |
๐ก Input Examples
Single-market price check
{"products": "8720648364181","country": "NL"}
Batch of catalogue EANs for the German market
{"products": "4006381333931\n4008110018751\n4005808756919","country": "DE","force": true}
United States lookup
{"products": "0885909950805\n0194252099216","country": "US","force": false}
๐ค Output
{"ean": "8720648364181","sku": null,"gl": "nl","found": true,"status": "scraped","title": "Example Product Name","brand": "ExampleBrand","url": "https://www.google.com/search?q=8720648364181&tbm=shop&gl=nl","thumbnail": "https://example.com/thumbnail.jpg","currency": "EUR","fetched_at": "2026-08-11T09:14:02.481Z","age_hours": 0.0,"offers_count": 2,"offers": [{"sellerName": "Store A","sellerReference": "https://example.com/store-a","price": "34.95","shippingPrice": null,"totalPrice": "34.95","condition": "New","availability": "InStock"}],"lowest_total_price": 34.95,"highest_total_price": 39.95}
When a product resolves but Google Shopping lists no sellers, the record instead carries status set to a no-offers state, no_offers_found set to true, an empty offers array, offers_count of 0, and an explanatory message.
๐งพ Google Shopping Output Fields
| Field | Type | Description |
|---|---|---|
ean | string | null | Ean of the item. |
sku | string | null | Stock keeping unit. |
gl | string | null | Gl of the item. |
found | boolean | null | Whether found. |
status | string | null | Status of the item. |
no_offers_found | boolean | null | Whether no offers found. |
message | string | null | Message of the item. |
title | string | null | Title of the item. |
brand | string | null | Brand name. |
url | string | null | Canonical URL of the scraped item. |
thumbnail | string | null | Thumbnail image URL. |
currency | string | null | Currency code of the price. |
checked_at | string | null | When the checked happened. |
age_hours | number | null | Age hours of the item. |
offers_count | integer | null | Number of offers. |
offers | array | null | Offers values collected for the item. |
fetched_at | string | null | When the page was fetched. |
lowest_total_price | number | null | Lowest total price of the item. |
highest_total_price | number | null | Highest total price of the item. |
๐งพ Offer Object Fields
Each entry inside the offers array describes a single seller listing:
| Field | Description |
|---|---|
sellerName | Name of the merchant making the offer |
sellerReference | Reference URL for the merchant or the offer |
price | Item price excluding shipping |
shippingPrice | Shipping cost, where one is stated |
totalPrice | Item price plus shipping |
condition | Stated condition of the item, such as New |
availability | Stock status reported by the merchant |
๐ป How to Use the Google Shopping Scraper (Step by Step)
Step 1: Assemble your product identifier list
The products field takes a plain block of text with one identifier per line. Export the identifier column from your product information system, paste it into the field, and the actor splits it on newlines and trims whitespace automatically. Empty lines are skipped, so a trailing blank line at the end of a paste is harmless. If the field ends up empty, the run finishes immediately without producing any records โ a useful sanity check if you ever see an empty dataset.
Step 2: Choose the target country
country decides which Google Shopping locale is queried and therefore which merchants and currency appear in the results. It defaults to NL. Whatever you pass is lower-cased and echoed back on every record as gl, which is what makes multi-market datasets safe to stack. If you sell in several countries, run the same product list once per country rather than mixing markets in a single run.
Step 3: Decide whether to force a refresh
The force flag controls whether the actor performs a fresh lookup or is willing to return a previously stored outcome. Leave it false for routine monitoring where a slightly older value is acceptable, and set it true when you are investigating a specific pricing anomaly and need to be certain the numbers reflect the present moment. The age_hours field on each record tells you how stale the returned data is.
Step 4: Start the run and watch the log
Launch the actor from the Apify Console or the API. The run log reports how many products were parsed from your input and the country being used, then logs each product as it is processed. If a lookup fails at the HTTP level, the log records the status code for that specific product and continues to the next one, so a single problematic identifier does not abort the whole batch.
Step 5: Interpret the outcome flags before the prices
Before you analyse pricing, split the dataset on found and no_offers_found. Records where found is false never resolved to a product at all โ usually an identifier problem on your side. Records where no_offers_found is true resolved fine but had no sellers in that country, which is a genuine market-coverage finding rather than an error. Only the remaining rows carry meaningful offers data.
Step 6: Work with the offers array
offers_count gives you the headline, but the real detail sits in the offers array. Each entry names a seller, states a price, a shipping price and a total, and reports condition and availability. Flatten this array into a separate table keyed on ean if you want per-seller time series; keep it nested if you only need the summary figures, which are already available as lowest_total_price and highest_total_price.
Step 7: Export, schedule and integrate
Export the dataset as CSV, JSON, XLSX or XML from the Console, or read it through the dataset API. For ongoing price monitoring, attach an Apify Schedule to run the same product list at a fixed cadence, and use a webhook to notify your own systems when each run completes so a downstream job can pick up the new snapshot automatically.
๐ API Access & Integrations
Trigger a Google Shopping scraping run and get the dataset items back in one call:
curl -X POST "https://api.apify.com/v2/acts/scrapers-hub~google-shopping-scraper-extra-offers/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"products": "8720648364181\n4006381333931","country": "NL","force": false}'
The equivalent using the Python client:
from apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("scrapers-hub/google-shopping-scraper-extra-offers").call(run_input={"products": "8720648364181\n4006381333931\n4008110018751","country": "NL","force": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["ean"], item["offers_count"], item["lowest_total_price"])
Finished datasets connect to Zapier, Make, Google Sheets and Slack, and Apify webhooks can call your own endpoint the instant a Google Shopping run completes.
๐ก Best Use Cases for Google Shopping Offers Data
๐ฐ Competitive price monitoring
Run your catalogue EANs daily and track lowest_total_price per product over time. Because totalPrice inside each offer already includes shipping where stated, you are comparing landed prices rather than headline prices, which is what a shopper actually decides on. Alert when the floor drops below your own listed price.
๐บ๏ธ Cross-border market coverage
Execute the same products list against several country values and compare found and no_offers_found rates. Products that resolve everywhere but only attract offers in one market show you where distribution is thin, and the gl field on each record keeps the markets cleanly separated in a stacked table.
๐งฎ Price dispersion analysis
The gap between lowest_total_price and highest_total_price, divided by offers_count, is a quick proxy for how disciplined a product's pricing is. Wide dispersion across many offers often signals grey-market supply or inconsistent MAP enforcement, and is worth investigating seller by seller in the offers array.
๐ช Seller and reseller discovery
Flatten the offers array and group by sellerName to build a list of every merchant carrying your products. sellerReference gives you the link to follow up, and availability tells you whether they hold stock or are listing without inventory.
๐ Catalogue data enrichment
Where your own product records are incomplete, title, brand and thumbnail provide reference values you can use to fill gaps or validate existing entries. Comparing the returned brand against your master data is also an effective way to catch mis-keyed identifiers.
๐ฐ๏ธ Data freshness governance
checked_at, fetched_at and age_hours let you enforce a service-level rule in your own pipeline: refresh anything older than a threshold, and flag anything stale in your reporting layer. Combined with the force input, this makes selective refreshes straightforward.
๐จ Availability and stock-out tracking
The availability value inside each offer, read alongside offers_count and no_offers_found, gives you an early-warning signal for products disappearing from a market. A product whose offer count falls steadily towards zero is losing distribution before it shows up in your own sales data.
โ๏ธ Tips for Better Google Shopping Scraping Results
- Clean identifiers before submitting them. Strip spaces, hyphens and leading apostrophes that spreadsheet exports often add. A malformed EAN is the single most common reason for a
foundvalue of false. - Keep one country per run. Mixing markets in a single job makes the dataset harder to reason about; separate runs per
countryvalue keep both the input and the resulting time series clean. - Batch sensibly. Very large single blocks in
productsproduce long runs. Splitting a large catalogue into several runs makes failures easier to isolate and reruns cheaper. - Use
forcesparingly. Forcing a refresh on every product on every run removes the benefit of stored results. Reserve it for investigations and for products whereage_hoursexceeds your tolerance. - Store
checked_atwith every snapshot. When you append runs into a historical table, the timestamp is what turns a pile of rows into a usable price series. - Separate no-offer records early. Filter on
no_offers_foundbefore computing averages, otherwise products with zero sellers will quietly skew your aggregates.
๐ ๏ธ Troubleshooting
The run finished but the dataset is empty.
The actor exits immediately when no products are parsed from the input. Check that products actually contains text and that lines are separated by real newlines rather than commas or semicolons.
A product returns found as false.
The identifier did not resolve. Verify the EAN or code against your source system, confirm there are no stray characters, and check whether the product is sold in the country you targeted at all.
A product returns no_offers_found as true.
This is not an error. The lookup succeeded but Google Shopping listed no sellers for that product in that country. The message field explains the outcome. Try a different country value if you expect the product to be available elsewhere.
Some products are missing from the dataset entirely. If a lookup fails at the HTTP level the actor logs the failing status code for that product and moves on rather than pushing a record. Check the run log for those entries and re-submit just those identifiers.
Prices look stale.
Inspect age_hours on the affected records. If the value is higher than you want, set force to true and rerun those identifiers to obtain a fresh check.
โ Frequently Asked Questions About Google Shopping Scraping
What does this Google Shopping scraper actually return?
One record per product identifier you submit, containing the identifiers, the country code, outcome flags, product attributes, the full offers array, the offer count, the lowest and highest total prices, and freshness timestamps.
What format should the products input use?
Plain text with one identifier per line. The actor splits on newlines and trims each entry, and blank lines are ignored, so pasting a column straight out of a spreadsheet works without further formatting.
Which countries can I target?
Any country code accepted by Google Shopping's gl parameter. The default is NL. Whatever you supply is lower-cased and stored on each record so multi-market datasets remain unambiguous.
Does the actor need a Google API key? No. It queries Google Shopping's public interface directly, so there is no API key to obtain and no developer quota attached to your account.
What is the difference between found and no_offers_found?
found tells you whether the product resolved at all. no_offers_found tells you whether it resolved but had no seller listings. A record can be found and still have no offers, which is a meaningful market signal rather than a failure.
How do I get per-seller prices rather than just the summary?
Read the offers array. Each entry contains sellerName, sellerReference, price, shippingPrice, totalPrice, condition and availability.
Does lowest_total_price include shipping?
It is derived from the totalPrice values in the offers array, which combine item price and shipping where a shipping price is stated. Where a merchant does not state shipping, shippingPrice is null and the total equals the item price.
What does age_hours mean?
How old the returned data is, in hours, at the time the record was produced. Use it together with checked_at and fetched_at to decide whether a value meets your freshness requirements.
When should I set force to true?
When you need certainty that the lookup was performed fresh rather than returning a previously stored outcome โ typically during an investigation, or when age_hours on an earlier record exceeded your threshold.
Can I scrape Google Shopping by keyword instead of by identifier? This actor is identifier-driven. Its input is a list of product codes, which is what makes each output row joinable to a catalogue record. Keyword search is not part of its input schema.
Can I export the results to Excel or Google Sheets? Yes. Apify datasets export to CSV, XLSX, JSON and XML from the Console, and the dataset API endpoint can be consumed directly by Google Sheets or any BI tool that reads CSV or JSON over HTTP.
How do I schedule recurring Google Shopping price checks?
Create an Apify Schedule pointing at this actor with your saved input. Keep the products list and country value identical between runs so the resulting snapshots form a comparable time series.
Is scraping Google Shopping legal? The actor reads publicly visible Google Shopping results. Public data collection is broadly permissible in many jurisdictions, but you remain responsible for complying with Google's Terms of Service and any laws or contracts that apply to you. Take legal advice before redistributing collected data commercially.
Are the fields ever null?
Yes. Fields that Google does not supply for a given product โ commonly sku, brand, thumbnail or currency on unresolved lookups โ come back as null rather than being omitted, so the record shape stays consistent across every row.
How do I connect the output to my own systems? Use the dataset API, an Apify webhook that fires on run completion, or one of the no-code integrations such as Zapier, Make, Google Sheets or Slack.
๐ Support & Feedback
Spotted a problem with the Google Shopping scraper, or a field that is not behaving as documented? Report it on the Issues tab of this actor so it can be tracked and fixed in the open.
If you need a custom build โ additional offer attributes, a different input format, keyword-driven lookups, or an output shape tailored to your warehouse โ email scraperhubapi@gmail.com with a description of your use case.
If this actor is useful to you, a rating and a short review on the actor page genuinely helps other pricing and ecommerce teams find it, and it guides what gets built next.
โ๏ธ Disclaimer
This Google Shopping scraper accesses only publicly visible product and offer information. It does not log in to any account, bypass authentication, or retrieve data that is not already displayed to ordinary visitors.
Responsibility for how the collected data is used rests with you. That includes observing Google's Terms of Service, respecting applicable copyright and database rights, and complying with any competition or consumer-protection rules that govern price monitoring in the markets you operate in.
The fields returned describe products, merchants and prices rather than individuals. Should any record you collect nonetheless contain personal data โ a sole trader's name appearing as a seller, for example โ you act as the data controller for that record and must comply with the GDPR, the UK GDPR, the CCPA or whichever privacy regime applies, including lawful basis, retention limits and data subject rights.
This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Google LLC. If you believe data collected through this actor should be removed, write to scraperhubapi@gmail.com with the specifics and the request will be handled promptly.