Shopify Store Scraper: Products, Prices & Price Changes avatar

Shopify Store Scraper: Products, Prices & Price Changes

Pricing

from $0.80 / 1,000 products

Go to Apify Store
Shopify Store Scraper: Products, Prices & Price Changes

Shopify Store Scraper: Products, Prices & Price Changes

Track any Shopify store's products with price, compare-at price, discount, variants, SKUs, stock and new products, plus price changes and restocks between runs, for competitor monitoring. About $0.001 per product: 1,000 cost $1. No login. Includes collection and product URLs.

Pricing

from $0.80 / 1,000 products

Rating

0.0

(0)

Developer

mogged

mogged

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Security

Limited permissions

Share

For ecommerce brands, price analysts and resellers who monitor competitor catalogues every day. Get public products, variant prices, discounts, SKUs, barcodes when published, stock availability and persistent price-change history.

About $0.001 per delivered product: 40 products cost $0.04, or 1,000 cost $1, plus Apify's $0.00005 minimum start charge. Variant details are included in that product price. Bronze, Silver and Gold discounts apply. In change-only mode, unchanged products have no product charge.

The prefilled two-store example returned 40 products in 9 seconds in an actual 512 MB cloud test on 29 October 2026. All four source requests succeeded. Both stores returned confirmed USD currency. Store response times vary.

What you get

FieldMeaning
verdictReadable product, price, availability and discount summary
recordTypePRODUCT, free NOTE, or free store SUMMARY
store, productId, handle, urlStore scope and stable public product identity
title, vendor, productType, tagsMerchant-supplied catalogue classification
price, priceMaxLowest and highest published variant price, in major currency units
compareAtPrice, discountPercentCompare-at value of the same lowest-price variant and its calculated discount
onSale, discountedVariantCountWhether any variant is discounted, and how many
currency, currencySourceCurrency explicitly found on the storefront, or null
available, availableVariantCountWhether any variant is available and how many are available
variantCount, variantsVariant count and optional nested variant details
createdAt, publishedAt, updatedAtPublic product timestamps, normalized to UTC when supplied
images, scrapedAtPublic image URLs and the observation timestamp
changeType, changes, previousPricePrimary watch change, all simultaneous change types and prior price
variantChangesIDs and changed fields for variants in a watch
priceSourceCatalogue decimal JSON or product Ajax JSON

Each variant contains variantId, title, options, price, compareAtPrice, sku, barcode, available, inventoryQuantity and inventoryPolicy. A missing value stays null. Stock quantities are source-reported public values, not independently verified warehouse counts. Many stores expose availability without a quantity or barcode.

The product-level discount never compares the cheapest size with the compare-at price of an unrelated, more expensive size. Use onSale to find a discount on any size, then inspect the matching variant for its price.

Start in three steps

  1. Enter one or more public store roots, or paste individual product or collection links.
  2. Choose the maximum number of products examined per store and whether to include variants.
  3. Run, inspect the free store summary, and export the product dataset as JSON, CSV or Excel.
{
"storeUrls": [
"https://www.allbirds.com",
"https://www.deathwishcoffee.com"
],
"maxProductsPerStore": 20,
"includeVariants": false,
"proxyConfiguration": { "useApifyProxy": true }
}

This is the prefilled example: up to 40 charged product rows, about $0.04 before plan discounts. Enable variants for slower, deeper per-product detail. JSON preserves nested values. For a flat export, use the Products and prices dataset view and filter recordType to PRODUCT.

Input reference

InputDefaultPurpose
storeUrlsNone in API inputPublic store or locale roots; the form prefills two stores
collectionsEmptyOptional collection handles applied to each store root
productUrlsEmptyProduct or collection links, including collection product paths
maxProductsPerStore20Current products examined per store, from 1 to 10,000
includeVariantsfalseInclude nested variants and request public product details
onlyChangedSinceLastRunfalseReturn only new or changed products for a persistent watch
watchIddefaultStable monitoring name; letters, numbers, underscores and hyphens
proxyConfigurationDatacenter proxyCustom proxy settings or explicitly disabled proxy

