Price Drop Alerts with a Shopping API
A price-drop alert is a four-step loop: poll a product query on a schedule, read the numeric extractedPrice from each listing, compare it to your stored baseline, and notify when it falls. The Shopping API supplies everything the loop needs in one call — price, currency, merchant, and a stable product URL to key the alert on.
This guide walks through the pattern with a tested Python script and honest cost math, so you know what a real price-watch system costs before you build it.
TL;DR: Poll /api/shopping for your watchlist, use extractedPrice (a number, not a string) to compare, store a baseline per product, and fire when the current price drops below it. Skip null prices. At the Scale tier a 1,000-keyword daily sweep costs a few cents a day.
Table of Contents
- The price-drop loop
- Price data the API gives you
- Working Python: a price watcher
- Cost math for a real watchlist
- Honest limits
- FAQ
The price-drop loop
Every price-watch system, from a hobby script to an enterprise repricer, is the same four steps:
- Poll. On a schedule, query each product you watch.
- Normalize. Turn the display price into a number you can compare.
- Compare. Against the last price you stored for that product.
- Alert. When the current price drops below the baseline (or your threshold).
The hard part is never the loop — it is getting a clean, comparable price reliably. That is where the API earns its keep.
Price data the API gives you
Each listing in the Shopping API response includes both a display price string and a numeric extractedPrice. The numeric one is what your comparison logic should use:
{
"title": "Sony WF-1000XM6",
"price": "$299.99", // display string
"extractedPrice": 299.99, // number, ready for math
"currency": "USD",
"merchant": "Best Buy",
"url": "https://www.bestbuy.com/product/sony-wf1000xm6-..."
}
Keying alerts on url (the merchant product URL) keeps the same product stable across polls. Keying on the title alone is fragile — two merchants can sell "Nike Vomero 18" at different prices, and that is exactly the difference you want to catch.
Working Python: a price watcher
Here is a complete, runnable watcher. It keeps baselines in a JSON file, polls a watchlist, and prints an alert for every product whose price dropped since the last run. Wire the print to your email, Slack, or push channel.
Replace sk_live_your_key with your key from the dashboard.
import json
import os
import time
import requests
API_KEY = "sk_live_your_key"
BASE_URL = "https://apiserpent.com/api/shopping"
STATE_FILE = "price_baselines.json"
def fetch_prices(query):
resp = requests.get(
BASE_URL,
params={"q": query, "engine": "yahoo", "num": 20},
headers={"X-API-Key": API_KEY},
timeout=60,
)
resp.raise_for_status()
out = {}
for item in resp.json()["results"]["shopping"]:
price = item.get("extractedPrice")
if price is None: # Yahoo didn't show a price this poll
continue
out[item["url"]] = {
"title": item["title"],
"price": price,
"merchant": item.get("merchant"),
}
return out
def load_state():
if os.path.exists(STATE_FILE):
return json.load(open(STATE_FILE))
return {}
def save_state(state):
json.dump(state, open(STATE_FILE, "w"), indent=2)
WATCHLIST = ["nike running shoes", "sony headphones", "iphone 15 case"]
state = load_state()
for query in WATCHLIST:
for url, listing in fetch_prices(query).items():
previous = state.get(url, {}).get("price")
current = listing["price"]
if previous is not None and current < previous:
drop = previous - current
print(f"PRICE DROP ({drop:.2f}) {listing['title']} "
f"${current:.2f} was ${previous:.2f} @ {listing['merchant']}")
state[url] = listing
save_state(state)
print(f"\nWatched {len(state)} products. Baselines saved to {STATE_FILE}.")
Run it once to seed baselines, then again later — any product whose extractedPrice fell prints a PRICE DROP line. The script skips listings with no price instead of treating null as a catastrophic drop to zero.
Cost math for a real watchlist
Here is what a price-watch system actually costs on the Shopping API, billed per 1,000 calls (no page multiplier, no subscription):
| Tier | Per 1,000 calls | 500 keywords, 1×/day | 5,000 keywords, 1×/day |
|---|---|---|---|
| Default | $0.60 | $0.30/day | $3.00/day |
| Growth | $0.06 | $0.03/day | $0.30/day |
| Scale | $0.03 | $0.015/day | $0.15/day |
At the Scale tier a 500-keyword daily sweep is a cent and a half a day. Even hourly checks of a 200-product watchlist (4,800 calls/day) stay well under a dollar a day. See the pricing page for the current full table.
Honest limits
- No history built in. The API returns the current price; you store the baseline. Your database is the history.
- Null prices happen. A share of listings appear without a displayed price on a given poll. Skip and retry them next round.
- Short rail. One query returns roughly a dozen products. For a broad catalog, split it across many queries.
- Source freshness. Prices are as fresh as the product rail at read time. For true real-time marketplaces, a marketplace's own API or feed is the better tool.
Next step: pull a key from the dashboard, try the Shopping API in the playground, then adapt the watcher above. Pair it with price monitoring, e-commerce price intelligence, or the cross-engine Google vs Yahoo comparison.
FAQ
How do price drop alerts work with a shopping API?
Poll a query on a schedule, read the numeric extractedPrice, compare it to the baseline you stored for that product URL, and alert when it falls below a threshold.
What is the cheapest way to track price drops?
Shopping calls cost $0.00003 each at the Scale tier. A 1,000-keyword catalog checked once a day is a few cents a day, so even hourly sweeps of a small watchlist are affordable.
Why is the price sometimes missing?
The product rail hydrates prices asynchronously, so a small share of listings can lack a displayed price at read time. Skip nulls in your loop and log them; never treat a missing price as a zero.
Can I get historical price data?
No API returns the prices it showed yesterday. You build history by storing baselines as you poll. The API supplies the current price; your store supplies the past.
Does engine=yahoo vs engine=google matter for price alerts?
Both engines return price and extractedPrice. Query the same product on both for a cross-engine view of the lowest offer — see the Google vs Yahoo comparison for the pattern.


