Compare product prices across merchants with the Google Shopping API
Parse the price string yourself, discard the parts of the payload you do not need, and query narrow enough to get like-for-like offers. Tested in August 2026.

You want one product’s price across every merchant that sells it, for a comparison page or a repricing job that rechecks a list of SKUs a few times a day. Opening one browser tab per competitor does not scale past a handful of products, and it is exactly the kind of repetitive lookup a script should be doing instead.
What /v1/shopping returns
Send a query to /v1/shopping and you get shopping_results, a list where each entry has a title, a source (the merchant name), a display price string like "$26.99", an extracted_price number, a product_id, and several fields you will not use: thumbnail, original_thumbnail, page_token, immersive_url. It costs 10 credits per call.
A broad query gets you whatever shares a keyword
How narrow your query is decides how useful the results are. We called the endpoint with the two-word query “web scraping api” and got 40 results back. Only a couple were software or data products; most of the rest were tools and supplies whose title or brand happened to contain the same words, including a beekeeping tool line called “APIs Tactical.” Google Shopping matches on the text of the query, not on your intent, so a broad category term pulls in anything that matches the words, not everything relevant to the category you had in mind.
For a comparison page or a repricing job, query the exact product name or model number, the way you would type it into a shopping search expecting one specific result. Then check that each row’s title actually looks like your product before treating its price as a competing offer, because nothing in the response guarantees every row is on topic.
Parse the price string yourself
extracted_price looks like the safe field, a plain number instead of a string with a currency symbol attached. In our sample it was wrong once out of 40: a listing displayed as "$1,400.00" came back with extracted_price set to 1.4, off by a factor of a thousand, almost certainly the comma getting misread. One bad row in forty is enough to break a repricing decision if nothing catches it. Parse the display string yourself with a regex, and treat extracted_price as a hint at best.
import re
import requests
API_KEY = "faf_live_..." # your FastAF key
def price_to_float(display):
digits = re.sub(r"[^0-9.]", "", display or "")
return float(digits) if digits else None
resp = requests.get(
"https://api.fastaf.co/v1/shopping",
params={"query": "web scraping api"},
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=60,
)
resp.raise_for_status()
offers = [
{
"merchant": item["source"],
"price": price_to_float(item["price"]),
"title": item["title"],
}
for item in resp.json()["shopping_results"]
]
offers.sort(key=lambda o: (o["price"] is None, o["price"]))
for o in offers[:5]:
print(f'{o["price"]:>8.2f} {o["merchant"]:<24} {o["title"]}')
On our sample the five cheapest offers were an alcohol prep pad and four pieces of beekeeping equipment, all under $8, none of them a web scraping product. That is not a parsing bug, it is what a two-word query actually returns: proof that the query needs to be specific before this list means anything for a comparison page.
Discard almost all of it
The sample response we tested against was 530,728 bytes for 40 results. Field by field, thumbnail and original_thumbnail alone account for about 80% of those bytes: base64-encoded images a repricing job has no use for. page_token and immersive_url are internal Google references, only useful for rebuilding the Google Shopping page itself. None of it belongs in a database row that just needs to answer what a product costs right now.
The list comprehension above does the discarding on its own: it keeps three fields per offer and lets the rest of each shopping_results entry get garbage collected. Across a list of SKUs checked several times a day, the difference between that and storing every response verbatim adds up fast.
What it costs
A call is 10 credits, so checking 100 products once a day is 1,000 credits, about 30,000 a month: the $29 Growth pack’s 75,000 credits cover two and a half months of it. Failed requests are not charged.
Start with the free tier, 500 credits and no card, good for 50 calls: enough to see what merchant coverage actually looks like for the specific products you care about before building a repricing job around it.