Coles, Woolworths & ALDI Scraper avatar

Coles, Woolworths & ALDI Scraper

Pricing

from $1.05 / 1,000 products

Go to Apify Store
Coles, Woolworths & ALDI Scraper

Coles, Woolworths & ALDI Scraper

Scrape Australian grocery prices from Coles, Woolworths and ALDI in one run: price, was-price, discount, unit price, stock, category, ingredients and nutrition. Compare the three chains on one row, watch price changes, or list stores near a postcode.

Pricing

from $1.05 / 1,000 products

Rating

5.0

(1)

Developer

Matvey

Matvey

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

a day ago

Last modified

Share

Coles, Woolworths & ALDI Scraper reads all three Australian supermarkets in one run and hands back one table: product, brand, size, price, was-price, discount, price per unit, availability, category and a link. Ask for milk and you get what Coles sells, what Woolworths sells and what ALDI sells, in the same columns, ready for a spreadsheet, a database or an AI agent.

Three things this does that a single-chain scraper cannot. It can put the same product from the three chains on one row with the three prices side by side and name the cheapest. It can watch prices: give a run a name, schedule it, and every later run returns only what moved — dropped, risen, gone on special, come back in stock. And it reads the label — ingredients, allergens, Health Star Rating, the nutrition panel and the country of origin — for the chains that publish it.

No login, no API key, no browser. Errors are never billed, and a watch that finds nothing new costs nothing.

What is the Coles, Woolworths & ALDI Scraper?

Australian grocery prices are public on each chain's website and nowhere together. Coles sits behind a bot check, Woolworths answers its own search service, ALDI runs a product API — three different shapes, three different names for the same column, and a different set of house brands each. This Actor is the layer that hides all of that: one input, one row shape, three chains.

Who uses it: price-comparison and cashback apps, FMCG and category managers checking where their product sits against the private label, journalists and researchers working on cost of living, market-research teams building a price index, and AI agents asked "what does a litre of milk cost in Australia this week".

What data does it return?

