Woolworths Price Scraper & Monitor (Australia)
Pricing
from $0.80 / 1,000 product with a prices
Woolworths Price Scraper & Monitor (Australia)
Woolworths scraper and price tracker for Australia: prices, specials, was-prices, unit prices and stock by product URL or code, or a catalog export, never charged for failed results, unpriced products or unchanged products left out. Unofficial.
Pricing
from $0.80 / 1,000 product with a prices
Rating
0.0
(0)
Developer
COMPASS DEV
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
a day ago
Last modified
Categories
Share
Woolworths scraper and price tracker for Australia that returns Woolworths prices, specials, was-prices,
unit prices and stock for any Woolworths product (by product URL or code, or a catalog export from the Woolworths
sitemap) as flat rows — and never charges for failed results, for products without a price, or for unchanged products
left out with onlyChangedProducts.
Unofficial. Not affiliated with Woolworths Group.
It also tracks price changes between runs (previous price, price change, new and changed flags) and can return specials only. Results come as clean, flat rows that export well to CSV, Excel, JSON or Google Sheets.
You pay only for products with a price. Failed and blocked products are free.
Quick start
-
Click Start. The form is already filled in with two products (a product URL and a product code both work):
{"products": ["https://www.woolworths.com.au/shop/productdetails/888140/woolworths-full-cream-milk","83273"]}The other fields keep their defaults (products mode, datacenter proxy).
-
In under a minute you get two rows with the current price, was-price, special flag and unit price (see Output example). On the Free plan this run costs $0.003 plus Apify's Actor-start charge.
-
Replace them with your own products: the code is the number in the product page's address (
…/productdetails/888140/…→888140). Export the results as CSV, Excel or JSON from the Output tab.
Use cases
- Weekly shopping-list price tracker. Put the products you buy in a list with a
stateName, schedule the run daily or weekly, and see each product'spriceChangesince the last run. - Specials finder. Add
"onlySpecials": trueto your product list to see which of your products are on special today, with the was-price next to the current price. - Brand and retail price research. Brands and analysts monitor the online shelf price, special and availability of a set of products at Woolworths, or export priced products from the catalog for price research.
What it does
| Mode | Use it for | Input |
|---|---|---|
| Products (default) | Daily/weekly price monitoring of specific products | Product URLs or product codes |
| Catalog | Catalog export: priced products from the official Woolworths sitemap (~42,000 listed) | How many priced products (maxItems) |
For every product you get: name, brand, size, price, was-price, special flag, unit price (e.g. $1.65 per 1L),
availability, category, product URL and image URL. With a tracking name (stateName) you also get the
previous run's values and what changed (see Track price changes).
Input examples
Monitor three products (URLs or codes both work):
{"products": ["https://www.woolworths.com.au/shop/productdetails/888140/woolworths-full-cream-milk","83273","208064"]}
Export 500 priced products from the catalog:
{ "mode": "catalog", "maxItems": 500 }
Use Australian residential IPs instead of the default datacenter proxy (adds a surcharge, see Pricing):
{ "products": ["888140"], "proxy": "residentialAU" }
Daily price watch that returns only what changed (see Track price changes):
{ "products": ["888140", "83273", "208064"], "stateName": "my-weekly-basket", "onlyChangedProducts": true }
The first 50 products on special from the catalog:
{ "mode": "catalog", "maxItems": 50, "onlySpecials": true }
| Field | Default | Description |
|---|---|---|
mode | products | products or catalog |
products | — | Product URLs or codes (products mode). Duplicates are checked once. |
maxItems | 100 | Catalog mode: how many priced products to deliver (max 50,000), in sitemap order |
includeUnpricedProducts | false | Catalog mode: also output products without a price at the default online store (free) |
stateName | — | Optional tracking name. Remembers each product's values between runs and fills the change fields. |
onlyChangedProducts | false | Needs stateName. Output only products that changed since the last run, or are new. Others are not output and not charged. |
onlySpecials | false | Output only products on special. Others are not output and not charged. In catalog mode, maxItems counts specials delivered. |
proxy | datacenter | datacenter (cheapest, works for Woolworths) or residentialAU |
maxConcurrency | 5 | Parallel sessions (1–10). Each makes at most 1 request per second. |
Field names from other tools: productId, itemId, url, urls, startUrls, productIds (→ products);
maxResults, limit (→ maxItems); the standard proxyConfiguration (→ proxy; the RESIDENTIAL group →
residentialAU).
Output example
{"status": "ok","error": null,"attempts": 1,"input": "83273","productCode": "83273","name": "Sanitarium So Good Barista Oat Long Life Milk 1L","brand": "Sanitarium","size": "1L","price": 3,"wasPrice": 4,"isOnSpecial": true,"unitPrice": 3,"unitPriceUnit": "1L","currency": "AUD","availabilityStatus": "available","category": "Milk > Long Life Milk","url": "https://www.woolworths.com.au/shop/productdetails/83273/sanitarium-so-good-barista-oat-long-life-milk","imageUrl": "https://cdn0.woolworths.media/content/wowproductimages/large/083273.jpg","store": "default online store","previousPrice": null,"previousWasPrice": null,"previousIsOnSpecial": null,"previousAvailabilityStatus": null,"priceChange": null,"changedSinceLastRun": null,"firstSeen": null,"scrapedAt": "2026-09-28T08:53:01.329Z"}
The change fields stay null unless you set a tracking name (stateName).
Status of each row
Products mode: every product you list gets exactly one row. Catalog mode: products without a price
are skipped, unless includeUnpricedProducts is true; failed products are always shown. Filters: with
onlySpecials or onlyChangedProducts, products the filter leaves out are not output and not charged;
failed products are still shown (free), so you always see errors.
status | Meaning | Charged? |
|---|---|---|
ok | Product found. See availabilityStatus. | Yes, only when the row has a price |
no_data | Product discontinued or removed from the catalog | No |
failed | We couldn't get an answer (see error and attempts), the input wasn't a Woolworths product, or the run stopped after a block | No |
availabilityStatus on ok rows:
| Value | Meaning | Price | Charged? |
|---|---|---|---|
available | Sold and available online | Current price | Yes |
unavailable_online | Sold, but currently unavailable online (e.g. out of stock) | Current shelf price is kept | Yes |
not_ranged | Listed by Woolworths but not sold at the default online store | null (never 0) | No |
Pricing
Pay per product with a price. Price depends on your Apify plan:
| Apify plan | Per product | Per 1,000 products |
|---|---|---|
| Free | $0.0015 | $1.50 |
| Bronze | $0.0010 | $1.00 |
| Silver | $0.0009 | $0.90 |
| Gold | $0.0008 | $0.80 |
| Platinum | $0.0007 | $0.70 |
| Diamond | $0.0006 | $0.60 |
- Residential surcharge: +$0.0020 per product with a price, only when you choose
"proxy": "residentialAU". - Apify's standard Actor-start charge applies per run.
- Never charged for failed results:
failedandno_datarows and products without a price are free. Products left out byonlySpecialsoronlyChangedProductsare not output and not charged. - Your maximum charge is respected: the Actor never charges past your run's spending limit. When the limit is reached it stops; products it could not pay for are not returned.
Track price changes
Give your list a tracking name and run it on a schedule. Each run compares every product with the previous run of the same tracking name:
- Create a task with your products and a
stateName, for example{"products": ["888140", "83273"], "stateName": "my-weekly-basket"}. - Add an Apify schedule (for example, every morning at 7:00 Sydney time).
- Every row now includes
previousPrice,previousWasPrice,previousIsOnSpecial,previousAvailabilityStatus,priceChange(current − previous, in AUD),changedSinceLastRunandfirstSeen. - Want only the news? Add
"onlyChangedProducts": true. Unchanged products are then not output and not charged, so a quiet day costs almost nothing.
What counts as a change: price, was-price, special flag or availability. A product you tracked that
disappears from Woolworths shows up once as no_data with changedSinceLastRun: true (free).
How it works: the last seen values are kept in a named key-value store in your own Apify account
(woolworths-monitor-<tracking name>). Use a different tracking name for each list. Only products actually
checked in a run are updated. If a run stops early (for example after a block), the other products keep their
last known values, so nothing is lost. On the first run every product has firstSeen: true and the
previous… fields are null.
Use it from AI agents
- Works through Apify's MCP server, so AI assistants (Claude, ChatGPT and other MCP clients) can find and call it.
- Smallest input:
{"products": ["888140"]}— every other field has a sensible default. - One flat row per product, with an explicit
statusandavailabilityStatus, easy for an agent to read. - For a recurring watch, pass a
stateNameand"onlyChangedProducts": true: the agent then gets only what changed, withpriceChangeand the previous values in the same row. - Small lists are fast: in our tests a 1-product run took about 3–5 seconds and a 5-product run about 10 seconds (default settings, datacenter proxy).
- x402 payments: the Actor is pay-per-event only, with no usage fees, limited permissions and no Standby mode, so agents can pay per product with x402.
Copy-paste call (your Apify token in APIFY_TOKEN):
curl -s -X POST "https://api.apify.com/v2/acts/mouadapi~woolworths-price-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"products": ["888140"]}'
The same call from JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('mouadapi/woolworths-price-monitor').call({ products: ['888140'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Limits (by design)
- Default online store only. Prices and availability are those Woolworths shows for its default online store. Store or postcode selection is not supported, so regional prices may differ.
- No keyword search or category browsing. Woolworths asks crawlers not to crawl its search pages (robots.txt), and we respect that. Use product URLs/codes, or catalog mode.
- Catalog mode follows sitemap order (roughly alphabetical by product name), not category order. About a third of catalog products have no price at the default online store. They are skipped by default and never charged.
- Polite speed: at most 5 requests per second with the default 5 sessions. In our tests, 1,000 products took about 10 minutes at the default 256 MB memory, and about 6.5 minutes at 512 MB (Apify gives more CPU to runs with more memory). Raise the run's memory for large catalog exports.
Known issues
No open bugs are known in the current version. Things that can surprise you:
- Woolworths can keep a removed product in its sitemap for a while. It comes back as
no_data(free). - Catalog mode with
onlySpecialschecks products in sitemap order until it hasmaxItemsspecials, so it checks many more products than it returns and takes longer. Products that are not on special are free. - Each price is the one Woolworths showed at
scrapedAt; Woolworths can change prices later the same day.
Reliability
- If Woolworths blocks a request or resets a connection, the Actor stops and tells you how far it got
(checked / total). It doesn't try to get around blocks and never switches proxies automatically.
Unchecked products get free
failedrows. - Temporary errors (timeouts, HTTP 5xx) are retried with a short backoff.
- If Woolworths answers "too many requests" (HTTP 429), that session pauses for 1, then 2, then 4 minutes on the same connection, and if it's still refused after that, the run stops as it does for a block.
- A daily health check runs known products and alerts us if anything breaks.
FAQ
How much does it cost? $1.50 per 1,000 products with a price on the Free plan, down to $0.60 on Diamond (see Pricing), plus Apify's small Actor-start charge per run. Checking 10 priced products on the Free plan costs $0.015.
Am I charged for failed products? No. Only rows with a price are charged. failed and no_data rows, products
without a price and products left out by your filters are free.
What are the limits? Default online store only (no postcode or store selection), no keyword search or category browsing, and 1 request per second per session (5 sessions by default). See Limits.
Is this allowed? The Actor reads public product pages that Woolworths' robots.txt allows. It uses no login and collects no personal data.
How do I monitor prices every day? Save your product list as a task with a stateName and add an Apify
schedule (for example, every morning). Each run's dataset is a dated price snapshot with the change since the
last run; add onlyChangedProducts to get only the changes. Use Apify integrations or webhooks to send
results to Google Sheets, Slack or your database. See Track price changes.
Why is a product no_data? Woolworths has discontinued or removed it (it may still appear in the
sitemap). You are not charged.
Why does a product have no price? It is listed by Woolworths but not sold at the default online store
(not_ranged). You are not charged for it.
Also by the same author: DNS Lookup & SSL Certificate Checker — bulk DNS records, SPF/DMARC and SSL certificate expiry for many domains.