Shopify Product Scraper — Catalog, Variants, Prices & Discounts avatar

Shopify Product Scraper — Catalog, Variants, Prices & Discounts

Pricing

from $10.00 / 1,000 products

Go to Apify Store
Shopify Product Scraper — Catalog, Variants, Prices & Discounts

Shopify Product Scraper — Catalog, Variants, Prices & Discounts

Export the full product catalog of any Shopify store as a clean, spreadsheet-ready table. Variants, prices, compare-at prices, calculated discount %, stock status, SKUs and images.

Pricing

from $10.00 / 1,000 products

Rating

0.0

(0)

Developer

tidyfeed

tidyfeed

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Paste a store address. Get its entire catalog as a spreadsheet-ready table.

Every product, every variant, with prices as real numbers, a calculated discount %, stock status, SKUs and images. Add several stores to compare competitors side by side in one run.

No API key. No login. No Shopify partner account. No proxies.


The difference, on a real product

Shopify publishes its product feed in a shape that is awkward to use. Here is what a live Allbirds variant looks like in the raw feed:

{
"options": [{ "name": "Size", "position": 1 }], ← name lives up here
"variants": [{
"option1": "10.5", ← value lives down here
"price": "91.00", ← a string
"compare_at_price": "130.00" ← another string
}]
}

Three problems: the option name and its value are in different objects, prices are text rather than numbers, and there is no discount figure anywhere.

Here is the same variant as this actor returns it:

option1Nameoption1ValuepricecompareAtPricediscountPercentonSaleavailable
Size10.59113030truetrue

Paste that into a spreadsheet and it sorts, filters and sums immediately. No formulas, no lookup table, no cleanup pass.


What you get

One row per variant, so every size and colour carries its own price and stock flag.

ColumnExample
storeDomainallbirds.com
productTitleWomen's Strider - Rugged Beige
option1Name / option1ValueSize / 10.5
option2Name / option2ValueColour / Navy — blank when a product has one option
skuA11848W105
price91
compareAtPrice130
discountPercent / onSale30 / true
availabletrue
vendor, productTypeAllbirds, Shoes
tagsthe store's own tags, comma-joined
productUrl, imageUrl, imageCountdirect links
publishedAt, createdAt, updatedAtISO timestamps

Prefer one row per product? Switch Row format and you get a price range, variant count and combined SKU list instead.


What it costs

One charge per product returned. Every variant of that product is included at no extra cost.

That is the same billing unit the rest of this category uses, so the price comparison is direct — the difference is what arrives for the money.

Your runYou pay
A 200-product store$2.01
A 1,000-product catalog$10.01
Three competitors at 500 products each$15.01

Products your filters exclude are not billed. Set Minimum discount % to 50, point it at a 250-product catalog, and if 87 products qualify you are charged for 87 — not 250.


It follows headless stores to their real shop

A growing number of brands run a custom front end — Next.js, Hydrogen, a bespoke storefront — on their own domain. Ask brand.com/products.json and you get a web page instead of a feed, which is where most scrapers stop and report "not a Shopify store".

These stores still name their Shopify shop in their own markup. This actor reads that address and pulls the catalog from there.

kotn.com → custom front end → reads kotn-ss15.myshopify.com → 250 products
mejuri.com → custom front end → reads mejuri-us.myshopify.com → 250 products

Both of those return nothing on the brand domain. Both come back with a full catalog here.


Typical uses

  • Competitor price monitoring — schedule a daily run across several stores and watch prices move.
  • Sale tracking — set Minimum discount % to 20 and see only what a competitor has actually marked down.
  • Catalog migration or audit — pull an entire catalog into a spreadsheet before a replatform.
  • Assortment research — compare how two brands price the same product type.
  • Dropshipping and sourcing — export a supplier's catalog with SKUs and stock.
  • Feeding an AI agent — callable over the API and through MCP, so Claude, Cursor and other assistants can pull live catalog data mid-task.

Input

FieldWhat it does
Shopify store URLsOne or more addresses. A bare domain, a homepage, a product page or a .myshopify.com address all work.
Max products per storeStops after N products per store. Default 1000.
Row formatOne row per variant (default), or one row per product with a price range.
Include product descriptionAdds the description as plain text with the HTML stripped out. Off by default.
Skip sold-out itemsKeeps only what is currently in stock.
Minimum discount %Keeps only items discounted by at least this much.
{
"storeUrls": ["https://gymshark.com", "allbirds.com"],
"maxProductsPerStore": 1000,
"outputMode": "variant",
"onlyAvailable": true,
"minDiscountPercent": 20
}

That run returns every in-stock item discounted 20% or more, across both stores.


How it works

Shopify serves a public product feed at /products.json on every storefront. This actor reads that feed, walks it 250 products at a time, and reshapes the result into a flat table.

Because it uses the store's own public feed:

  • it is fast — a 1,000-product catalog finishes in well under a minute,
  • it needs no proxies — nothing to configure, nothing extra to pay for,
  • it does not break when a theme changes — there is no HTML parsing involved.

Runs are resilient across stores: if one address fails, the others carry on and the run still succeeds, with a per-store line saying exactly what happened and why.


Honest limits

Worth knowing before you run it:

  • Password-protected and pre-launch stores return nothing. There is no public feed to read.
  • A handful of stores disable the feed. Rare, but it happens; the run reports which stores came back empty and why.
  • A few brand domains sit behind bot protection that challenges every request. The run reports those instead of failing, and the store's .myshopify.com address usually works in their place.
  • Currency is not published in the feed. Prices are in the store's own default currency.
  • Inventory counts are not published either — Shopify exposes an in-stock/out-of-stock flag, not a quantity.
  • Non-Shopify sites are detected and skipped with a clear message rather than a failed run.

Output example

{
"storeDomain": "allbirds.com",
"productTitle": "Women's Strider - Rugged Beige (Stony Cream Sole)",
"handle": "womens-strider-rugged-beige",
"productUrl": "https://allbirds.com/products/womens-strider-rugged-beige",
"vendor": "Allbirds",
"productType": "Shoes",
"sku": "A11848W105",
"option1Name": "Size",
"option1Value": "10.5",
"price": 91,
"compareAtPrice": 130,
"discountPercent": 30,
"onSale": true,
"available": true,
"imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/A11847…jpg",
"imageCount": 5,
"updatedAt": "2026-08-21T04:54:55-07:00"
}

Export as CSV, Excel, JSON or XML, or pull it straight from the API.


Scheduling

Prices change. Set a schedule to run this daily or weekly, and each run stores a dated snapshot you can compare — that is all a price-monitoring pipeline really needs.


This actor reads only data that a Shopify store publishes publicly, at an address the store itself serves to anyone. It collects no personal data, requires no login, and bypasses no access control. You remain responsible for how you use the exported data.


Questions, or a store that behaves oddly? Open an issue on the actor — issues are read and answered.