Shopify Variant Stock & Price Change Feed avatar

Shopify Variant Stock & Price Change Feed

Pricing

from $2.00 / 1,000 variant records

Go to Apify Store
Shopify Variant Stock & Price Change Feed

Shopify Variant Stock & Price Change Feed

Recheck public variant price and availability changes; do not infer private stock quantities. For Shopify category and inventory monitoring teams. Check the live Pricing tab and input limits.

Pricing

from $2.00 / 1,000 variant records

Rating

0.0

(0)

Developer

Practical AI Lab

Practical AI Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Reads the public products.json feed of Shopify stores and returns one row per product variant: published price, compare-at price, a derived discount, and the store's own published availability flag. On repeat runs it also tells you what changed since the last run: new variants, price changes and availability changes.

What makes it different from a general product scraper

  • Variant-level rows with SKU, variant ID and a direct variant link, ready for spreadsheets and monitoring.
  • Change detection built in. A small snapshot per store and scope is kept in a named key-value store (pal-variant-stock-snapshots). Each row carries changeType, previousPrice, previousAvailability and priceDelta.
  • "Only changed" mode outputs just the rows that moved, which suits scheduled monitoring.
  • Meaningful price drops and restocks: alertSignal flags a price drop over your chosen threshold, a change from published sold_out to available, or both. priceDropPercent explains how much the listed price decreased. These are dataset signals, not emailed or pushed alerts.
  • Actionable-only output: onlyActionableChanges suppresses rows that do not meet the threshold or show a restock. A baseline run has no signal, so keep it disabled initially; scheduled repeat runs can enable it.
  • Honest data. Availability is the boolean the store publishes (available, sold_out, or unknown if absent). The Actor never outputs, estimates or guesses inventory counts and does not call any hidden or private stock API.

Input

FieldMeaning
storeUrls1–10 HTTPS store URLs. Only the domain is used.
maxProductsPerStore1–2000, default 250.
collectionHandleOptional single collection, e.g. new-arrivals.
availabilityFilterall, available or sold_out (output filter only).
minPrice / maxPriceOptional price range in the store's currency (output filter only).
trackChangesDefault true. Compare with the previous run.
onlyChangedRecordsDefault false. Output only new/changed variants.
minPriceDropPercentDefault 5. Price decrease threshold from 0% through 100%; not a currency conversion.
onlyActionableChangesDefault false. Output only threshold-crossing price drops or newly published availability. Requires trackChanges=true.
requestDelayMs500–10000, default 1000.

Sample input

{
"storeUrls": ["https://www.allbirds.com"],
"maxProductsPerStore": 100,
"availabilityFilter": "all",
"trackChanges": true,
"onlyChangedRecords": false,
"minPriceDropPercent": 5,
"onlyActionableChanges": false,
"requestDelayMs": 1000
}

Replace the sample store with stores you are permitted to monitor. The sample store is only an example of a public Shopify store; a store can change its feed or robots.txt at any time, and the Actor will then report the store as failed.

Output

One dataset row per variant. Format example with placeholder values (not real data):

{
"store": "shop.example.com",
"productId": 1,
"productHandle": "blue-shirt",
"productTitle": "Blue Shirt",
"vendor": "Acme",
"productType": "Shirts",
"productUrl": "https://shop.example.com/products/blue-shirt?variant=11",
"variantId": 11,
"variantTitle": "S",
"sku": "BS-S",
"price": "20.00",
"compareAtPrice": "25.00",
"discountPercent": 20.0,
"availability": "available",
"variantUpdatedAt": "2026-01-01T00:00:00-00:00",
"scrapedAt": "2026-01-02T08:00:00+00:00",
"changeType": "price_changed",
"previousPrice": "22.00",
"previousAvailability": "available",
"priceDelta": "-2.00"
}

changeType is one of not_tracked, baseline, unchanged, new_variant, price_changed, availability_changed, price_and_availability_changed. Additional output fields are priceDropPercent and alertSignal (none, price_drop, restocked, price_drop_and_restock). A change flag is not a notification and cannot verify checkout inventory.

A SUMMARY record in the default key-value store lists, per store, the status, products read, variants parsed or skipped, rows output and any error.

Pricing event

The code emits one pay-per-event charge named variant-record per variant row pushed to the dataset. Rows are charged only after they were fetched and parsed successfully. Failed stores, blocked requests and invalid input produce no charged rows. The actual price per event is configured on the platform, not in this project. If your spending limit is reached, the run stops and keeps the previous snapshot untouched.

Safety and compliance behavior

  • HTTPS only; no credentials, ports, IP addresses or internal host names. Hosts resolving to non-public addresses are refused.
  • robots.txt is fetched for every store and honored (wildcards, $, longest match, Crawl-delay up to 10 s). If robots.txt cannot be read safely (HTTP 401/403/429/5xx or a network error), the store is skipped.
  • Redirects are followed only within the same host (max 3).
  • Requests are sequential, paced, size-capped (12 MB per page), retried at most twice on HTTP 429/503.
  • No proxies, no login, no browser, no personal data. The feed contains product data only.

Limitations and caveats

  • Availability is not stock. A store may publish available: true for products it oversells or backorders, and the flag can lag the real shop state. No quantities are provided.
  • No currency field. products.json does not state the currency; prices are in whatever the store's feed uses for your request. Multi-market price variants are not covered.
  • Not every store works. Stores may disable or restrict products.json, password-protect the shop, or disallow it in robots.txt. Those stores are reported as failed and not charged.
  • Published data only. Hidden, unpublished or customer-segment-specific products and prices are not visible.
  • Change detection needs history. The first run for a store and scope is a baseline. If a run was capped by maxProductsPerStore, variants beyond the cap are not compared, and a shift in the store's product ordering can make existing variants look new_variant. Removed variants are not reported.
  • Snapshots are keyed by store and collection; changing filters on price or availability does not affect them.
  • DNS is checked before each request, but the HTTP client resolves the host again; a hostile DNS rebinding setup is reduced, not fully excluded.
  • Sample-size caveat: there are no benchmark or accuracy figures for this Actor yet. Test it on a few stores of your own before relying on it for decisions, and check a handful of rows against the live product pages.

Local tests

Tests are offline and use only the standard library plus the project code:

python -m unittest discover -s tests -t .