FieldExample
chainName, chainColes · Woolworths · ALDI
name, brand, sizeColes Full Cream Milk · Coles · 2L
sizeNormalised2000ml — the same size written the same way for every chain
price, wasPrice, isOnSpecial3.40 · 4.10 · true
savings, savingsPercent0.70 · 17
unitPrice, unitMeasure, unitPriceText1.70 · 1l · $1.70 / 1L
inStock, availability, purchaseLimittrue · InStoreAndOnline · 20
category, subCategory, departmentMilk · Dairy, Eggs & Fridge · DAIRY
barcode, ratingAverage, ratingCount9300633636364 · 4.6 · 812
url, imageUrl, productIdlink to the product page and its photo
matchKey`2000ml

Measured on 16 September 2026, house-brand full cream milk came back as Coles $3.40, Woolworths $3.40, ALDI (Farmdale) $3.39 for 2L, and $4.95 at all three for 3L. That is the kind of row this exists to produce.

Whole aisles, not just keywords

Paste a Coles category link (https://www.coles.com.au/browse/dairy-eggs-fridge/milk) or an ALDI category key (970000000) into 📂 Category pages and the Actor walks the aisle instead of guessing at a keyword. Woolworths is the exception and is said so plainly: its category service refuses an anonymous request, so Woolworths is covered by keywords. Coles category pages are also the path its own robots.txt allows, unlike its search.

Ingredients, allergens and nutrition

Turn on 🥗 Ingredients, allergens and nutrition and the rows carry ingredients, allergensContains, allergensMayContain, healthStarRating, nutrition (the panel as name-and-value pairs), servingSize, servingsPerPackage, countryOfOrigin, storageInstructions and gtin.

Where it comes from, honestly: Woolworths ships the whole label inside its normal answer, so it costs nothing extra and is always there. Coles keeps the label on the product page, so each Coles product needs one more request — charged as its own add-on and capped by Maximum label lookups per run. ALDI publishes no label data to an anonymous visitor at all, and those columns stay empty for ALDI rows rather than being guessed at.

Your own store: aisle and shelf stock at Coles

Put your Coles store number into 🏬 Coles store number and the Coles rows stop being the national range: aisle tells you where in the shop the product sits ("Dairy"), and availableQuantity becomes that store's shelf count instead of a warehouse figure. Measured on 16 September 2026, the same milk read 2,146 units without a store and 260 with one, with the aisle filled in.

Prices themselves do not change: all three chains publish one national online price, and this Actor does not pretend otherwise.

Stores near a postcode

Switch What a row should be to One store per row and give a 📍 Postcode (or a latitude and longitude). You get the Woolworths and ALDI supermarkets near that point, sorted by distance: name, street address, suburb, state, postcode, phone, distance in kilometres, whether it is open right now and the trading hours for the days ahead.

Coles is the one missing, and the reason is not laziness: its store finder answers only for the location it reads from the caller's own address, so there is no way to ask it about a postcode you choose. Rather than return a list for the wrong city, the Actor says plainly that Coles was skipped. Coles' own store number can still be given directly in 🏬 Coles store number for the aisle and shelf-stock fields.

The postcode table behind this is built from the chains' own published store addresses, so no third-party geocoder is involved. It covers the 800 Australian postcodes that actually have a supermarket in them; for anywhere else, pass a latitude and longitude instead and the lookup works the same.

One comparison per row

Switch What a row should be to One comparison per row and the output changes shape: one row per product, with colesPrice, woolworthsPrice, aldiPrice, cheapestChain, cheapestPrice, priceGap, priceGapPercent and bestUnitPriceChain, plus the name and link each chain had.

Matching across chains is done on the normalised size and the words of the name, and by default two products only meet if the brand agrees — with one deliberate exception: the three house brands are treated as comparable to each other, because Coles Full Cream Milk, Woolworths Full Cream Milk and ALDI's Farmdale are exactly what a shopper weighs against one another. Set How strictly to match to Equivalent to also pair different brands of the same size and wording.

Every comparison row carries matchType (own-brand, same-brand, equivalent, single) and matchConfidence between 0 and 1, so a heuristic never passes itself off as a certainty.

How this compares with a single-chain scraper

Every other Australian grocery scraper on the Store covers one chain. Measured against them on 16 September 2026:

This ActorA typical single-chain scraper
Chains in one runColes, Woolworths and ALDIone
The three prices on one rowyes, with the cheapest chain and the gapno — you match the products yourself
Sizes made comparableyes2L, 2 litre and 2000ml all become 2000mlno
Only what changed since the last runyes, on any keyword or aisle, in all three chainsone actor does it, for one chain
Ingredients, allergens, Health Star, nutritionyes for Woolworths and Colesno
Aisle and shelf stock for your own storeyes at Coles, with the aisle nameno
Store finder by postcodeyes, Woolworths and ALDIno
Category pages instead of keywordsyes, Coles and ALDIsome
Filters: specials, minimum discount, price cap, in stockyesrarely
Failed requests and empty checksnever billedusually billed as a run
Output schema published for agents91 described fields, six table viewsoften none at all

Where a single-chain scraper is still ahead: the ones built only for Coles can return a Coles store list for a postcode, which this Actor cannot, because Coles answers that question only for the caller's own location.

Watching prices

Give the run a watch name and schedule it. The first run delivers what is there now and remembers every price. Every run after returns only rows that moved, each carrying changeType, previousPrice, priceChange and priceChangePercent:

  • price-drop, price-rise — the shelf price moved
  • special-started, special-ended — a discount began or finished
  • back-in-stock, out-of-stock — availability flipped
  • new — a product that was not in the range last time

Nothing moved? An empty dataset, a status message saying so, and no charge. Different watch names keep separate memories, so dairy and nappies never see each other's history.

How much does it cost?

  • $1.50 per 1,000 products — one row, one charge.
  • $5 per 1,000 comparison rows — a comparison row is assembled from two or three chain rows and is charged once instead.
  • $2 per 1,000 stores — one supermarket with its address, hours and coordinates.
  • $2 per 1,000 label lookups — charged only for Coles products whose label had to be read from its own page. Woolworths labels are free, because they arrive with the product.
  • Error rows, filtered-out products and a watch that finds no movement: $0.

Sweeping twenty keywords across three chains, 100 products deep, is about 6,000 rows — around $9. Watching the same list daily after the first run costs only the movements, usually a few hundred rows a day.

Apify's free plan includes $5 of platform credit, which is roughly 3,300 products.

Residential proxy traffic for Coles is paid by this Actor, not by you — the per-row price already covers it.

How to use it in four steps

  1. Type what you want to track in 🔎 What to look upmilk, nappies, coffee, olive oil.
  2. Leave all three chains ticked, or untick the ones you do not need.
  3. Press Start. The first run returns products from all three chains.
  4. To track prices instead of listing them: fill in 🔔 Watch name, then open the Schedules tab and run it daily. Connect Slack, e-mail, Google Sheets, Zapier, Make or a webhook under Integrations and the movements land where you work.

⬇️ Input

{
"keywords": ["milk", "bread", "eggs"],
"chains": ["coles", "woolworths", "aldi"],
"output": "comparison",
"maxProductsPerKeyword": 60,
"onSpecialOnly": false,
"watchName": "weekly-basket"
}

Paste Coles, Woolworths or ALDI product links into 🔗 Product URLs. The chain is recognised from the link, so the three can be mixed in one list.

Filters

🏷️ Only products on special, 📉 Minimum discount, 💲 Maximum price and 📦 Only what is in stock narrow what is delivered — and what is billed, because a filtered-out product is not charged.

⬆️ Output

{
"type": "product",
"chain": "aldi",
"chainName": "ALDI",
"productId": "000000000410925003",
"name": "FARMDALE Full Cream Milk 2L",
"brand": "FARMDALE",
"size": "2 l",
"sizeNormalised": "2000ml",
"price": 3.39,
"wasPrice": null,
"isOnSpecial": false,
"unitPriceText": "$1.70 per 1 l",
"inStock": true,
"category": "Dairy & Eggs",
"url": "https://www.aldi.com.au/product/farmdale-full-cream-milk-2l",
"currency": "AUD",
"scrapedAt": "2026-09-16T07:20:11.004Z"
}

Three table views come with the dataset: Products, Price comparison and Price changes. A failed request pushes one type: "error" row naming the chain and the reason, free of charge, and the run summary lands in the key-value store as SUMMARY.

Reliability, honestly

  • Woolworths and ALDI are read from their own services and answer in a fraction of a second.
  • Woolworths also refuses an address that has asked too often — its Akamai answers "Access Denied". The Actor notices and switches that chain to the proxy for the rest of the run instead of failing; this was found the hard way, by getting the development machine blocked while building the postcode table.
  • Coles is the hard one. Its bot check refuses datacenter addresses outright — by the evening of 16 September 2026 Apify's datacenter pool stopped being let in at all — so the Actor asks for residential addresses by default. Even then roughly half of the addresses are turned away on the first try, which is why a blocked page is retried up to eight times from a different address each time, with the challenge page recognised for what it is rather than parsed as an empty result. In testing that brings a keyword home on all but the unluckiest run; when a run does report Coles blocked, running it again is usually enough.
  • Prices are the national online prices each chain publishes to a visitor without a postcode or a store selected. Store-level and delivery-zone pricing is not read, and the Actor never claims to.

Use cases

Price comparison and cashback apps

One call, three chains, one schema, with the unit price already parsed — the part everyone builds by hand.

Category and brand managers

Watch your own SKUs and the private label next to them, and hear about a competitor's promotion the day it starts, not at the end of the month.

Cost-of-living research and journalism

A basket of staples, scheduled weekly, produces a clean price series with was-prices and discounts attached.

AI agents

A flat row shape, sensible defaults and no required fields, callable through the Apify API or the Apify MCP server.

Integrations

Run it from the Apify API, the Python or JavaScript client, n8n, Make, Zapier, Google Sheets, or as a tool for an agent via the Apify MCP server.

from apify_client import ApifyClient
client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("lergassy/au-grocery-scraper").call(run_input={
"keywords": ["milk"],
"output": "comparison",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["name"], row["cheapestChain"], row["cheapestPrice"])

❓ FAQ

The Actor reads only pages any visitor can open without logging in, and collects prices and product descriptions, not personal data. Public data collection is generally lawful in Australia and the EU, but what you do with the data can be regulated — consult a lawyer for your own case.

Are these the prices in my local store?

They are the national online prices each chain shows without a store or postcode selected. Some products differ store by store; this Actor does not claim to know which.

Why do I need a proxy?

Coles refuses unproxied traffic outright. Apify Proxy is on by default and needs no setup.

Can I compare products that are not the same brand?

Yes — set How strictly to match to Equivalent. By default only the same brand, or the three house brands together, are compared, so nothing is claimed that is not true.

What happens when a watch finds no changes?

An empty dataset and a $0 bill. That is the expected answer of a watch.

Can I use it through the Apify API or an MCP server?

Yes to both, and the input has no required fields, so an agent can call it correctly without reading this page.

Your feedback

Missing a chain, a field or a filter? Open an issue on the Issues tab or leave a review — both are read and answered.

You might also like

ActorWhat it does
Shopee ScraperProducts, prices and reviews across South-East Asia
Lazada ScraperThe same for Lazada
Tokopedia Reviews ScraperIndonesian marketplace reviews
Threads MonitorThe same watch idea, applied to Meta Threads