If you run a DTC brand, a dropshipping store or a reseller business, you want to know when a competitor or supplier changes a price, puts something on sale, runs out of a size or launches a product. Checking their store by hand every morning does not scale, and a plain scraper only gives you today's catalog, not what changed since yesterday.
Shopify Catalog and Price Change Monitor by Hay Equipos reads a Shopify store's public product feed, saves a snapshot, and on every later run tells you exactly what changed.
How it works
- It reads the store's public
/products.jsonfeed, the same feed Shopify serves to every visitor, plus/meta.jsonfor the store name and currency. No login, no cookies, no cart or checkout pages. - It saves the catalog after each run in a named key value store in your own Apify account (default name
shopify-catalog-monitor-snapshots, one record per store). - The next run compares against that snapshot and flags each product as
baseline,unchanged,new,updatedorremoved, with a list of exactly what changed. - One feed page at a time per store, a pause between pages, robots.txt respected by default and retries with backoff when a store rate limits.
What you get back
One row per product, with all its variants. A product whose price changed since the last run (illustrative values, trimmed):
{
"recordType": "product",
"store": "www.example-store.com",
"storeName": "Example Store",
"currency": "USD",
"productId": 7340901859408,
"handle": "trail-runner",
"title": "Trail Runner",
"vendor": "Example Store",
"productType": "Shoes",
"productUrl": "https://www.example-store.com/products/trail-runner",
"minPrice": 95,
"maxPrice": 110,
"available": true,
"variantCount": 8,
"variantsInStock": 5,
"onSale": true,
"changeType": "updated",
"changes": [
{ "field": "price", "variantId": 42146889039952, "variantTitle": "9", "from": 110, "to": 95 },
{ "field": "available", "variantId": 42146889039953, "variantTitle": "10", "from": true, "to": false }
],
"variants": [
{ "variantId": 42146889039952, "title": "9", "sku": "TR-09", "price": 95, "compareAtPrice": 110, "onSale": true, "available": true }
],
"checkedAt": "2026-09-27T05:52:40.000Z"
}
Rows also include tags, imageUrl, imagesCount, createdAt, updatedAt, publishedAt and, if you ask for it, a plain text description. Changes can be a new title, a new price, a new compare at (sale) price, a stock flag flip, or a variant added or removed.
A per store summary (products found, new, updated, removed, whether the whole catalog was read) is saved in the run's key value store under SUMMARY.
Step by step in the Apify Console
- Open the actor on the Apify Store (link at the end) and click Try for free.
- In Shopify store URLs, add one store per line, as a link or a bare domain. Only the domain is used.
- Set Maximum products per store (default 1,000). Use 0 for the whole catalog, up to 25,000.
- Pick Output: all products with change flags, or only changes since the previous run.
- Keep the default Snapshot store name, or use a different name per client to keep separate histories.
- Leave Respect robots.txt on. Adjust Stores processed in parallel (default 2) and Pause between pages (default 1,000 ms) if needed.
- Click Start. The first run for each store saves the baseline. Changes appear from the second run on.
For daily alerts, save the input as a task with Output set to only changes, add a daily schedule, and connect the dataset to Slack, email, a sheet or a webhook through Apify integrations.
Calling it from code
With curl:
curl -X POST \
"https://api.apify.com/v2/acts/pistachio_implementation~shopify-catalog-monitor/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"storeUrls": ["www.example-store.com"],
"maxProductsPerStore": 0,
"outputMode": "changes"
}'
With Python and the apify-client package:
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("pistachio_implementation/shopify-catalog-monitor").call(
run_input={
"storeUrls": ["www.example-store.com", "shop.example.org"],
"maxProductsPerStore": 0,
"outputMode": "changes",
"snapshotStoreName": "competitor-watch",
}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["recordType"] == "error":
print("could not read", row["storeUrl"], row["error"])
continue
for c in row["changes"]:
print(row["store"], row["changeType"], row["title"], c)
Pricing
Pay per event, with no subscription and no platform usage charge on top:
| Event | Price |
|---|---|
| Actor start (Apify's standard start event) | $0.00005 per run |
| Product checked | $0.001 per product read ($1 per 1,000 products) |
| Change detected | $0.005 per product that is new, updated or removed |
Products are charged as checked in both output modes, because every product is read and compared. The first run for a store never charges for changes. Stores that fail, such as password protected stores or stores that block the feed, return an error row and are not charged. You can set a maximum charge per run and the actor stops when it is reached.
Limits and what it does not do
- Shopify stores only, and only those that leave the public product feed on.
- Removed products are reported only when the whole catalog was read on both runs. If you cap products below the catalog size, new and updated products are still flagged, but removals are held back to avoid false alarms. A capped run can also surface products as new when the feed order shifts, so read whole catalogs when you can.
- No inventory quantities. The public feed shows only whether each variant can be bought.
- Default currency only. Market specific prices are not included.
- Catalogs above 25,000 products are cut at 25,000.
The actor is an independent tool and is not affiliated with Shopify. Use the data in line with each store's terms.
Try it on the Apify Store: https://apify.com/pistachio_implementation/shopify-catalog-monitor
Top comments (0)