Guide
How to export any Shopify store's products to CSV
7 min read
Shopify's built-in product export only works on your own store. But if you want to pull a competitor's (or any public) Shopify catalog into a spreadsheet - every product, variant, price and SKU - you can, using the public products.json endpoint, with no app and no API key. Here's how to do it, convert it to CSV or Excel, and what you can and can't capture.
Why you can export another store's products
Every public Shopify store publishes its catalog as JSON at /products.json - the same data its storefront uses. Because it's public and needs no login, you can read it and save it to a file. (This is different from Shopify's Admin export, which only the store owner can run.)
If you've never used it, start with our complete guide to the Shopify products.json endpoint - this article assumes you know the basics and focuses on getting the data into a spreadsheet.
Step 1: Grab the raw JSON
Open the store's products.json in your browser to confirm it works, asking for the maximum 250 products per page:
https://examplestore.com/products.json?limit=250&page=1
Step 2: Flatten it to one row per variant
A product can have many variants (sizes, colors), and each variant has its own price and SKU. For a useful spreadsheet you want one row per variant, not per product. These are the columns worth exporting:
- Product title, handle, vendor, product_type
- Variant title (e.g. 'Large / Black'), SKU
- price and compare_at_price (so you can see what's on sale)
- available (in / out of stock)
- created_at / updated_at (to spot new and recently-changed items)
- Product URL: https://store.com/products/{handle}
Step 3: The script (Python)
This small script paginates through the whole catalog and writes a variant-level CSV you can open in Excel or Google Sheets. Change the domain at the top.
import csv, requests
STORE = 'https://examplestore.com'
HEADERS = {'User-Agent': 'Mozilla/5.0'}
rows, page = [], 1
while True:
r = requests.get(f'{STORE}/products.json',
params={'limit': 250, 'page': page}, headers=HEADERS)
products = r.json().get('products', [])
if not products:
break
for p in products:
for v in p['variants']:
rows.append({
'product': p['title'], 'handle': p['handle'],
'vendor': p.get('vendor'), 'type': p.get('product_type'),
'variant': v['title'], 'sku': v.get('sku'),
'price': v.get('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='', encoding='utf-8') as f:
w = csv.DictWriter(f, fieldnames=rows[0].keys())
w.writeheader(); w.writerows(rows)
print(f'Exported {len(rows)} variants to catalog.csv')No-code options
If you'd rather not run a script, there are lighter options for a one-off export:
- Browser + a JSON-to-CSV converter: open products.json, copy the output, paste into a free online JSON-to-CSV tool. Fine for small catalogs; messy for nested variants.
- Google Sheets + Apps Script: a short UrlFetchApp script can pull products.json straight into a sheet. (Plain IMPORTDATA / IMPORTXML can't parse JSON, so you need Apps Script.)
- A browser extension that exports a page's JSON - quick, but still one page at a time.
Can you re-import this CSV into your own Shopify store?
A common follow-up: can you take the export and bulk-import it into your own store? Technically yes, but the file needs reshaping first. Shopify's product importer expects its own column names - Handle, Title, Body (HTML), Vendor, Variant Price, Variant SKU, Image Src and so on - so you'd map the products.json fields onto Shopify's import template before uploading, not feed in the raw columns above.
Two things to watch. Images come through as URLs in the Image Src column, and Shopify fetches each one at import time, so the source images have to stay publicly reachable or they simply won't import. And re-publishing another store's product photos and descriptions as your own is a copyright problem - use an export to analyze a catalog, not to clone one.
What you can't export
Set expectations: the public endpoint only has published storefront data. You will NOT get exact inventory counts (only an in/out-of-stock flag), draft or unpublished products, or any sales, cost, or revenue figures. Those live in the Admin API that only the store owner can use.
A one-time export vs ongoing tracking
An export is a snapshot - the catalog as it is right now. It won't tell you when a price drops next week, when an item sells out, or when a new product launches. For that you'd re-export on a schedule and diff each file against the last.
Shop Sentry does that automatically: it reads the same public catalog, tracks every product and variant over time, and alerts you to changes - and on the Agency plan you can export the tracked data and change history to CSV or pull it via the REST API whenever you want.
Frequently asked questions
Can I export a competitor's Shopify products without an app?
Yes. The public products.json endpoint returns the full catalog with no app and no API key. You just fetch it (paginating 250 at a time) and save it as CSV or JSON.
Does this include prices and variants?
Yes - each variant's price, compare_at_price (sale 'was' price), SKU, options and availability are all in products.json. That's exactly what you'd put in the spreadsheet.
Can I export inventory quantities?
No. You only get a true/false 'available' per variant, never the exact stock count. Exact inventory is private to the store owner.
How do I export more than 250 products?
Loop through pages: ?limit=250&page=1, then page=2, page=3, and so on until a page returns an empty list. The script above does this automatically.
Can I import the exported CSV into my own Shopify store?
Yes, but you first remap the columns to Shopify's import template (Handle, Title, Variant Price, Image Src, and so on), and the image URLs must stay publicly reachable for Shopify to fetch them at import. Don't republish a competitor's photos or copy as your own - that's a copyright issue.
