Shopify Products Scraper & Price Monitor avatar

Shopify Products Scraper & Price Monitor

Pricing

Pay per event

Go to Apify Store
Shopify Products Scraper & Price Monitor

Shopify Products Scraper & Price Monitor

Scrape every product from any Shopify store, custom domains included: prices, compare-at prices, discounts, SKUs, variants, stock status and images. One row per product or per variant. Price monitor mode returns only new, changed and removed products. $1 per 1,000 products.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Joshua White

Joshua White

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Scrape every product from any Shopify store, custom domains included: titles, prices, compare-at ("was") prices, discounts, SKUs, variants, stock status, images, vendors and tags. Or turn on the price monitor and get only the products whose price or stock changed since the last run. A Shopify scraper and competitor price tracker in one, with no browser, no login and no proxies.

Try it in one click: the input is prefilled with Allbirds and ColourPop's lipstick collection (50 products each). Apify's free plan covers about 5,000 products a month.

What Shopify product data do you get?

  • The whole catalog, checked against the store's own product count. Tested on 11 stores up to 10,346 products (Gymshark): every count matched exactly; 234 of 234 spot-checked variants matched on price.
  • Prices you can sort by: price, compare-at price, onSale, discountPercent, per product and per variant, as numbers in the store's currency.
  • One row per product or one row per variant (size/color, SKU, price, availability flat, ready for a spreadsheet).
  • Stock levels and barcodes (optional) when the store exposes them.
  • Collections or single products: paste a collection or product URL to read only that.

How to scrape a Shopify store in 3 steps

  1. Add store URLs: allbirds.com, a collection like https://colourpop.com/collections/lips, or a product page.
  2. Optional: One row per variant, Max products per store, collection filters, stock levels, or the price monitor.
  3. Click Start, then download CSV, Excel or JSON, or read it through the API.

How much does it cost to scrape Shopify?

$1 per 1,000 products, so Apify's $5 monthly free credit covers about 5,000 products. In monitor mode you pay only for new, changed or removed products; unchanged products are free. Stores that fail (not Shopify, password-protected, feed turned off, domain that does not resolve) are free. A 1,000-product competitor checked daily, with about 20 changes a day, costs about $0.60 a month after the first run.

Input example

{
"startUrls": ["https://www.allbirds.com", "https://colourpop.com/collections/lips"],
"outputMode": "products",
"maxProductsPerStore": 50,
"includeInventory": false
}

This reads up to 50 products per store (100 in all, about $0.10). Set maxProductsPerStore to 0 for whole catalogs; Allbirds alone has about 700 products.

Output example

One row per product (variant list and images shortened):

{
"store": "www.allbirds.com",
"storeName": "Allbirds",
"currency": "USD",
"productId": 7340901859408,
"handle": "womens-allbirds-flip-flop-dusty-pink",
"title": "Women's Allbirds Flip Flop - Dusty Pink",
"url": "https://www.allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
"vendor": "Allbirds",
"productType": "Shoes",
"tags": ["allbirds::gender => womens", "allbirds::material => sugar"],
"price": 25,
"priceMax": 25,
"compareAtPrice": 50,
"onSale": true,
"discountPercent": 50,
"available": true,
"variantsCount": 7,
"availableVariantsCount": 1,
"options": [{ "name": "Size", "values": ["5", "6", "7", "8", "9", "10", "11"] }],
"variants": [
{
"variantId": 42146889039952,
"title": "5",
"sku": "A12513W050",
"price": 25,
"compareAtPrice": 50,
"onSale": true,
"discountPercent": 50,
"available": false,
"option1": "5",
"option2": null,
"option3": null,
"grams": 455,
"requiresShipping": true,
"taxable": true,
"imageUrl": null,
"url": "https://www.allbirds.com/products/womens-allbirds-flip-flop-dusty-pink?variant=42146889039952",
"position": 1,
"updatedAt": "2026-10-05T18:53:32.000Z"
}
],
"imageUrl": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345",
"images": ["https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345"],
"descriptionText": "Sun on your feet. Comfort underneath. Light, easy, and made for warm weather...",
"descriptionHtml": "<p>Sun on your feet. Comfort underneath...</p>",
"publishedAt": "2026-09-25T23:58:13.000Z",
"createdAt": "2026-03-27T21:03:50.000Z",
"updatedAt": "2026-10-05T18:53:32.000Z",
"collection": null,
"scrapedAt": "2026-10-05T18:53:29.584Z"
}

