Shopify Store Scraper & Price/Stock Change Monitor avatar

Shopify Store Scraper & Price/Stock Change Monitor

Pricing

Pay per event

Go to Apify Store
Shopify Store Scraper & Price/Stock Change Monitor

Shopify Store Scraper & Price/Stock Change Monitor

Export any Shopify store's full catalog from its domain, then get only what changed: new or removed products, price and stock changes. No login needed.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Randor Saar

Randor Saar

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Shopify Store Scraper & Price/Stock Change Monitor exports the full public catalog of any Shopify store from just its domain: products, variants, prices, compare-at (sale) prices, stock flags, SKUs, images and tags. Schedule it in changes mode and each run returns only what changed: new and removed products, price moves, sale changes and stock flips.

Try it in one click: the form is pre-filled with one store (colourpop.com) and 100 products. A real run of it on Apify finished in 6 seconds with 100 product rows and one free status row, for $0.085.

  • ✅ Just type a domain (gymshark.com): no login, no API key, no store access needed
  • ✅ Full catalogs, including stores above 25,000 products (Kith: 35,206 of 35,206, matching its sitemap)
  • ✅ Change monitor built in: you pay a small scan fee plus a fee per change, not for re-exporting the catalog
  • ✅ Headless stores (custom front ends) are read from their verified myshopify.com shop
  • ✅ Pay only for stores that finish: rows are held back until a store's crawl ends ok; blocked, failed or unfinished stores cost nothing
  • ✅ One free status row per store that says what worked and why
  • ✅ Collects public data only: the same product data any logged-out shopper sees, no customer data

What can you use it for?

You areYou use it to
Dropshipper or resellerWatch supplier catalogs for price and stock changes
DTC brand or repricing teamTrack competitor prices, discounts and new launches
Market or assortment analystBuild price-band and launch datasets across many stores
AI agent (Apify MCP)Answer "what does this store sell, and what changed this week?"

What data does it extract?

Product row (type: "product"), one per product (or one per variant with One row per variant):

FieldWhat it is
store, myshopifyDomain, currencyStore domain, its Shopify shop domain, and the store's default currency
productId, handle, title, urlShopify product ID, handle, title and product link
vendor, productType, tagsBrand, product type and tags
featuredImage, imageUrlsMain image and all image URLs
priceMin, priceMax, compareAtMax, onSalePrice range across variants, highest compare-at (crossed-out) price, and whether anything is discounted
available, variantsInStock, variantCountStock flag for the product and how many variants are in stock
variants[]Per variant: id, title, sku, price, compareAtPrice, available, grams, options
createdAt, publishedAtWhen the product was created and published (UTC)
likelyTestProducttrue for products that look like store test or placeholder items
inventoryQuantityInventory add-on only: total for the product and per variant, where the store makes it public (null otherwise)
descriptionHtmlOnly with Include description HTML
source, scrapedAtWhere the row came from (products.json or the Storefront API) and when

Change row (type: "change"): store, productId, variantId, handle, title, variantTitle, changeType, oldValue, newValue, changePercent, previousSeenAt, url, scrapedAt. changeType is one of added, removed, priceUp, priceDown, compareAtChanged, backInStock, outOfStock, and optionally titleChanged, tagsChanged, imagesChanged.

Store status row (type: "storeStatus", always free): status, productsFound, expectedCount and where it came from, complete, route, httpStatus, proxyUsed, error and notes.

statusMeaningCharged?
okCatalog read completely (or up to your maxProductsPerStore)Yes, its rows
notProcessedThe run stopped first, your max charge was too low for this store, or the store's time budget ran outNo
invalidInputNot a domain or URLNo
passwordProtectedThe store is behind its storefront passwordNo
blockedA bot challenge or HTTP 429 that stayed after retries and fresh proxy sessionsNo
notShopifyNot a Shopify store, or its product feed is switched offNo
errorAnything else, including a catalog well short of the store's own product countNo

