How to Scrape Google Shopping Prices
A practical guide to scraping Google Shopping prices with Python: pull every seller's price for a product by EAN, build a price-history database, and automate monitoring and alerts across 40+ countries.
Just want the prices? The Google Shopping Scraper API returns every seller's live price for a product by EAN, across 40+ countries, in one JSON call.
Why scrape Google Shopping prices?
Google Shopping shows what every merchant charges for a product side by side, which makes it the single best place to read the market price of anything. For a retailer or brand, scraping those prices unlocks:
- Competitor price monitoring — know exactly where you sit against every other seller
- Repricing — feed live market prices into a repricing engine and react automatically
- MAP compliance — catch sellers breaking your minimum advertised price
- Price history — build a time series to spot trends, promotions, and seasonality
- Cross-border pricing — compare the same product across countries to find margin gaps
This guide is price-focused. If you want the broader tutorial covering search, matching, variants, and reviews, start with How to Scrape Google Shopping with Python.
The catch: prices are tied to the right product, not the barcode
Before you can track a price you have to be sure you are tracking the right product. Google Shopping keys products by an internal catalog ID (a "Google Shopping SKU"), not by EAN, and a raw barcode search often returns the wrong item or nothing at all.
ShoppingScraper is the only provider that translates a raw EAN/GTIN into the correct Google Shopping catalog ID (SKU). That means the prices you scrape belong to the exact product you asked for, not a lookalike, which is the whole point when you are repricing against them. You send the barcode, you get the right product's prices back.
Prerequisites
- Python 3.9+
- httpx —
pip install httpx - A ShoppingScraper API key — get 100 free credits at shoppingscraper.com
Store the key in an environment variable, never in your code:
export SHOPPINGSCRAPER_API_KEY="your-api-key-here"Get every seller's price for a product
The /offers endpoint takes an EAN and a Google Shopping site and returns each seller's price, shipping cost, and total.
import os
import httpx
API_KEY = os.environ["SHOPPINGSCRAPER_API_KEY"]
BASE_URL = "https://api.shoppingscraper.com"
def get_prices(ean: str, site: str = "shopping.google.nl") -> dict:
"""Return every seller's price for a product on Google Shopping."""
response = httpx.get(
f"{BASE_URL}/offers",
params={"site": site, "ean": ean},
headers={"x-api-key": API_KEY},
timeout=httpx.Timeout(connect=5.0, read=60.0, write=5.0, pool=5.0),
)
response.raise_for_status()
return response.json()
data = get_prices("0194253397052", site="shopping.google.nl")
offers = sorted(data.get("offers", []), key=lambda o: float(o.get("totalPrice", "inf")))
print(f"{data.get('title')} ({len(offers)} sellers)\n")
for o in offers:
print(f" {o['sellerName']:<20} {o['totalPrice']} {data.get('currency', '')}"
f" ({o.get('availability', '')})")
if offers:
print(f"\nCheapest: {offers[0]['sellerName']} at {offers[0]['totalPrice']} {data.get('currency', '')}")The offers come back with price, shippingPrice, and totalPrice, so you can rank sellers on the real landed cost, not just the headline number.
Track price history over time
A single price is a snapshot. To monitor prices you store every observation with a timestamp and build a history. This script writes to SQLite so you can query trends later.
import os
import sqlite3
from datetime import datetime, timezone
import httpx
API_KEY = os.environ["SHOPPINGSCRAPER_API_KEY"]
BASE_URL = "https://api.shoppingscraper.com"
DB_PATH = "google_shopping_prices.db"
def init_db() -> None:
conn = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA journal_mode=WAL")
conn.execute("""
CREATE TABLE IF NOT EXISTS price_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ean TEXT NOT NULL,
site TEXT NOT NULL,
seller TEXT,
total_price REAL,
currency TEXT,
scraped_at TEXT NOT NULL
)
""")
conn.execute("CREATE INDEX IF NOT EXISTS idx_ean_time ON price_history (ean, scraped_at)")
conn.commit()
conn.close()
def record_prices(ean: str, site: str = "shopping.google.nl") -> int:
resp = httpx.get(
f"{BASE_URL}/offers",
params={"site": site, "ean": ean},
headers={"x-api-key": API_KEY},
timeout=httpx.Timeout(connect=5.0, read=60.0, write=5.0, pool=5.0),
)
resp.raise_for_status()
data = resp.json()
now = datetime.now(timezone.utc).isoformat()
conn = sqlite3.connect(DB_PATH)
rows = 0
for o in data.get("offers", []):
conn.execute(
"""INSERT INTO price_history (ean, site, seller, total_price, currency, scraped_at)
VALUES (?, ?, ?, ?, ?, ?)""",
(ean, site, o.get("sellerName", ""),
float(o["totalPrice"]) if o.get("totalPrice") else None,
data.get("currency", ""), now),
)
rows += 1
conn.commit()
conn.close()
return rows
init_db()
for ean in ["0194253397052", "8710103990741"]:
n = record_prices(ean)
print(f"Recorded {n} offers for {ean}")Schedule it with cron to build history automatically:
# Run every hour
0 * * * * cd /path/to/project && source .venv/bin/activate && python price_monitor.pyQuery the lowest price per day once you have a few runs stored:
SELECT date(scraped_at) AS day, MIN(total_price) AS lowest
FROM price_history
WHERE ean = '0194253397052'
GROUP BY day
ORDER BY day;Set a price alert
With history in place, alerting is a simple comparison: if today's lowest price drops below your threshold (or below your own price), fire a notification.
def lowest_price(ean: str, site: str = "shopping.google.nl") -> float | None:
data = get_prices(ean, site)
prices = [float(o["totalPrice"]) for o in data.get("offers", []) if o.get("totalPrice")]
return min(prices) if prices else None
def check_alert(ean: str, your_price: float) -> None:
market_low = lowest_price(ean)
if market_low is not None and market_low < your_price:
print(f"ALERT: {ean} undercut. Market low {market_low} < your price {your_price}")
check_alert("0194253397052", your_price=279.0)Wire the alert body to email, Slack, or a webhook and you have a working competitor-price watchdog. For catalog-wide monitoring without running your own cron, the built-in schedulers do the recurring collection for you.
Compare prices across countries
The same EAN resolves across Google Shopping's country domains, so you can watch the same product in every market you sell in. See the multi-country section of the Python guide for the concurrent pattern that runs all countries at once.
Next steps
- Read the full tutorial — How to Scrape Google Shopping with Python covers search, EAN to SKU matching, variants, and reviews
- Explore the endpoints — the Google Shopping Scraper API documents offers, match, search, variants, and reviews
- Automate it — the price-monitoring schedulers run recurring checks hands-free
- Scale to a full catalog — the migration guide documents the batch Channel API for up to 50,000 EANs at a time
CTO & Co-founder
Full-stack engineer specializing in web scraping, API design, and AI applications for e-commerce. Built ShoppingScraper's infrastructure processing 1M+ daily product lookups.