Shopify Store Scraper — Products, Prices, Variants and Store Data

Export a Shopify store's full public catalog, or profile the store itself, from the same products.json feed Shopify serves to every visitor.

Run on Apify →See pricing

What it does

Most Shopify stores expose their published catalog as JSON at /products.json. This actor reads that feed for one or more store URLs and returns one row per product: title, handle, vendor, product type, tags, created, published and updated dates, price range, compare-at price and discount percentage, stock availability, every variant (SKU, price, compare-at, options, weight) and every image URL.

For competitor price monitoring, pass updatedSince on a daily schedule and only products updated since that date become rows, so unchanged products cost nothing. collections narrows a run to specific collection handles. In store mode you get one row per shop instead: name, country, currency, ships-to countries, product and collection counts, price statistics, top vendors, product types and tags, the biggest collections, the theme and the apps detected on the homepage.

It is polite by design: the store's robots.txt and Crawl-delay are obeyed, requests go one at a time per store at about 1.3 per second, and any block stops that store with a free row. Products cost $0.30 per 1,000 and each analyzed store $0.005; blocked, headless and non-Shopify sites are free.

How it works

  1. Each URL in storeUrls (or storeUrl) is reduced to its host, so any page of a store works, including myshopify.com domains.
  2. The actor reads the store's robots.txt first, then pages through products.json at 250 products per page, up to maxProductsPerStore.
  3. Filters are applied as it goes: collections switches to collection feeds and updatedSince keeps only recently updated products, which are the only ones charged.
  4. In store or both mode it also reads meta.json and the homepage HTML to compute price stats and detect the theme and apps from open fingerprints.
  5. A 401, 403, 429 or bot challenge stops that store at once with no retries, proxies or bypass, and the resulting row is free.

Input example

A typical run input (JSON). Every field is also available as a form in the Apify console.

{
  "storeUrls": [
    "allbirds.com",
    "https://www.tentree.com"
  ],
  "mode": "products",
  "collections": [],
  "maxProductsPerStore": 1000,
  "updatedSince": "",
  "includeVariants": true,
  "includeBodyHtml": false
}
All input fields
FieldTypeRequiredDefaultWhat it does
storeUrlsarraynoStore domains or URLs, e.g. allbirds.com or https://www.allbirds.com/collections/mens. Any page of the store works because the store is taken from the host. myshopify.com domains work too. Duplicates are removed.
storeUrlstringnoOne store domain or URL. Handy for Clay, Make/Zapier and AI agents. Scraped together with storeUrls.
modestringno"products"products: one row per product ($0.30 per 1,000). store: one row per shop with meta.json details, product count, price stats, top vendors/types/tags, top collections, theme and detected apps ($0.005 per store). both…
collectionsarrayno[]Optional collection handles (the part after /collections/ in the URL, e.g. mens-shoes). When set, products come from each collection instead of the whole catalogue, and each row says which collection it came from.…
maxProductsPerStoreintegerno1000Stop each store after this many product rows (products/both mode), or after scanning this many products for the stats (store mode). products.json returns 250 products per page.
updatedSincestringno""Optional date (YYYY-MM-DD) or ISO timestamp. Only products whose updated_at is on or after it become rows. Products skipped by this filter are never charged. Use it for daily price and stock monitoring.
includeVariantsbooleannotrueAdd every variant (SKU, price, compare-at price, availability, options, weight) to each product row. Same price.
includeBodyHtmlbooleannofalseAdd the product description (body_html) to each row. Off by default because it makes rows much bigger. Same price.

Output example

Product rows carry the store, pricing, discount and stock fields up front, with variants and images attached to each row:

storetitlevendorproductTypepricecompareAtPriceMindiscountPctavailablevariantCount
www.allbirds.comWomen's Allbirds Flip Flop - Dusty PinkAllbirdsShoes255050true7
www.allbirds.comMen's Canvas Runner NZ - Deep Navy Stripes (Blizzard Sole)AllbirdsShoes100true13
www.tentree.comSasquatch Peak HattentreeAccessories31.54530true1
www.deathwishcoffee.comWhite Chocolate Pistachio Ground BundleDeath Wish CoffeeBundle48.9953.999.3true1

Pricing

Pay per event: you are charged only for the results you receive, with no subscription. Set a maximum total charge on any run and it stops cleanly at the cap.

Charged forWhenPricePer 1,000Worked example
Product resultCharged per product row delivered (with variants and images)$0.0003$0.30A 1,000-product store = $0.30; with updatedSince, unchanged products are skipped and cost nothing
Store analyzedCharged per store row in store/both mode (meta, price stats, top vendors/types, collections, theme, apps)$0.005$5100 competitor stores = $0.50; blocked, headless, robots-disallowed and non-Shopify sites are free rows
Actor Start (platform start fee)Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event).$0.00005—One run at 256 MB = $0.0000125

Prices are read from the live Apify Store listing when this page is built. The listing is always authoritative.

Try Shopify Store Scraper on Apify. Pay only for the results you get.

Run on Apify →

Use cases

Competitor price and stock monitoring

Schedule a daily run for a list of competitor stores with updatedSince set to the previous day. You get only the products whose prices, stock or details changed, and pay only for those rows.

Catalog export and migration prep