With One row per variant, each row has the product fields plus variantId, variantTitle, sku, price, compareAtPrice, onSale, discountPercent, available, option1Name/option1Value (up to 3 options), grams, variantImageUrl, variantUrl, and the product's productPriceMin/productPriceMax. With stock levels on, inventoryQuantity and barcode are added (per variant, and a product total when every variant's is known).

FieldMeaning
priceProduct rows: the lowest variant price. Variant rows: that variant's price. A number in currency.
compareAtPriceThe "was" price the store shows crossed out. null when there is none.
onSale, discountPercenttrue when a variant's price is below its compare-at price; the largest discount in percent.
availableWhether it can be bought now (product rows: any variant).
currencyThe store's own currency, from its shop information.
collectionThe collection the product was found in, when you read collections.

Missing values are null, never guessed.

Run summary

Each run writes an OUTPUT record (in the Console: Storage → Key-value store): per store, the products in the store, products listed and output, monitor counts, how many variants exposed stock levels, and why a store failed.

Price-change monitor

Turn on Monitor: only new, changed and removed products and schedule the actor (for example daily).

  • The first run remembers every product. It outputs them all as new, or nothing if you turn off Output the whole catalog on the first run.
  • Later runs output only products whose price, compare-at price or stock status changed (changeType: "changed"), new products ("new") and products that disappeared ("removed").
  • Each product row gets previousPrice and a changes list with old and new values per variant. In per-variant mode you get one row per changed variant with previousPrice, previousCompareAtPrice and previousAvailable.
  • Memory is kept per state key and store URLs, so you can run several independent monitors.

Example change (per-variant mode, illustrative values):

{
"store": "shop.example.com",
"title": "Canvas Tote",
"variantId": 50020935008498,
"sku": "TOTE-01",
"price": 45,
"previousPrice": 52,
"compareAtPrice": null,
"previousCompareAtPrice": null,
"available": true,
"previousAvailable": true,
"changeType": "changed",
"url": "https://shop.example.com/products/canvas-tote"
}

Speed and limits

  • About 250 products per request. 19,040 products from 11 stores took 29 seconds in testing.
  • Stock levels need one extra request per product: about 2 products per second per store.
  • Shopify's public feed stops at 25,000 products per store or collection. For a bigger catalog the run summary says so; split it with Collections.
  • Requests are polite: at most 2 per second per store, with retries, and Crawl-delay is honored.
  • Some Shopify stores use a headless storefront (Hydrogen or a custom front end) that turns the public feed off. Those are reported as such and not charged.

Responsible use

The actor reads only the public product feeds that Shopify stores publish for every visitor. It follows each store's robots.txt and skips stores that disallow access, sends a clear User-Agent (ShopifyProductsScraper), uses no proxies, and needs no login. It collects product data only, no customer or personal data. Use the data in line with the law where you are and the stores' terms.

Ready-made examples

Each one opens this actor with the input already filled in. Click Try to run it, or change the input to fit your own list.

More tools from oldjard

Use it from an AI agent or the API

  • Minimal input: {"startUrls": ["allbirds.com"], "maxProductsPerStore": 50}. Set maxProductsPerStore to cap the work and the cost.
  • Cost: $0.001 per product returned (with all its variants). Stores that fail are free. 50 products = $0.05.
  • Run time (our runs): about 5 s for up to 100 products; 28 s for 5,570 products from 3 stores.
  • Results: the default dataset, one row per product; per-store status is the OUTPUT record in the key-value store.
  • Works over the Apify MCP server (search-actors, then call-actor) and is eligible for agentic payments (x402).

FAQ

Does it work on any Shopify store? Any store with the standard public product feed. Headless storefronts that turn the feed off (for example Hydrogen) are reported and not charged; in testing that was 3 of 18 stores.

Can I get alerts? Schedule it in monitor mode and connect Apify's Slack, email or webhook integration to the run.

How do I know a site is on Shopify? Just paste it. The actor checks, and tells you if it is not.

Why are prices in one currency? The feed gives prices in the store's own currency (shown in currency). Stores that sell in several currencies convert at checkout.

Why is inventoryQuantity null? The store hides stock levels. Many do; available still tells you whether it can be bought.

Can I track just a few products? Yes: paste their product URLs and turn on the monitor.

Changelog

  • 0.1: first release. Whole store, collections, single products; per-product or per-variant rows; stock levels; price-change monitor.