Google Shopping Scraper - Extra Offers avatar

Google Shopping Scraper - Extra Offers

Pricing

from $1.99 / 1,000 results

Go to Apify Store
Google Shopping Scraper - Extra Offers

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

Scrapers Hub

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

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.

CategoryFieldsWhat it tells you
๐Ÿ”– Product identifiersean, skuThe identifier you supplied and any stock keeping unit associated with the record
๐ŸŒ Market contextgl, currencyThe country code the lookup targeted and the currency the prices are quoted in
โœ… Lookup outcomefound, status, no_offers_found, messageWhether the product resolved, what state the check ended in, and a human-readable explanation
๐Ÿงพ Product attributestitle, brand, url, thumbnailThe product name, its brand, the canonical URL for the lookup and a thumbnail image
๐Ÿ’ฐ Offers and pricingoffers, offers_count, lowest_total_price, highest_total_priceThe full array of seller offers plus the count and the price envelope across them
โฑ๏ธ Freshnesschecked_at, fetched_at, age_hoursWhen 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

FeatureDescription
๐Ÿ”ข Identifier-driven lookupsSupply products as a newline-separated list in the products field; each line is looked up independently and returned as its own dataset record
๐ŸŒ Country targetingThe country input sets the Google Shopping locale (gl), so prices and available sellers reflect the market you actually sell in
๐Ÿ“ฆ Full offers arrayThe offers field carries the seller-level detail behind the summary numbers, rather than only a single headline price
๐Ÿ“‰ Price envelopelowest_total_price and highest_total_price are computed across the offers so you get the spread without post-processing
๐Ÿšฆ Explicit outcome flagsfound, status and no_offers_found distinguish "product not resolved" from "resolved but no sellers listed" โ€” two very different situations
๐Ÿ’ฌ Diagnostic messagesThe message field explains unusual outcomes in plain language, which makes triaging a large batch far quicker
โฑ๏ธ Freshness metadatachecked_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 flagThe force input lets you re-run a lookup rather than accepting a previously cached outcome
๐Ÿงฑ Stable record shapeEvery 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

FieldTypeRequiredDefaultDescription
productsstringYes""Product identifiers to look up, one per line. Blank lines are ignored. If no products are supplied the run ends immediately.
countrystringNoNLCountry code used as the Google Shopping locale for the lookup. It is lower-cased and returned on each record as gl.
forcebooleanNofalseForce 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

FieldTypeDescription
eanstring | nullEan of the item.
skustring | nullStock keeping unit.
glstring | nullGl of the item.
foundboolean | nullWhether found.
statusstring | nullStatus of the item.
no_offers_foundboolean | nullWhether no offers found.
messagestring | nullMessage of the item.
titlestring | nullTitle of the item.
brandstring | nullBrand name.
urlstring | nullCanonical URL of the scraped item.
thumbnailstring | nullThumbnail image URL.
currencystring | nullCurrency code of the price.
checked_atstring | nullWhen the checked happened.
age_hoursnumber | nullAge hours of the item.
offers_countinteger | nullNumber of offers.
offersarray | nullOffers values collected for the item.
fetched_atstring | nullWhen the page was fetched.
lowest_total_pricenumber | nullLowest total price of the item.
highest_total_pricenumber | nullHighest total price of the item.

๐Ÿงพ Offer Object Fields

Each entry inside the offers array describes a single seller listing:

FieldDescription
sellerNameName of the merchant making the offer
sellerReferenceReference URL for the merchant or the offer
priceItem price excluding shipping
shippingPriceShipping cost, where one is stated
totalPriceItem price plus shipping
conditionStated condition of the item, such as New
availabilityStock 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 ApifyClient
client = 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 found value of false.
  • Keep one country per run. Mixing markets in a single job makes the dataset harder to reason about; separate runs per country value keep both the input and the resulting time series clean.
  • Batch sensibly. Very large single blocks in products produce long runs. Splitting a large catalogue into several runs makes failures easier to isolate and reruns cheaper.
  • Use force sparingly. Forcing a refresh on every product on every run removes the benefit of stored results. Reserve it for investigations and for products where age_hours exceeds your tolerance.
  • Store checked_at with 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_found before 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.