Shopify Product & Price Scraper avatar

Shopify Product & Price Scraper

Pricing

from $0.40 / 1,000 product scrapes

Go to Apify Store
Shopify Product & Price Scraper

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

Eimantas V

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

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% off
163 fully out of stock
grind.co.uk 105 products · typical price 28.95 · 31 hidden from the storefront
hooksneedles 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

GroupFields
PricingminPrice, maxPrice, isOnSale, maxDiscountPercent
StockstockStatus (in-stock / partial / out-of-stock), variantCount, availableVariantCount
VariantsPer SKU: price, compareAtPrice, discountPercent, available, sku, grams, option1-3
Cataloguetitle, handle, productUrl, vendor, productType, tags, imageCount, featuredImage
TimingcreatedAt, publishedAt, daysSinceCreated, isNewArrival
VisibilityisHidden — 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
}
OptionDefaultNotes
granularityproductvariant for one row per SKU
maxProductsPerStore1000Your billing guard on large catalogues
onSaleOnly / inStockOnlyfalseApplied before billing
excludeHiddenfalseDrop storefront-hidden products
minPrice / maxPriceIn the store's own currency
titleKeywords / vendors / productTypes
addedWithinDaysNew-arrivals feed; see the caveat below
includeDescriptionsfalseOff keeps the dataset far smaller
includeCollectionsfalseOne 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_403 with an explanation and are not charged. Most Shopify stores serve it fine; note that a store may block www. while serving the apex, and the Actor already prefers whichever your input resolves to.
  • Non-Shopify domains return NOT_SHOPIFY rather than an empty success.
  • No inventory quantities. Shopify exposes available as 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. maxPrice on a store summary can be a placeholder rather than a real product; that is why medianPrice exists.
  • productsScanned is a lower bound when truncated is true — the pages past your cap were never fetched, so it is not the catalogue total.

Pricing

EventPriceWhen
Actor start$0.005Once per run
Store scraped$0.01Per store whose catalogue was read
Product scraped$0.0004Per 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 changed price is the event you're watching for.
  • onSaleOnly: true is the cheapest promo tracker — you pay only for products actually discounted that day.
  • addedWithinDays: 7 at variant granularity is a clean new-launch feed across a whole competitive set.
  • excludeHidden: true if you are benchmarking assortment size. Counting products no shopper can reach overstates a competitor's range by a third on some stores.
  • Watch discountRate per store over time. A rising discount rate with a rising out-of-stock count usually means end-of-season clearance.