Skip to content

Get product prices and stock from a store's schema.org data

Many online stores publish each product’s price and stock status as schema.org data, so Google can show them in search results. That data sits in the page’s HTML as JSON, which makes it easier and steadier to read than the visible page. This guide shows how to check a store yourself, how to get the data through a product data API, and how often stores really fill each field.

Run this on any product page to see its schema.org data. It needs only curl and Python. Check the store’s robots.txt and terms first.

Terminal window
curl -s -A "Mozilla/5.0 (compatible; price-check)" "https://www.adafruit.com/product/6534" | python3 -c '
import json, re, sys
for block in re.findall(r"<script[^>]*application/ld\+json[^>]*>(.*?)</script>", sys.stdin.read(), re.S):
data = json.loads(block)
for item in data if isinstance(data, list) else [data]:
if item.get("@type") == "Product":
offer = item["offers"]
print(item["name"], "|", offer["price"], offer["priceCurrency"], offer["availability"])
'

On 2026-11-05 that printed:

Adafruit Si5351C 8 Channel TCXO Clock Generator - 2.5KHz-200MHz | 14.95 USD http://schema.org/InStock

It’s a sketch for one store’s shape. Other stores nest products in @graph, list several offers, use lowPrice, or leave fields out, and some only add the data with JavaScript. You can also paste a URL into the Schema Markup Validator.

Product Scraper API - Prices & Stock from Any Store handles those shapes and returns one format across stores, so it works as an e-commerce product API or a price API for any store that publishes this data:

Terminal window
curl -s -X POST "https://api.apify.com/v2/acts/rocketyard~product-schema-scraper/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H 'content-type: application/json' \
-d '{"startUrls":[{"url":"https://www.adafruit.com/product/6534"},{"url":"https://www.muji.us/products/body-fit-cushion"}]}'

It costs $1.50 per 1,000 results plus a small start fee per run. You can also run it from a form without code. To cover a whole catalog, turn on Crawl the website with a start page and a Link pattern such as /products/.

We ran the Actor’s extractor on 16 product pages from 9 online stores on 2026-11-05, counting pages with a product record:

Field Filled
name 100%
description 81.3%
sku 75%
gtin 0%
brand 62.5%
image 100%
price 100%
priceCurrency 100%
availability 68.8%
ratingValue 31.3%
reviewCount 31.3%
category 31.3%

Price and currency came back on every page with a record. Stock status is less common: where it is missing, the markup doesn’t publish it, so the field is null rather than a guess. No page in this test published a GTIN.

Pages with each field, per store:

Store Pages Price Stock SKU Brand
Adafruit 3 3 3 3 0
Zappos 3 3 3 3 3
Allbirds 2 2 2 2 2
MUJI US 2 2 2 2 2
Decathlon US 2 2 0 0 2
Death Wish Coffee 1 1 1 1 1
SparkFun 1 1 0 1 0
IKEA US 1 1 0 0 0
Apple 1 1 0 0 0

We tried 14 stores and 9 returned records. The other 5:

  • ColourPop: HTTP 429 on every page
  • Kylie Cosmetics: HTTP 429 on every page
  • bol.com: HTTP 403 on every page
  • Brooklinen: no Product markup in the HTML of the 2 pages it served
  • Back Market: connection failed

That was one plain pass from one address with 4 seconds between pages and no retries, honouring robots.txt, and we also hit rate limits on some pages of stores listed above. The Actor retries rate limits, but it doesn’t bypass blocks: what stays blocked comes back as a free error item. Pages that add the data only with JavaScript and pages behind a login aren’t read.

Each run reads prices as they are now and keeps no history. To track them, schedule a run and compare results by url and price.