URL lists accept plain strings. URL objects containing url also work when supplied by an integration. Bare public domains are accepted. HTTPS, normal domain names and standard ports are required. Credentials, internal addresses and unrelated URL paths are rejected with a free note.

Store roots select the full public catalogue unless collections supplies a narrower scope. Product links select those products. Collection links work directly in productUrls. Duplicate URLs, overlapping collections and overlapping product links produce one row and one product charge per store and product ID.

{
"storeUrls": ["https://www.deathwishcoffee.com"],
"collections": ["coffee"],
"maxProductsPerStore": 100,
"includeVariants": true
}

For selected products, omit storeUrls:

{
"productUrls": [
"https://www.deathwishcoffee.com/products/death-wish-stir-stick-set"
],
"includeVariants": true
}

Monitor prices every day

Create a task with onlyChangedSinceLastRun: true and a memorable watchId, such as coffee-daily. Schedule that task daily in Apify. Keep the same store roots, product URLs, collections, product cap and variant setting. Use another watch ID for a different scope.

{
"storeUrls": ["https://www.deathwishcoffee.com"],
"maxProductsPerStore": 1000,
"includeVariants": true,
"onlyChangedSinceLastRun": true,
"watchId": "coffee-daily"
}

The first run establishes the baseline and returns observed products as new. The next run returns changed products only. An unchanged catalogue produces a free summary and no product charges, apart from the platform start fee. Each changed product is charged once even when several variants change together.

Watch changes include new, priceUp, priceDown, backInStock, soldOut and removed. Additional explicit types cover discountChanged, variantsChanged, currencyChanged and metadataChanged. changes retains simultaneous signals, so a price drop and stockout are visible together. previousPrice is the prior observed product minimum, not a historical price obtained from the merchant.

A change to a non-cheapest variant still qualifies when variants are included. Ordinary inventory-quantity churn and the merchant's continually updated timestamps do not create paid change rows. Confirmed currency changes are flagged separately rather than called price rises or falls. Missing currency discovery never creates a paid change alert; monetary comparisons resume when the currency is confirmed.

A removal is emitted only after a complete successful scan of the unchanged scope. Capped catalogues, failed pages, incomplete detail reads and spending-limit stops never prove that an unseen product disappeared. A product leaving a selected collection means removal from that collection scope, not necessarily deletion from the whole store. Removed rows use price: null, preserve previousPrice, and represent an observation about catalogue membership.

Run each watch sequentially. If its previous run is unfinished, reboot that original run or use another watch ID. Do not launch the same watch simultaneously. Watch state is isolated by account and Actor, and continues across tasks and container restarts.

Example from a real cloud run

Observed on 29 October 2026, with longer image lists and optional fields omitted here for readability:

{
"verdict": "Death Wish Stir Stick Set: USD 8.00, in stock.",
"recordType": "PRODUCT",
"store": "https://www.deathwishcoffee.com",
"productId": "7499727863863",
"handle": "death-wish-stir-stick-set",
"title": "Death Wish Stir Stick Set",
"vendor": "Planet Apparel",
"price": 8,
"compareAtPrice": null,
"discountPercent": 0,
"currency": "USD",
"available": true,
"variantCount": 1,
"variants": [{
"variantId": "42351252209719",
"price": 8,
"compareAtPrice": null,
"sku": "USTIRDW26",
"barcode": null,
"available": true
}],
"changeType": null,
"previousPrice": null
}

Prices and stock can change after this observation. Read the current run's scrapedAt before using a number in a report or alert.

Free summaries and source failures

Every store receives a free SUMMARY dataset row with observed products, delivered rows, sale count, median price, new products since the previous watch run, unchanged count, currency and coverage status. The key-value store's SUMMARY record combines all stores with request counts and the spending-limit result.

A capped sample is clearly marked CAPPED and fullScan: false. A blocked, unavailable, password-protected or unsupported store produces a free note, with no product charge. Invalid values are rejected by input validation or returned as a free note by the Actor. Check summary status as well as the platform's run status: SUCCEEDED means the request was handled, and does not promise that every merchant exposed data.