Pull a whole store's published catalog with variants, images and optionally descriptions as JSON or CSV. It is a quick way to audit a catalog or hand product data to another system.

Product research and dropshipping

Compare vendors, product types, price ranges and discount depth across several stores in one dataset. Compare-at prices show how often and how deeply a store discounts.

Store profiling for sales and partnerships

Use store mode to get one row per shop with its theme, detected apps, currency, ships-to countries and catalog size. Agencies and app vendors can qualify a list of Shopify stores at $0.005 each.

How it compares

ActorForge Shopify ScraperDownloading products.json yourselfStore owner's admin CSV export
Works on stores you do not ownYesYesNo, owner only
Pagination, robots.txt and polite pacing handledYesYou handle itNot needed
Clean rows with discount % and stock flagsYesNo, raw JSONPartial
Only products updated since a dateYes, unchanged products freeYou filter itNo
Theme and app detectionYes, store modeNoNo
Inventory quantities and sales figuresNo, not publicNoYes
Headless (Hydrogen/custom) storefrontsNo, returns a free not-reachable rowNoYes

If you own the store, Shopify's admin export includes inventory quantities and data this public feed never shows. For one small store, opening /products.json in a browser may be all you need; the actor helps once you have many stores, schedules or large catalogs.

Limits and honest notes

FAQ

How do I scrape all products from a Shopify store?

Add the store's domain to storeUrls with mode set to products. The actor pages through the public products.json feed at 250 products per page until it reaches maxProductsPerStore (default 1,000, up to 100,000).

Why does a Shopify store return no products?

Headless storefronts built on Hydrogen/Oxygen or a custom frontend do not serve /products.json, and some stores block automated requests with a 403 or a bot challenge. Those stores come back as free rows explaining the reason.

Can I get inventory quantities or sales numbers?

No. products.json shows whether each variant is available but not stock quantities, and sales figures are not public. Prices are the store's base-currency prices, not market-specific or B2B prices.

How do I scrape only one collection?

Put the collection handle, the part after /collections/ in the URL such as mens-shoes, in collections. Each row then says which collection it came from. The handles apply to every store in the run.

Which Shopify apps can it detect?

Store mode checks the homepage HTML against open webappanalyzer fingerprints (7,600+ of them), covering apps such as Klaviyo, Rebuy, Yotpo and Afterpay, and reads the theme name, base theme and version. Apps that load only after JavaScript runs or only on product pages may be missed.

Use it from code

Run the actor through the Apify API with the input above.

cURL

curl -X POST "https://api.apify.com/v2/acts/actor-forge~shopify-store-scraper/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"storeUrls": ["allbirds.com", "https://www.tentree.com"], "mode": "products", "collections": [], "maxProductsPerStore": 1000, "updatedSince": "", "includeVariants": true, "includeBodyHtml": false}'

JavaScript (Node.js)

// Node.js 18+ (built-in fetch). Set APIFY_TOKEN in your environment.
const input = {
  "storeUrls": [
    "allbirds.com",
    "https://www.tentree.com"
  ],
  "mode": "products",
  "collections": [],
  "maxProductsPerStore": 1000,
  "updatedSince": "",
  "includeVariants": true,
  "includeBodyHtml": false
};

const res = await fetch(
  "https://api.apify.com/v2/acts/actor-forge~shopify-store-scraper/run-sync-get-dataset-items",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.APIFY_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(input),
  }
);
const items = await res.json();
console.log(items.length, items[0]);

Python

# pip install apify-client   (set APIFY_TOKEN in your environment)
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {
    "storeUrls": [
        "allbirds.com",
        "https://www.tentree.com"
    ],
    "mode": "products",
    "collections": [],
    "maxProductsPerStore": 1000,
    "updatedSince": "",
    "includeVariants": True,
    "includeBodyHtml": False
}

run = client.actor("actor-forge/shopify-store-scraper").call(run_input=run_input)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

The run-sync-get-dataset-items endpoint waits for the run (up to 5 minutes) and returns the dataset rows directly. For longer runs, start the run asynchronously and read the dataset when it finishes, as the Python example does. Replace APIFY_TOKEN with your own token from the Apify console.

Step-by-step guides

How to Export Shopify Store Product Data to CSV or JSON

Give the ActorForge Shopify Store Scraper a store URL, let it page through the public products.json feed, then download the dataset as CSV or JSON…

Related actors

App Store & Google Play Scraper — Apps, Charts, Reviews

Scrape Google Play and App Store app details (rating, histogram, installs, price, version, developer, screenshots, similar apps), Apple top charts…

$0.80 per 1,000 · app result

Google Ads Transparency Scraper — Competitor Ads | $0.60/1K

Scrape competitor ads from the Google Ads Transparency Center by domain, advertiser name or ID: format, first/last shown, regions, impressions, ad…

$0.60 per 1,000 · ad result

SEO Audit Crawler — On-Page SEO Checker for Whole Sites

Crawl a whole website and audit every page for technical and on-page SEO: titles, meta descriptions, H1s, canonicals, noindex, duplicates, broken…

$6 per 1,000 · page audited

Try Shopify Store Scraper on Apify. Pay only for the results you get.

Run on Apify →

More E-commerce & App Stores tools · All actors