How to use it

  1. Click Try for free and keep the pre-filled store, or enter your own domains (gymshark.com, https://kith.com, or a collection URL such as https://kith.com/collections/mens).
  2. Pick a mode: snapshot (all products), changes (only what changed since the last run) or snapshotWithChanges (all products, each tagged with its change).
  3. For monitoring, set a Watchlist name and schedule the Actor (for example daily). Each watchlist keeps its own baseline.
  4. Click Start, then download the results as JSON, CSV, Excel or HTML, or read them through the Apify API.

Input example

{
"stores": ["gymshark.com", "colourpop.com", "allbirds.com"],
"mode": "changes",
"watchlistName": "competitors",
"minPriceChangePercent": 2
}

Other options: collections, maxProductsPerStore, rowPerVariant, trackFields (add title, tags, images), includeInventory, includeDescriptionHtml, originFallback, resetState, maxConcurrencyPerStore, storeTimeBudgetSecs (default 1,200 s, 60 to 3,600) and proxyConfiguration (Apify datacenter proxy by default). Every field is explained in the input form.

Output examples

A product row from a real run on 24 October 2026 (tags, images and variants shortened):

{
"type": "product",
"store": "allbirds.com",
"myshopifyDomain": "weareallbirds.myshopify.com",
"currency": "USD",
"productId": "7340901859408",
"handle": "womens-allbirds-flip-flop-dusty-pink",
"title": "Women's Allbirds Flip Flop - Dusty Pink",
"vendor": "Allbirds",
"productType": "Shoes",
"tags": ["allbirds::edition => limited", "allbirds::gender => womens", "allbirds::material => sugar", "…"],
"url": "https://allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
"featuredImage": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12513_26Q2_Allbirds-Flip-Flop-Dusty-Pink_PDP_LEFT.png?v=1774646345",
"priceMin": 25,
"priceMax": 25,
"compareAtMax": 50,
"onSale": true,
"available": true,
"variantsInStock": 1,
"variantCount": 7,
"variants": [
{ "id": "42146889039952", "title": "5", "sku": "A12513W050", "price": 25, "compareAtPrice": 50, "available": false, "grams": 455, "options": ["5"] }
],
"createdAt": "2026-03-27T21:03:50Z",
"publishedAt": "2026-09-25T23:58:13Z",
"likelyTestProduct": false,
"source": "products.json",
"scrapedAt": "2026-10-24T12:50:04Z"
}

A change row from a real scheduled run (a size sold out between two runs):

{
"type": "change",
"store": "gymshark.com",
"currency": "USD",
"productId": "6806899851466",
"handle": "gymshark-gslc-stringer-sleeveless-tops-purple-aw26",
"title": "Gymshark GSLC Stringer - Cherry Purple/Soft White",
"variantId": "39799451844810",
"variantTitle": "Medium",
"changeType": "outOfStock",
"oldValue": true,
"newValue": false,
"changePercent": null,
"previousSeenAt": "2026-10-24T13:15:30Z",
"url": "https://gymshark.com/products/gymshark-gslc-stringer-sleeveless-tops-purple-aw26?variant=39799451844810",
"scrapedAt": "2026-10-24T13:39:02Z"
}

A store status row (free):

{ "type": "storeStatus", "store": "allbirds.com", "status": "ok", "route": "products.json", "productsFound": 397, "expectedCount": 397, "expectedCountSource": "meta.json", "complete": true, "proxyUsed": "apify-datacenter", "rowsOutput": 397, "error": null }

The dataset has three views: Products, Changes and Store status. The run's OUTPUT record holds a run summary (events, stores by status, timing, request statistics) and STATUS a compact list of each store's result.

How much does it cost to scrape a Shopify store?

You pay per result. Platform usage (compute, proxy, storage) is included in the price.

EventPrice
Product row (or variant row)$0.85 per 1,000 ($0.00085 each)
Change row$2.00 per 1,000 ($0.002 each)
100 products scanned in changes mode$0.0003 per 100 ($0.003 per 1,000)
Inventory add-on (only where the quantity is public)$0.50 per 1,000
Actor start$0.00005 per run (Apify's standard start event; the default 512 MB counts once)
Status rows, stores that don't end ok, duplicates, price moves below your thresholdfree

Snapshot mode charges one product row per product. Changes mode charges a scan fee in batches of 100 products plus one change row per change; unchanged products are not output.

The scan fee is rounded up once per store per run: a 75-product store is 1 batch ($0.0003), a 153-product store 2 batches ($0.0006), a 10,359-product store 104 batches ($0.0312). The remainder never carries over to another store.

Worked examples (prices from the table above, counts from real runs):

  • The pre-filled run (colourpop.com, 100 products, snapshot): 100 × $0.00085 + $0.00005 = $0.08505.
  • One store's full catalog: Allbirds, 397 products = 397 × $0.00085 = $0.34.
  • First monitoring run (baseline) on gymshark.com, colourpop.com and allbirds.com (10,359 + 1,064 + 397 products): 104 + 11 + 4 = 119 batches × $0.0003 = $0.036, no change rows.
  • Daily monitoring of the same 3 stores: $0.036 scan fee plus $0.002 per change. A real run on Gymshark found 26 changes: 26 × $0.002 = $0.052.
  • 100 stores, 119,977 products checked in one changes-mode run: 1,244 batches × $0.0003 = $0.37.

Apify's Free plan includes $5 of monthly usage.

You never pay for status rows, for stores that end blocked, notShopify, error, notProcessed or any status other than ok (even if part of their catalog was read), for duplicate products, or for price moves below minPriceChangePercent. The run also respects the maximum charge you set: a store that wouldn't fit is skipped as notProcessed and costs nothing.

Change monitoring (changes mode)

  • The first changes run for a store saves a baseline and outputs no change rows: you pay only the scan fee.
  • The baseline lives in the key-value store shopify-monitor-<watchlistName> in your Apify account, one record per store.
  • A baseline is replaced only after a complete crawl that ended ok. A stopped, blocked or timed-out crawl never overwrites it, so you don't get false removed rows.
  • A product is reported removed only after it was missing on two complete runs in a row. A variant that disappears from a product that is still listed is reported straight away.
  • A product deleted and re-created with the same handle is reported once (added with recreatedFromProductId).
  • updated_at is not used: Shopify bumps it on nearly every product daily. Changes are detected from price, compare-at price and stock per variant.
  • With maxProductsPerStore set, the baseline isn't saved (a capped crawl isn't a full catalog).

In real tests, every detected change was checked against the live store: 9 of 9, 1 of 1 and 16 of 16 matched.

How reliable is it?

  • Accuracy: 30 of 30 products from 13 stores matched the store's own product pages on every field.
  • Blocking: every request goes through Apify's datacenter proxy with one session per store, rotated (up to 3 times) on a bot challenge or HTTP 429. In our test runs on Apify with the proxy, the only store that kept challenging was bombas.com (Vercel). A 100-store run at 512 MB saw 0 challenges and 0 HTTP 429 responses. Challenges are never solved; a store that keeps challenging ends blocked and costs nothing.
  • Large stores: Shopify's product feed stops at 25,000 products. Past that, the Actor continues through Shopify's public Storefront API and uses the store's sitemap as the target count (Kith: 35,206 of 35,206 on Apify in 669 s).
  • Scale: one 100-store run at 512 MB read 191,064 products in 1,296 s (97 stores finished; the 3 largest needed a bigger time budget).
  • Restarts: charged products are recorded before each charge, so if Apify migrates or restarts a run, nothing is charged twice (tested with forced reboots on Apify: charged batches equalled the expected count exactly).

FAQ

Is it legal to scrape Shopify stores? This Actor reads only public product data that any logged-out shopper can see, through the same JSON feeds Shopify serves to every visitor. It doesn't log in and reads no customer data. Check your own use against each store's terms and the law where you work; if you're unsure, ask a lawyer.

Why did a store end blocked? The store put a bot challenge on its own domain (for example bombas.com sits behind Vercel's checkpoint). The Actor retries with fresh proxy sessions but never solves challenges. You aren't charged for that store.

Why did a big store end notProcessed? Its time budget ran out. The largest stores (for example Burga, about 160,000 products, or Fashion Nova) may need more than the default 1,200 s. Raise Time budget per store (up to 3,600 s). Nothing is charged for an unfinished store.

Why is the price in a different currency than on my screen? Prices are in the store's default currency (currency), as its public feed serves them, not your local currency.

Can I monitor only one collection? Yes: enter a collection URL (https://kith.com/collections/mens) or list collection handles in collections.

Can I get exact stock quantities? Turn on the inventory add-on. Many stores hide quantities; you're charged only for products where a quantity was public.

Can I use it through the API or with integrations? Yes. Run it with the Apify API, the JavaScript or Python client, schedules, webhooks, or integrations such as Make, Zapier and Google Sheets.

Limits

  • Shopify stores only. Stores with their product feed switched off end notShopify.
  • Very large stores (e.g. Burga, about 160,000 products, or Fashion Nova) may need a larger storeTimeBudgetSecs; in our tests Fashion Nova wasn't finished within a 600 s budget (34,095 products read on Apify at 512 MB).
  • Stores behind their own bot protection (e.g. bombas.com, Vercel) end blocked.
  • Prices are the storefront's default-currency prices; market-specific prices aren't read.
  • A store whose public feed lists well under its own product count ends error (not charged), because the catalog can't be confirmed complete.

Feedback

Found a bug or need a field? Open an issue on the Issues tab and include the run ID.