The Actor respects the run's maximum charge and stops cleanly when another product cannot fit. It saves the useful row before charging, deduplicates delivery through the durable dataset and reconciles charges after a platform reboot. Retries and restart recovery do not add duplicate product charges.

Pricing examples

Delivered productsList product charge
20$0.02
40$0.04
100$0.10
1,000$1.00
10,000$10.00

Add the $0.00005 minimum start fee per run. Bronze products cost $0.00095, Silver $0.0009 and Gold or higher $0.0008. A 40-product Bronze run therefore costs $0.03805 including the start fee. Current Apify pricing is authoritative.

The cap counts products examined, including unchanged products, rather than promising a requested number of changes. For example, examining 100 products and finding three changes delivers three paid product rows. Free notes and summaries never count as paid products. No separate fee is charged for a variant, request, retry or barcode.

API and integrations

Start an asynchronous run using your own Apify API token:

curl -X POST \
'https://api.apify.com/v2/acts/moggedhq~shopify-store-products-scraper/runs' \
-H 'Authorization: Bearer YOUR_APIFY_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"storeUrls":["https://www.allbirds.com"],"maxProductsPerStore":20}'

Use the returned run's defaultDatasetId to download /v2/datasets/DATASET_ID/items. Read /v2/key-value-stores/STORE_ID/records/SUMMARY using the run's defaultKeyValueStoreId for coverage and diagnostics.

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('moggedhq/shopify-store-products-scraper').call({
storeUrls: ['https://www.allbirds.com'],
maxProductsPerStore: 20,
includeVariants: true
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const products = items.filter(row => row.recordType === 'PRODUCT');
console.log(products);

Connect scheduled tasks to Make, Zapier, n8n, Sheets or your warehouse. Trigger an alert from product rows whose changes contain priceDown or backInStock. Keep credentials in your integration's secret storage.

Use with AI agents (MCP)

Connect your assistant to Apify MCP. Ask it to run moggedhq/shopify-store-products-scraper with the store URLs, product cap and variant setting, then read product rows and the summary. For daily monitoring, provide a stable watch ID and request change-only mode. Tell the agent to preserve your maximum charge and to report partial coverage.

Limits and FAQ

Does every Shopify store work? No. Traditional public Shopify catalogue endpoints are supported. Headless frontends, custom routing, password protection and merchant access controls can prevent access. The Actor does not log in or solve challenges.

Where do currency and prices come from? Prices come from public catalogue or product JSON. Currency comes from explicit storefront HTML values; it remains null if unconfirmed. Preserve locale roots such as /en-gb when supplied by a store. This is not a ZIP-specific, checkout, tax, shipping, subscription or member-price service.

Can I search every Shopify store by keyword? No. Supply known stores or product links. This Actor monitors chosen competitors; it does not query a worldwide marketplace or collect merchant contacts.

Will I get exact stock, reviews or sales? Only public availability and any explicitly exposed variant quantities. No sales estimates, customer records, reviews, hidden inventory, cart calls or checkout requests are used. Missing barcodes and timestamps remain null. Public JSON can list products whose shopping page requires membership; catalogue availability does not establish purchase eligibility.

How are stores paced? One request at a time per host, roughly 1.1 seconds between starts, with fresh proxy sessions for retries. Up to two different hosts advance concurrently. Datacenter proxy is the default; residential proxy is used only when explicitly selected. Long Retry-After instructions defer the store to a later run.

What happens after a spending-limit stop? Delivered rows remain available. The previous watch baseline is retained so undelivered changes can be seen later. Increase the next run's limit to finish the intended scan. Some already delivered changes can appear again in that new run because it is a new delivery, not a reboot.

Can I reuse a watch with different filters? Use a different watch ID. Scope changes are rejected with a free note to prevent misleading comparisons. Stored snapshots are observations from your earlier runs, not historical backfill.

Review the target merchant's access terms and use the public data within your permissions. Shopify store scraper, Shopify products and Shopify price changes are the data covered here.