Shopify Product & Price Scraper
Pricing
from $0.40 / 1,000 product scrapes
Shopify Product & Price Scraper
Scrape full product catalogues from any Shopify store: variant-level prices, compare-at discounts, SKUs and live stock status. Bulk multi-store, one row per product or per SKU, with a per-store pricing summary. Built for daily price monitoring. From $0.40 / 1,000 products.
Pricing
from $0.40 / 1,000 product scrapes
Rating
0.0
(0)
Developer
Eimantas V
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Point it at any Shopify store. Get the full catalogue with variant-level prices, discounts, SKUs and live stock — in about a second per store, no browser.
allbirds.com 291 products · typical price 66.00 · 53% discounted, deepest 75% off163 fully out of stockgrind.co.uk 105 products · typical price 28.95 · 31 hidden from the storefronthooksneedles 897 products · typical price 24.97 · 26 added in the last 30 days
It reads each store's own public catalogue endpoint — the one Shopify exposes so themes and apps can list products. No key, no login, and nothing that breaks when a theme changes.
What you get
Per product
| Group | Fields |
|---|---|
| Pricing | minPrice, maxPrice, isOnSale, maxDiscountPercent |
| Stock | stockStatus (in-stock / partial / out-of-stock), variantCount, availableVariantCount |
| Variants | Per SKU: price, compareAtPrice, discountPercent, available, sku, grams, option1-3 |
| Catalogue | title, handle, productUrl, vendor, productType, tags, imageCount, featuredImage |
| Timing | createdAt, publishedAt, daysSinceCreated, isNewArrival |
| Visibility | isHidden — tagged to stay off the storefront |
Per store — product count, price range, median and mean price, discount rate, out-of-stock count, new arrivals, hidden and zero-priced counts, top vendors and product types, and plain-English highlights.
Two row shapes
granularity: "product" gives one row per product with variants nested. granularity: "variant" gives one row per SKU — which is what price and stock monitoring actually needs, because a sold-out size or a discounted colour is invisible in a product row carrying only a min and max.
Billing counts products either way, so the row shape is a free choice.
Who this is for
- Competitor price monitoring — run daily at variant granularity and diff on
productId+variant.sku. Price moves, new discounts and stock-outs fall straight out of the diff. - Assortment and market research — compare catalogue size, average price and discount depth across a set of stores in one run.
- Dropshipping and sourcing — filter by price band, vendor and product type across many suppliers at once.
- Sales prospecting — catalogue size and discount rate say a lot about a store's maturity. Pair with a tech-stack Actor: find prospects running Shopify, then scrape what they sell.
Input
{"stores": ["allbirds.com", "grind.co.uk"],"granularity": "variant","onSaleOnly": true,"maxProductsPerStore": 1000}
| Option | Default | Notes |
|---|---|---|
granularity | product | variant for one row per SKU |
maxProductsPerStore | 1000 | Your billing guard on large catalogues |
onSaleOnly / inStockOnly | false | Applied before billing |
excludeHidden | false | Drop storefront-hidden products |
minPrice / maxPrice | — | In the store's own currency |
titleKeywords / vendors / productTypes | — | |
addedWithinDays | — | New-arrivals feed; see the caveat below |
includeDescriptions | false | Off keeps the dataset far smaller |
includeCollections | false | One extra request per store |
Four things worth knowing
These are all things that produced visibly wrong numbers before they were handled, found by running the Actor against real stores.
updated_at is not emitted, because Shopify does not mean by it what you would expect. Every product in a catalogue response carries an identical updated_at equal to the moment of the request — verified across five unrelated stores, one distinct value each. Passing it through would make every product look modified on every run and quietly break exactly the change detection people build with it. Diff on price and available instead; those are real.
Compare stores on medianPrice, not averagePrice. Merchants park internal products at sentinel prices. One asset placeholder listed at 999,999 moved a quilting shop's mean from 31.05 to 1,068.36 — enough to rank it above a jeweller. Both figures are reported; the median is the one that a single absurd row cannot move.
A large slice of most catalogues is hidden from the storefront. Products tagged hidden or hidden_product — influencer exclusives, deal-site bundles, spare parts — sit in the feed where no shopper can browse to them. That was 30% of one store and 39% of another. Every record carries isHidden; set excludeHidden: true to drop them.
published_at is not a reliable age signal. Some stores republish their whole catalogue continuously — Gymshark's entire 2023-onwards range carries a publish date inside the last fortnight. Keying "new arrival" off it reported a three-year catalogue as 100% new. This Actor derives isNewArrival and addedWithinDays from created_at instead, and still reports publishedAt if you want it.
A stale compare_at_price is not a discount. Shopify leaves the field populated after a sale ends, so treating "field is set" as discounted invents permanent fake sales. A product only counts as on sale when a variant's compare-at price is genuinely above its current price.
Zero-priced products — free gifts, empty tins, bundle placeholders — are returned in full but kept out of the store's price statistics, and counted separately as freeProducts. They are not the cheapest thing a store sells.
Output
{"storeDomain": "allbirds.com","title": "Wool Runner","productUrl": "https://www.allbirds.com/products/wool-runner","productType": "Shoes", "vendor": "Allbirds","minPrice": 75, "maxPrice": 75,"isOnSale": true, "maxDiscountPercent": 25,"stockStatus": "partial", "variantCount": 2, "availableVariantCount": 1,"variants": [{ "sku": "WR-9", "price": 75, "compareAtPrice": 100, "discountPercent": 25, "available": true }],"createdAt": "2026-07-03T00:00:00.000Z", "daysSinceCreated": 40, "isNewArrival": false,"isHidden": false, "recordType": "product"}
Three ready-made dataset views: Products, Price monitor (SKU level) and Store comparison. Set flattenOutput: true for CSV — at variant granularity the flat shape is already close to a price table.
Honest limits
- Some stores block the endpoint. Headless storefronts and stores behind aggressive bot protection return 403. You get
HTTP_403with an explanation and are not charged. Most Shopify stores serve it fine; note that a store may blockwww.while serving the apex, and the Actor already prefers whichever your input resolves to. - Non-Shopify domains return
NOT_SHOPIFYrather than an empty success. - No inventory quantities. Shopify exposes
availableas a boolean, not a stock level. Anything claiming exact units for an arbitrary store is guessing. - Prices are in the store's own currency, which the catalogue endpoint does not state. Compare within a store, not across countries, unless you know the currency.
- Prices come as the store lists them, sentinels included.
maxPriceon a store summary can be a placeholder rather than a real product; that is whymedianPriceexists. productsScannedis a lower bound whentruncatedis true — the pages past your cap were never fetched, so it is not the catalogue total.
Pricing
| Event | Price | When |
|---|---|---|
| Actor start | $0.005 | Once per run |
| Store scraped | $0.01 | Per store whose catalogue was read |
| Product scraped | $0.0004 | Per distinct product returned, after filters |
$0.40 per 1,000 products. A 100-store run at 500 products each costs $21. Filters run before billing, and stores that block or aren't Shopify are never charged.
Tips
- Schedule daily, diff on
productId+variant.sku. New SKUs are launches, disappeared ones are discontinuations, and a changedpriceis the event you're watching for. onSaleOnly: trueis the cheapest promo tracker — you pay only for products actually discounted that day.addedWithinDays: 7at variant granularity is a clean new-launch feed across a whole competitive set.excludeHidden: trueif you are benchmarking assortment size. Counting products no shopper can reach overstates a competitor's range by a third on some stores.- Watch
discountRateper store over time. A rising discount rate with a rising out-of-stock count usually means end-of-season clearance.