DEV Community

Siftwright Data
Siftwright Data

Posted on

How to read any Shopify store's product catalog with products.json (no API key)

Almost every Shopify store publishes its whole public catalog as JSON. There's no API key, no app and no scraping of HTML. Add /products.json to the store's domain:

https://example-store.com/products.json
Enter fullscreen mode Exit fullscreen mode

That returns the store's products, with titles, descriptions, prices, variants, SKUs, stock flags and image URLs. It's handy for competitor price checks, catalog audits, building a comparison site, or simply exporting your own store to a spreadsheet.

Here's how it works, how to page through big catalogs, and a few things to watch for.

What you get back

Each request returns {"products": [...]}. A trimmed product looks like this:

{
  "id": 7340901859408,
  "title": "Women's Flip Flop - Dusty Pink",
  "handle": "womens-flip-flop-dusty-pink",
  "body_html": "<p>Sun on your feet. Comfort underneath...</p>",
  "vendor": "Example Brand",
  "product_type": "Shoes",
  "tags": ["womens", "summer"],
  "published_at": "2026-09-25T16:58:13-07:00",
  "updated_at": "2026-10-14T14:56:02-07:00",
  "variants": [
    {
      "id": 42146889039952,
      "title": "7",
      "sku": "A12513W070",
      "price": "25.00",
      "compare_at_price": "50.00",
      "available": false
    }
  ],
  "images": [{"src": "https://cdn.shopify.com/...", "alt": null}]
}
Enter fullscreen mode Exit fullscreen mode

A few useful details:

  • price and compare_at_price are strings. A compare_at_price above price means the item is on sale.
  • available on each variant tells you whether that size or colour is in stock. You don't get stock counts.
  • handle builds the product URL: https://example-store.com/products/<handle>.
  • images[].alt is the image's alt text. null means none was set, which matters for accessibility and SEO.

Paging through the whole catalog

The default page holds 30 products. Ask for up to 250 per page and step through pages until one comes back empty:

import requests, csv

store = "https://example-store.com"
rows, page = [], 1
while True:
    r = requests.get(f"{store}/products.json", params={"limit": 250, "page": page}, timeout=30)
    products = r.json().get("products", [])
    if not products:
        break
    for p in products:
        for v in p["variants"]:
            rows.append({
                "title": p["title"], "variant": v["title"], "sku": v.get("sku"),
                "price": v["price"], "compare_at": v.get("compare_at_price"),
                "available": v.get("available"),
                "url": f"{store}/products/{p['handle']}",
            })
    page += 1

with open("catalog.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=rows[0].keys())
    w.writeheader(); w.writerows(rows)
print(len(rows), "variants saved")
Enter fullscreen mode Exit fullscreen mode

Shopify sends Access-Control-Allow-Origin: * on this endpoint, so the same request works from browser JavaScript too:

const res = await fetch("https://example-store.com/products.json?limit=250&page=1");
const { products } = await res.json();
console.log(products.length, products[0].title);
Enter fullscreen mode Exit fullscreen mode

One collection only

Every collection has its own feed:

https://example-store.com/collections/<collection-handle>/products.json
Enter fullscreen mode Exit fullscreen mode

Things to watch for

  • Some stores turn it off or sit behind a password page. Then you'll get a 404 or HTML instead of JSON.
  • Be polite. Space requests a second or two apart. Shopify rate-limits heavy traffic, and a catalog of a few thousand products only needs a handful of requests anyway.
  • It's public data only. No costs, no stock counts, no unpublished products.
  • Prices are in the store's currency. Multi-currency stores may show a different currency depending on where you request from.

Free tools if you'd rather not write code

We put three small browser tools on Hugging Face that use this same feed:

If you'd like a store's prices tracked daily, with alerts when something changes or goes on sale, email siftwright.data@gmail.com and we'll set it up for you.

Top comments (0)