Shopify Store Monitor — Products, Prices & Stock Changes avatar

Shopify Store Monitor — Products, Prices & Stock Changes

Pricing

from $1.50 / 1,000 products

Go to Apify Store
Shopify Store Monitor — Products, Prices & Stock Changes

Shopify Store Monitor — Products, Prices & Stock Changes

Get every product and variant from any public Shopify store, or run it on a schedule to get only price drops, restocks, sold-outs, and new or removed products.

Pricing

from $1.50 / 1,000 products

Rating

0.0

(0)

Developer

Tucker Watts

Tucker Watts

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

15 hours ago

Last modified

Categories

Share

Get every product and variant from any public Shopify store as clean JSON, or run it on a schedule to get only what changed: price drops, price increases, restocks, sold-outs, new products and removed products.

  • No browser, no proxies, no login. Reads the public product feed Shopify serves on every store (/products.json), politely and within the store's robots.txt.
  • Change alerts, not just dumps. Schedule it daily and get a short list of changes instead of re-downloading the whole catalog.
  • Never crashes on a bad URL. Non-Shopify sites, password-protected stores, disabled feeds and rate limits each come back as a free store_error row that says what happened.

What you can do with it

  • Track competitor prices and discounts across many Shopify stores.
  • Get alerted when an out-of-stock product comes back.
  • Spot new product launches the day they go live.
  • Export a store's full catalog (titles, variants, SKUs, prices, compare-at prices, stock status, images) for analysis.

Input

FieldRequiredDescription
storeUrlsyesStore URLs or domains, up to 100 per run.
modenofull (default) returns every product. changes returns only what changed since the last run.
collectionnoA collection handle, e.g. sale, to limit to one collection.
vendornoOnly this vendor/brand (case-insensitive).
productTypenoOnly this product type (case-insensitive).
includeDescriptionnoFull mode: include the description as plain text. Default true.
maxProductsPerStorenoFull mode: stop after this many products per store.
{
"storeUrls": ["https://colourpop.com", "allbirds.com"],
"mode": "changes",
"collection": "sale"
}

Output

Full mode: one row per product

{
"type": "product",
"store": "colourpop.com",
"storeName": "ColourPop",
"currency": "USD",
"productId": 7661008683090,
"title": "Carry the Universe",
"handle": "carry-the-universe",
"url": "https://colourpop.com/products/carry-the-universe",
"vendor": "ColourPop",
"productType": "Gloss Bundle + Bag",
"tags": ["lip-gloss", "new-arrival"],
"description": "Every gloss, plus somewhere to put them. …",
"available": true,
"priceMin": 62,
"priceMax": 62,
"variants": [
{ "variantId": 42739735986258, "title": "Default Title", "sku": "Bundle-CarryTheUniverse", "options": [], "price": 62, "compareAtPrice": null, "available": true, "grams": 0 }
],
"images": ["https://cdn.shopify.com/…"],
"createdAt": "2026-09-01T09:00:00-07:00",
"updatedAt": "2026-09-24T11:46:01-07:00",
"publishedAt": "2026-09-02T11:33:11-07:00",
"scrapedAt": "2026-09-24T18:49:00.058Z"
}

Prices are numbers in the store's currency. compareAtPrice is null when the product isn't on sale.

Changes mode: one row per change

{
"type": "change",
"changeType": "price_drop",
"store": "example-store.com",
"currency": "USD",
"productId": 7369944137808,
"variantId": 42436493115472,
"title": "Classic Runner",
"variantTitle": "10",
"sku": "CR-M-10",
"url": "https://example-store.com/products/classic-runner",
"previousPrice": 98,
"price": 79,
"previousAvailable": true,
"available": true,
"detectedAt": "2026-09-24T18:49:00.000Z"
}

changeType is one of price_drop, price_increase, restock, sold_out (per variant), or new_product, removed_product (per product; variantId is null).

The first changes run for a store saves a baseline and returns no rows. Changes are reported from the second run on. Each combination of store, collection and filters has its own baseline.

Errors: free rows

{ "type": "store_error", "store": "example.com", "reason": "not_shopify", "message": "https://example.com does not look like a Shopify store (no public /products.json)." }

reason is one of invalid_url, not_shopify, password_protected, json_disabled, robots_disallowed, blocked, rate_limited, collection_not_found, network_error. A run summary is also saved to the OUTPUT record of the run's key-value store.

Pricing

Pay per event: you pay per product row (full mode) or per change row (changes mode). store_error rows are free. A changes run where nothing changed costs only the run start.

Set a maximum charge per run to cap spending. When the run reaches it, it stops cleanly, keeps everything already delivered, and says so in the status message. In changes mode, changes that didn't fit are reported on the next run and are never billed twice.

Limits

  • Public catalog only. Password-protected stores and stores that disable their product feed can't be read.
  • Up to 100 stores per run, up to 100,000 products per store.
  • The Actor sends about one request per second to each store and honors Retry-After. It never tries to get around a block. A store that refuses access is reported as blocked.
  • Shopify's public feed has no inventory counts, only in stock or out of stock per variant.
  • A new variant added to an existing product is not reported as a change. The product's other changes still are.

Use with AI agents

The input and output are flat and predictable. The type field on every row tells product, change and error rows apart, and every error has a fixed reason code. An agent can call this Actor with just storeUrls.