Price Tracker & Stock Monitor for Any Online Store
Pricing
from $1.20 / 1,000 products
Price Tracker & Stock Monitor for Any Online Store
Price tracker and stock monitor for any online store: price, stock and variants from product pages on Shopify, WooCommerce, Magento, BigCommerce, Wix, Squarespace, Walmart, Target, Best Buy, eBay, Etsy and more. Changes-only monitoring for competitor watchlists; compact JSON for AI agents.
Pricing
from $1.20 / 1,000 products
Rating
0.0
(0)
Developer
CleanPull
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Features
Share
This price tracker and stock monitor reads product page URLs from any online shop, or just a store's address, and gets each product's price, list price, stock state, every variant with its own price, stock, SKU and barcode, brand, images, rating and review count. It reads Shopify, WooCommerce, Magento, BigCommerce, Wix, Squarespace, PrestaShop, Shopware, Salesforce Commerce Cloud and custom stores, plus Walmart, Target, Best Buy, eBay and Etsy product pages. Schedule it for competitor price monitoring and every row says what changed since your last run: price, stock, a sale starting or ending, variants, title, image, or the page being taken down. It runs once, on a schedule or through the API, with no sign-in.
Also known as a competitor price tracker, product price monitor, stock checker, back-in-stock monitor and price change alert for online stores.
How to track prices on any online store
- Open Price Tracker & Stock Monitor for Any Online Store on Apify and go to its input form.
- Paste product page links in Product URLs, one per line. To watch a whole store instead, enter its address in Whole stores (sitemaps), with Products per store and, optionally, Only URLs containing.
- Keep Variants on for each size and colour's own price, stock, SKU and barcode. On Shopify, turn on Read the page on Shopify too for the review rating.
- Start the run. Open the Products view to read each product's Price, List price, Availability, In stock and Variants in stock, and the Variants (one row per variant) view for each variant's SKU, Barcode, Price and Units.
- To monitor prices and stock, turn on Changes only, give the watchlist a Monitor name, save it as a task and schedule it daily. The Changes view then lists each changed product's Changes, with the earlier values under Previous.
What the price tracker gives you
- "Tell me when a competitor changes a price or sells out." Put their product URLs in a watchlist, turn on Changes only and schedule it daily: only products that moved come back, with the old and new value.
- "Watch a competitor's whole store." Give the store's address in Whole stores (sitemaps); the actor finds its product sitemap and reads up to the number of products you choose, filtered by a word or pattern in the URL.
- "Which sizes are out of stock?" Every variant comes with its own stock state, and units left where the store publishes them.
- "Match competitor products to mine." Barcodes (GTIN, EAN, UPC), SKUs and MPNs are returned wherever the store publishes them.
- "Feed product data to an AI agent or a spreadsheet." Compact JSON with the same field names for every store, a field picker, and a dataset view per job.
- "Check the prices in another actor's results." Point Dataset of products at a dataset whose rows hold product URLs.
How the price tracker reads a store
Each product is read the cheapest complete way, and every row says where its price came from (priceSource):
- Shopify stores: the store's own product data (
/products/<handle>.js), with every variant, its stock and barcode, in the store's checkout currency. No page load at all. A store behind Shopify's bot check gets its product data asked for through stronger proxies, still without the page and without the residential add-on. A store whose bot check refuses every product address is read from its catalog (/products.json, 250 products a page, read once per run for all its products, up to 5,000): prices in the shop's base currency, without stock counts, with a warning saying so. A watched product missing from the catalog is reported as removed only when the next run sees the same. - Every other store: the product page's structured data: JSON-LD (including variant groups), microdata, Magento's price box, the analytics product event, and Open Graph tags, merged with the most trusted first.
- WooCommerce: when the page lacks a price, stock or variant prices, the store's public Store API fills them in, every variation included.
- Walmart, Target, Best Buy (US), eBay (ebay.com, ebay.de, ebay.co.uk and ebay.es) and Etsy: these marketplaces block automated visitors, so their product pages come through CleanPull's marketplace data service, a third-party web data provider. CleanPull holds the account; nothing to set up. All of a run's products on one marketplace are read in one job, from a few seconds to a few minutes, while the other stores are read. Rows have the same fields as any other store's (
priceSource: "marketplace-data",platform: "walmart"and so on), without variants. A listing the marketplace removed comes back as not found, and on a watchlist as removed. Walmart price checks with Changes only (price, stock and sale changes only) read its lighter price-and-availability data.
In tests on 51 product pages from 30 stores on 10 platforms, read from Apify's servers, it returned price and stock for 44. The other 7 were Target and Best Buy (read since 0.2 through the marketplace data service), three pages that publish no product data, a removed IKEA product and a store that blocks automated visitors. A watchlist of 30 of those products read twice, minutes apart, reported no false changes.
Price tracker accuracy
- A block is never an empty result. Each store gets its own proxy ladder (direct, then datacenter, then residential only for stores that block the others), so one strict store never makes the rest of the run slower or pricier.
- Partial pages are read again. Some shops occasionally serve a page without its product data; the actor reads it once more on a fresh session before giving up.
- Values from different sources are never mixed. A price keeps its own source's currency and list price; a product that cannot be bought has no price rather than a price of 0.
- Changes are real changes. A price or stock state missing from one read carries over instead of reading as a change, prices in different currencies are not compared, and a re-uploaded image with a new cache key is not a new image.
- Moved is not removed. A product sent to the same brand's site for another country (brand.com → brand.co.uk) is reported as moved, with the new address, and never as removed.
- Only public addresses are read. A URL, sitemap or redirect pointing into a private network is never fetched.
- Only delivered products and checks are billed. Each delivered row is charged, and with Changes only each unchanged product checked is charged as a check (see Pricing below). A page that could not be read is listed in the run summary with the reason, never charged. Sitemap pages that are not products are skipped for free.
- Runs do not fail for one bad entry. An invalid URL is skipped with a warning; an empty input runs the form's example.
- Sites with their own CleanPull actor are routed, not guessed: Amazon URLs point to Amazon Product Scraper. Neither they nor Walmart Canada and Best Buy Canada are fetched or charged.
Price tracker input
| Field | Key | What it does |
|---|---|---|
| Product URLs | productUrls | Product page URLs from any shop, one per line |
| Whole stores (sitemaps) | sitemaps | Store addresses (brand.com) or sitemap URLs: the actor finds the store's product sitemaps (from robots.txt) and reads its product pages |
| Only URLs containing | urlFilter | For sitemaps: keep only product URLs containing this text (case-insensitive), or matching a /regular expression/ |
| Products per store | maxProductsPerSitemap | How many product URLs to read from each store's sitemaps (default 100) |
| Dataset of products | datasetId | Another dataset whose rows hold product URLs (a previous run, or another actor's results) |
| Dataset field | datasetField | The field holding the product URL in that dataset (default url; url, productUrl and link are also tried) |
| Variants | includeVariants | Every variant with its own price, stock, SKU and barcode (on by default) |
| Read the page on Shopify too | readFullPage | Shopify: also read the product page, for the review rating its markup adds |
| Changes only | changesOnly | Return only products that changed since the last run with the same monitor name; the first run is the baseline |
| Monitor name | monitorName | Runs with the same name compare against each other (default default); one name per watchlist |
| Changes to report | changeTypes | price, stock, sale, variants, title, image, removed (all by default); a product whose only changes are left out counts as unchanged |
| Smallest price change (%) | minPriceChangePercent | Ignore price moves smaller than this percentage (default 0: every change) |
| Max products | maxItems | Stop after this many product rows |
| Only these fields | fields | Keep only these fields, for example ["url", "title", "price", "currency", "inStock"] |
| Products at a time | maxConcurrency | Products read in parallel across all stores (default 5) |
| Products at a time per store | maxConcurrencyPerStore | Products read in parallel from one store (default 2) |
| Proxy | proxyConfiguration | Your own proxy, tried after the direct attempt (a residential one after datacenter) |
| Start URLs | startUrls | Product URLs, same as Product URLs |
| History store | stateStoreName | Optional key-value store for what earlier runs saw (default cleanpull-any-store-monitor); pick one when running with a scoped token in Restricted access mode |
Example inputs
A competitor watchlist, checked daily for changes:
{"productUrls": ["https://www.allbirds.com/products/mens-tree-runners","https://www.zwilling.com/us/miyabi-evolution-5-inch-prep-knife-fine-edge--34025-133/34025-133-0.html"],"changesOnly": true,"monitorName": "competitors"}
The first 200 products of a store, only those with "bottle" in the URL:
{ "sitemaps": ["nalgene.com"], "maxProductsPerSitemap": 200, "urlFilter": "bottle" }
Price drops of 5% or more and stock changes only:
{"productUrls": ["https://www.monbento.com/catalog/product/view/id/5348"],"changesOnly": true,"changeTypes": ["price", "stock"],"minPriceChangePercent": 5}
Price tracker output
One row per product.
Example rows
A real row:
{"recordType": "product","url": "https://www.zwilling.com/us/miyabi-evolution-5-inch-prep-knife-fine-edge--34025-133/34025-133-0.html","domain": "zwilling.com","platform": "salesforce-commerce-cloud","source": "url","title": "MIYABI Evolution 5-inch Prep Knife, Fine Edge","brand": "MIYABI","gtin": "4009839334917","mpn": "34025-133-0","price": 129.99,"currency": "USD","listPrice": null,"onSale": false,"availability": "InStock","inStock": true,"priceMin": 129.99,"priceMax": 129.99,"variantCount": 0,"image": "https://www.zwilling.com/on/demandware.static/-/Sites-zwilling-master-catalog/default/dw35140085/images/large/34025-133-0_1.jpg","rating": 5,"reviewCount": 70,"dataSources": ["json-ld", "open-graph"],"priceSource": "json-ld","readThroughResidentialProxy": false,"changes": [],"firstSeen": true,"scrapedAt": "2026-10-13T22:10:01.035Z"}
A variant (in variants) looks like this:
{"id": "41884546990160","sku": "A12498M080","gtin": "196942291030","title": "8","options": { "Size": "8" },"price": 100,"listPrice": null,"currency": "USD","availability": "OutOfStock","inStock": false,"stockQuantity": null,"url": "https://allbirds.com/products/mens-canvas-runner-nz?variant=41884546990160"}
Changes and removed products
A change looks like { "type": "price", "field": "price", "from": 129.99, "to": 109.99, "percent": -15.4 }; variant changes name the variant. A product gone since the last run (its page answers 404, it is missing from a Shopify store's whole catalog on two runs in a row, or it redirects to the home page, a category or another site on two runs in a row; the first redirect is only a warning, not billed) gives one row with "removed": true, removedHow (not-found or redirected) and redirectedTo.
Also: canonicalUrl, finalUrl (after redirects), sku, productId, category, discountPercent, stockQuantity (where the store publishes it), variantsInStock, images, description, condition, seller, priceValidUntil, sitemap (for products found through one), previous (last run's values, on changed rows).
The run's final status message summarises the key numbers in plain text after "Done: N results.": per page its price and currency, the compare-at price and discount when on sale, stock, the variant price range with how many variants are in stock, and changes since the last run, ending "More in the dataset." when not everything fits.
Dataset views: Products, Variants (one row per variant) and Changes. RUN_SUMMARY in the key-value store gives the outcome (COMPLETE, PARTIAL, NO_CHANGES, EMPTY, FAILED), the platforms seen, charges, and every product that could not be read, with the reason.
Pricing
| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Product (a delivered row) | $1.50 | $1.50 | $1.35 | $1.20 |
| Product checked, unchanged (Changes only) | $0.50 | $0.50 | $0.45 | $0.40 |
| Product from a protected store (add-on, only for stores that block standard addresses) | $4.00 | $4.00 | $4.00 | $4.00 |
| Provider record (add-on per Walmart, Target, Best Buy, eBay or Etsy product read) | $6.00 | $3.00 | $2.70 | $2.40 |
| Provider search (one per marketplace and run: all its products in one job) | $30.00 | $15.00 | $15.00 | $15.00 |
Per 1,000 products. Each run also has a $0.00005 start fee. The add-on applies once per product read, only when the store's product page had to be read through residential addresses; optional store API calls never trigger it. Pages read that way are capped at 600 KB transferred, compressed as sent (a larger one is not read or charged); Shopify product data and WooCommerce Store API answers (a few KB) never add it. Provider records and provider searches are billed with the product's row or check, never for a product the service could not read; a job starts only when its products fit your spending limit and Max products with the rest of the run. A daily check of 100 competitor products with Changes only is about 3,000 checks a month: $1.50 on the Free and Bronze plans, plus the products that changed.
Limits
- Stores that publish no product data in their pages (no structured data, analytics event or platform API) cannot be read; the run summary names them.
- Amazon is not read here: it has its own CleanPull actor. Walmart Canada and Best Buy Canada are not read.
- Walmart, Target, Best Buy, eBay and Etsy: product URLs only (their sitemaps are not listed), US sites only (eBay also ebay.de, ebay.co.uk and ebay.es), no variants.
- eBay outside the US: an ebay.de, ebay.co.uk or ebay.es URL is read as the same item on ebay.com (eBay item numbers are the same on every site), so the row has the listing's own price in its own currency (
currency: EUR for a German seller, GBP for a UK seller), and English title and condition words. The row keeps your URL (canonicalUrlis the ebay.com one). Only item links (/itm/<number>) go this way; another page on those sites is read as any other store's, and the run notes it. A variation in the link (var=) is not carried over, so the row has the listing's default variation, and the run notes it. Two of your links to one item (on .de and .co.uk, say) are read once: each gets its row, and the provider record is billed once. - Prices are the store's public prices for a visitor from the proxy's country, without a sign-in, coupons or cart discounts.
- Gzipped sitemaps (
.xml.gz) are skipped; give the plain sitemap or product URLs. - robots.txt is read only to find a store's sitemaps; its Disallow rules are not applied. Read a store at a pace and scale its terms allow (Products at a time per store is 2 by default).
- Another dataset (Dataset of products,
datasetId) is read only when you pick it in the form, which gives this actor read access to that one dataset. The actor runs with limited permissions and cannot see your other storages. - WooCommerce variations: up to 100 per product.
- Nothing found: when nothing could be read because it is not there (a product address the store has no page for, a page with no product data, a sitemap with no products, a retailer it does not read), the run still succeeds, with one free
recordType: "unreadable"row per item giving thereason; nothing is charged. These free rows come only when the run delivers nothing; otherwise the misses are listed inRUN_SUMMARY. A run near its time limit stops starting products, delivers what it read and lists the rest inRUN_SUMMARY(as free rows when it delivered nothing). If the run delivers nothing and any product was blocked or failed with an error (not one of these misses), the run ends FAILED with the reasons inRUN_SUMMARY, no free rows are given, even for the misses, and nothing is charged.
FAQ
How much does price tracking cost per product per day?
Checking 100 competitor products once a day with Changes only costs $0.05 a day on the Free and Bronze plans (about $1.50 a month), plus $0.0015 for each product that changed; the first run, the baseline, delivers every product at $0.15. Without Changes only, the same 100 products cost $0.15 a day. A product from a store that blocks standard addresses adds $0.004 when it had to be read through residential addresses. Walmart, Target, Best Buy, eBay and Etsy products add $0.003 each on Bronze ($0.006 on the Free plan), delivered or checked, plus $0.015 once per marketplace per run on Bronze ($0.03 on Free), so 10 Walmart products checked daily with Changes only cost about $0.05 a day on Bronze and about $0.095 on Free. Pages that could not be read, sitemap pages that are not products and a first redirect (only a warning) are never charged. Each run also has the start fee, and higher Apify plans pay less (see Pricing below).
How often should I check competitor prices?
Daily suits most watchlists, and hourly works for fast-moving stores. With Changes only and a schedule, each run returns only the products that changed since the last run under the same Monitor name; Changes to report picks which changes count, and Smallest price change (%) keeps small moves out. A product that redirects away or leaves a Shopify catalog is reported as removed only when two runs in a row see it, so a daily schedule confirms a removal within a day.
What is the difference between price, list price and the price range?
price is what the store charges now, in currency. listPrice is the was-price or compare-at price the page shows; when it is above the price, onSale is true and discountPercent gives the cut. priceMin and priceMax span the variants' prices, and each variant in variants has its own price, listPrice and currency. On a store read from its Shopify catalog, prices are in the shop's base currency, which the warning names.
Why is a price, stock count or variant missing?
- Not for sale: a product that cannot be bought has
price: null, never 0. - Stock count:
stockQuantityis filled only where the store publishes units; otherwiseavailabilityandinStockgive the stock state. - No variants: Variants is off, the product is from Walmart, Target, Best Buy, eBay or Etsy (read without variants), and a WooCommerce product lists up to 100 variations.
- Shopify catalog: a store whose bot check refuses every product address is read from its catalog, without stock counts, and the warning says so.
- No rating on Shopify: Shopify product data has no reviews; turn on Read the page on Shopify too.
- No row at all: a page that could not be read is listed in
RUN_SUMMARYwith the reason and is not charged. When the whole run delivers nothing and every item is a miss (not there, no product data, a retailer it does not read), each gets a freerecordType: "unreadable"row with thereason; if any item was blocked or failed with an error, the run ends FAILED with no free rows.
Which online stores and platforms does it support?
Shopify, WooCommerce, Magento, BigCommerce, Wix, Squarespace, PrestaShop, Shopware, Salesforce Commerce Cloud and custom stores whose pages publish product data, plus Walmart, Target and Best Buy (US sites), eBay (ebay.com, ebay.de, ebay.co.uk and ebay.es) and Etsy by product URL. Amazon has its own CleanPull actor and is not read here; Walmart Canada and Best Buy Canada are not read.
Can I use the price tracker through the API?
Yes. Start runs through the Apify API or an API client, and read the dataset through its Products, Variants (one row per variant) and Changes views, or the RUN_SUMMARY record with the outcome, platforms, charges and every product that could not be read. Only these fields (fields) trims each row to the keys you need, and the final status message sums up each page's price and stock in plain text.
Does it work with Google Sheets, Make, Zapier or Claude?
Yes. Apify's integrations send each run's results to Google Sheets, Make, Zapier, webhooks and other tools, and a schedule keeps them updated. From Claude, the MarketMage plugin checks a product page's price now or sets up a daily or weekly watchlist of competitor prices and stock in a chat.
Is it allowed to track competitor prices?
The actor reads public product pages and store data as a signed-out visitor sees them: no login, no account and no customer data. Walmart, Target, Best Buy, eBay and Etsy pages come through a third-party web data provider. How you use the data, and following the laws and terms that apply to you, is your responsibility. This is not legal advice.
Related actors
Other CleanPull actors for monitoring:
- Shopify Scraper: every product and variant from any Shopify store, with stock and sales estimates.
- Catalog Matcher: match your catalogue to competitors' and find price gaps.
- Watch Digest: one scheduled digest of price, stock, rank and review changes.
- Alerts Sender: send results to email, Slack, Discord, Teams or a webhook.
Use it from Claude
The MarketMage plugin runs these actors from a Claude chat.
Found it useful? A rating on the Store helps others find it.
Changelog
- 0.2.x, moved stores (2026-11-09): a store given for its sitemaps whose address now redirects to another domain (a rebrand) is listed on the new domain, following up to 3 moves, and the status message says where it was read. Prices and events unchanged.
- 0.2.10, faster Shopify catalog reads (2026-11-06): a Shopify store that sends product addresses to its bot check goes to its catalog at once, and a product-data request the store throttles with a long wait (Shopify asks for 60 s) counts as refused instead of being waited out: allbirds.com reads in a few requests instead of about four minutes. Prices and events unchanged.
- 0.2.9, Shopify catalog (2026-11-06): Shopify stores whose bot check refuses every product address, product data included (allbirds.com), are read from the store's catalog (
/products.json), which the bot check does not cover. One walk per store per run serves all its products (it stops at the page holding the product, at the last page, or at 5,000 products). Prices are the shop's base currency (from its/meta.json), with a warning saying so; there are no stock counts. A watched product missing from a complete walk is reported as gone from the catalog when the next run sees the same (the first miss is a free warning); one beyond the 5,000 cap never is, and is read through its product data or page instead. The catalog is read through direct and datacenter addresses only. Prices and events unchanged. - 0.2.8, Shopify bot check (2026-11-06): Shopify stores that send visitors to their bot check (allbirds.com) are read again: when the product data is refused on its usual route and the store shows it is on Shopify, the product data is asked for through stronger proxies, before or instead of the page, without moving the store's pages to pricier proxies, and the bot-check page is never followed. Failure and status messages show addresses without tokens (one-time challenge tokens, session ids, long values); parameters such as
?variant=stay. Prices and events unchanged. - 0.2.7, status summary (2026-11-06): the final status message now summarises each page's key numbers after "Done: N results." (price, sale price and discount, stock, variant range, changes since the last run), so a reader can often skip the dataset read. Prices and events unchanged.
- 0.2.x, eBay Europe (2026-11-04): ebay.de, ebay.co.uk and ebay.es product URLs are read through the marketplace data service as the same item on ebay.com, in the listing's own currency (before, they were read as any other store's pages, which eBay blocks). Prices written with a decimal comma ("12,95 €") are read as 12.95. Event prices unchanged; ebay.de, ebay.co.uk and ebay.es product reads now carry the provider record and provider search, as ebay.com's do.
- 0.2.x, reliability (2026-11-01): a product address on a store that does not exist (no such domain) now ends with a free
unreadable'not found' row instead of a failed run; the address is checked before any proxy is used, so it costs nothing. Prices and events unchanged. - 0.2.x, billing fix (2026-10-31): two or more products from the same marketplace that finished together could each be charged the provider search, which is due once per marketplace per run. It is now charged once, as documented. Prices and events unchanged.
- 0.2.x, reliability (2026-10-24): runs that find nothing (a product address the store has no page for, a page with no product data, a sitemap with no products, a retailer it does not read) end SUCCEEDED with a free
unreadablerow per item saying why, instead of FAILED; a run stops starting products before its time limit and ends with what it read, never TIMED-OUT. A run where the store refused on every route for every product still fails. Prices and events unchanged. - 0.2 (October 2026): Walmart, Target, Best Buy (US), eBay and Etsy product URLs read through CleanPull's marketplace data service, with watchlists and change rows as for any store. New events: provider record and provider search.
- eBay and Etsy URLs now go through the service. 0.1 read them as any other store's pages, free of add-ons; from 0.2 each eBay or Etsy product read carries a provider record, and each run that reads them a provider search per marketplace (see Pricing).
- A one-off change on the first 0.2 run of a watchlist: the service's image and stock for an eBay or Etsy listing can differ from what 0.1 read from the page, so a watchlist may report an image or stock change once.
- eBay and Etsy sitemaps (and Walmart, Target and Best Buy ones) are rejected with a note: give the product URLs to watch instead.
- A run stopped by your spending limit or Max products before the service's products are read cancels their jobs.
- 0.1 (October 2026): products from any shop by URL, sitemap or dataset; Shopify product data, structured data, Magento, analytics and Open Graph reads; WooCommerce Store API with variations; per-store proxy ladder; changes since the last run, including removed pages.