Coles Australia Scraper - Prices, Specials, Stock & History avatar

Coles Australia Scraper - Prices, Specials, Stock & History

Pricing

from $0.50 / 1,000 products

Go to Apify Store
Coles Australia Scraper - Prices, Specials, Stock & History

Coles Australia Scraper - Prices, Specials, Stock & History

Coles AU prices, specials and stock for any of ~878 stores (by id, postcode or all), ~27k products, with price history nobody else keeps: previous price, 30-day low, 90-day average and a real-discount check. Barcodes, nutrition, allergens, store directory. Nightly cache, so runs don't fail.

Pricing

from $0.50 / 1,000 products

Rating

0.0

(0)

Developer

Piotr Zimniak

Piotr Zimniak

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 hours ago

Last modified

Share

Independent tool, not affiliated with or endorsed by Coles Group. It reads only public product, price and stock data.

Get prices, unit prices, specials, stock levels for any Coles store, barcodes and full product details (ingredients, allergens, nutrition, country of origin) from coles.com.au as JSON, CSV, Excel or via API. It is the only Coles scraper on the Store that keeps price history (September 2026): the previous price and when it changed, the lowest price in 30 days, the 90-day average, and whether a "special" beats that history.

Why this one

  • Runs don't fail. Results come from a catalogue we refresh every night, so a run does not depend on Coles answering at that moment: you always get the latest data, in seconds. See Reliability.
  • Any store, or all of them. Prices, stock and aisle for the Coles stores you choose, by store id, by postcode (every store in it) or all ~878 stores, each store as its own rows. Plus the full store directory with addresses and opening hours.
  • Price history for every product. Previous price, when it changed, lowest price in 30 days, 90-day average, and a check whether a "special" is a genuine discount. Tracking since 27 September 2026, updated every night; see Price history.
  • Barcodes and nutrition at no extra cost for products already in our database; fetchFullDetails fills in the rest.
  • The whole catalogue in one run. Every product Coles sells online (~27k), straight from the nightly snapshot.
  • Clean data. Unit prices normalised to per kg, per litre and per item; multi-buy offers as text ("Buy 2 for $9.40"); sponsored duplicates removed.
  • Pay for results, not for runs. $0.80 per 1,000 products on the Free plan, down to $0.50, store rows included; the start fee is $0.00005 (a twentieth of a cent). See Pricing.
  • See it live. Last night's price moves, specials and the Coles store finder: crawlplant.com/coles-au.

What can you use it for?

  • Price monitoring: shelf and unit prices of the products you care about, on a schedule.
  • Store-level retail analytics: compare prices, stock and availability across Coles stores and regions.
  • Deal hunting and consumer research: half-price and multi-buy specials with a check on whether the discount is real.
  • Price-change alerts: products whose price changed since your last run, sent to email, Slack or Sheets.
  • Basket and store comparison: barcodes and per-kg prices make matching with other supermarkets straightforward (see our Woolworths Australia Scraper, same output format).
  • Nutrition and allergen apps: filter by dietary statement, allergens, sugar or protein.
  • AI agents: a fast, well-described tool for "find me the cheapest…" style questions (see Use with AI agents).

Quick start

  1. Click Try for free (or Start), keep the default input (search for milk, 100 products) and press Start. It finishes in seconds and costs $0.08 on the Free plan.
  2. Open the Output tab: a table of products with prices, unit prices, specials and stock. Switch views to Product details or Deals check, or export as JSON, CSV or Excel.
  3. Change the input using one of the ready-to-use examples below, and save it as a task to reuse or schedule it.

Modes

ModeWhat you give itWhat you get
search (default)queries: keywordsmatching products, like the site's search
categorycategoryUrls: any coles.com.au/browse/... link (or just dairy-eggs-fridge/milk)the products in that category
specialsoptional specialsGroups: halfprice, multibuy, onlineonlycurrent specials (all of them by default)
barcodesbarcodes: EAN / GTIN codesthose products, looked up in our database (~91% of Coles products have a barcode)
productsproductIds: product ids (the number at the end of a product link)those exact products, with full details
urlsurls: any Coles product, search, category or specials link, or a product idwhatever each link shows; sort and specials filters in the link are kept
catalognothing (set maxItems high, e.g. 30000)the whole catalogue from the nightly snapshot; filters apply
categoriesnothingdepartments and categories with their links
storesnothing, or storeIds / postcodesthe store directory: address, coordinates, phone, opening hours, click & collect id

Add storeIds, postcodes or allStores to any product mode (not catalog / categories) to get the prices and stock of those stores.

Ready-to-use examples

Paste any of these into the JSON tab of the input (or send them through the API).

1. Price check for a shopping list: the exact products you buy, by product id.

{ "mode": "products", "productIds": ["8150288", "439693", "7667368"] }

2. Prices and stock in specific stores: one row per product per store.

{ "queries": ["tim tam"], "storeIds": ["313", "7689", "584"], "maxItems": 10 }

3. Cheapest coffee per kg: a search sorted by unit price, within a price range.

{ "queries": ["coffee beans"], "sortBy": "unit_price_asc", "minPrice": 5, "maxPrice": 40, "maxItems": 50 }

4. Everything in a category, cheapest first:

{ "mode": "category", "categoryUrls": ["https://www.coles.com.au/browse/dairy-eggs-fridge/milk"], "sortBy": "price_asc", "maxItems": 500 }

5. This week's half-price specials:

{ "mode": "specials", "specialsGroups": ["halfprice"], "maxItems": 2000 }

6. New specials only, every Wednesday: schedule this weekly to get what just went on special.

{ "mode": "specials", "onlyNewSpecials": true, "maxItems": 5000 }

7. Price-drop alerts since your last run: schedule it daily; each run returns only products whose price changed.

{ "mode": "products", "productIds": ["8150288", "439693", "7667368"], "changedSince": "last-run" }

8. Best sellers on special in a department:

{ "mode": "category", "categoryUrls": ["pantry"], "sortBy": "best_sellers", "specialsOnly": true, "maxItems": 100 }

9. Allergy-safe: no peanuts or tree nuts, with full details:

{ "queries": ["muesli bars"], "excludeAllergens": ["Peanut", "Tree Nut"], "fetchFullDetails": true, "maxItems": 50 }

10. High-protein yoghurt (at least 8 g per 100 g):

{ "queries": ["yoghurt"], "minProteinPer100g": 8, "fetchFullDetails": true, "maxItems": 100 }

11. The whole catalogue (analytics, BI, price comparison sites): served from the nightly snapshot in seconds.

{ "mode": "catalog", "maxItems": 30000 }

12. New products this week:

{ "mode": "catalog", "onlyNew": true, "maxItems": 30000 }

13. 90-day price history for a few products:

{ "mode": "products", "productIds": ["8150288", "439693"], "priceHistoryDays": 90 }

14. Links straight from the browser:

{ "mode": "urls", "urls": [
"https://www.coles.com.au/product/coles-full-cream-milk-3l-8150288",
"https://www.coles.com.au/search/products?q=tim%20tam&sortBy=priceAscending",
"https://www.coles.com.au/on-special?filter_Special=multibuy"
] }

15. Your local Coles by postcode: every Coles store in each postcode, each as its own rows.

{ "queries": ["tim tam"], "postcodes": ["2000", "3000", "4000"], "maxItems": 10 }

16. One product in every Coles store (price and stock map of Australia):

{ "mode": "products", "productIds": ["8150288"], "allStores": true }

17. The store directory: every Coles store with address, coordinates and opening hours.

{ "mode": "stores", "maxItems": 1000 }

18. Products by barcode (EAN / GTIN, e.g. from a scanner or another store's data):

{ "mode": "barcodes", "barcodes": ["9300601186945", "9310072034485"] }

19. This week's biggest discounts, half price and better, biggest first:

{ "mode": "specials", "minDiscountPercent": 50, "sortBy": "discount_desc", "maxItems": 3000 }

20. Daily watch of a brand, including products that were delisted:

{ "mode": "catalog", "brands": ["Arnott's"], "changedSince": "last-run", "includeDisappeared": true, "maxItems": 30000 }

How to…

Scrape Coles half-price specials

Use example 5 (mode: specials, specialsGroups: ["halfprice"]), or multibuy / onlineonly for the other special types. Add minDiscountPercent: 40 to keep only big discounts, or use example 19 to rank them biggest first.

Get this week's Coles catalogue as data

The weekly catalogue changes on Wednesday. { "mode": "specials", "maxItems": 10000 } returns every product on special right now, with shelf price, was price, special type, multi-buy offer text and unit price. Schedule it every Wednesday morning (Sydney time), add postcodes to see it at your own stores, or use example 6 to get only what went on special this week. This is the catalogue's products as data, not the printed PDF.

Check if a Coles special is a real discount

Every product on special has discountCheck.verdict: genuine means the "was" price was really charged for at least 28 of the 90 days before the special; questionable means it wasn't. The verdict is given once a product has 28 days of price history (see Price history).

Compare Coles prices and stock across stores

Add storeIds, postcodes or allStores to any product mode (examples 2, 15, 16). Each product comes once per store with that store's price, inStock, availableQuantity and aisle.

Get every Coles store location and opening hours

mode: stores (example 17) returns every Coles store with address, coordinates, phone, trading and holiday hours.

Look up Coles products by barcode

mode: barcodes (example 18) with EAN / GTIN codes from the pack or from another store's data.

Get Coles prices per kg or per litre

Every product has pricePerKg, pricePerLitre or pricePerItem. Sort a search by unit price with sortBy: unit_price_asc (example 3).

Export the whole Coles catalogue

mode: catalog with maxItems: 30000 (example 11) returns every product Coles sells online from the nightly snapshot.

Input options

Stores (combine freely; each store gets its own rows):

  • storeIds: Coles store ids, the number at the end of a store page link, e.g. 313 in coles.com.au/find-stores/coles/wa/karratha-313 (or run mode stores to list them all).
  • postcodes: up to 500 Australian postcodes; every Coles store in each postcode (the run log lists them). A postcode without a Coles gives no rows; the warnings name its nearest store and distance, so you can add it to storeIds. maxItems applies per store.
  • allStores: every Coles store (~878). maxItems applies per store, so keep it small.

Without them you get Coles' default online store (id 7674), which is the one our nightly catalogue and price history cover. Store prices come from our nightly read of every product in every Coles store, so even allStores answers in minutes; a store not read since this week's specials change (Wednesday) is fetched live.

Filters and sorting (all modes):

  • sortBy: relevance, price_asc, price_desc, unit_price_asc, best_sellers, discount_desc. Sorting is done by Coles before paging (discount_desc re-sorts the collected results by % off, so combine it with specialsOnly or specials mode and a high maxItems), so you get the true cheapest products, not just a re-ordered first page.
  • specialsOnly (filtered by Coles, no wasted pages), inStockOnly, minPrice / maxPrice, excludeCategories (department names or slugs; tobacco by default), brands (exact brand names), minDiscountPercent (e.g. 40 = only specials at least 40% below the was-price; multi-buy offers never match).
  • specialsGroups (specials mode): halfprice, multibuy, onlineonly. Empty = every special.

Health and nutrition: dietary (e.g. ["Gluten Free"], all required), excludeAllergens (e.g. ["Peanut", "Milk"]), maxSugarPer100g, minProteinPer100g. These use product details: from our database when we have them, or from the product page with fetchFullDetails. Products without the data a filter needs are left out, so you never get a product we can't confirm.

Price history (from our shared daily price database, default online store):

  • changedSince: only products whose price changed since a date (2026-09-01) or since your previous run (last-run).
  • includeDisappeared (with changedSince: "last-run"): also returns rows with type: "disappeared" for products your previous run returned that are gone now (delisted, or no longer matching your filters), with their last price and when they were last seen.
  • onlyNewSpecials: only products that went on special in the last 7 days (Coles specials change on Wednesdays).
  • onlyNew: only products that appeared at Coles in the last 7 days.
  • priceHistoryDays: add the list of price changes from the last N days.

Other options:

  • maxItems: products per query / category / link and store, after filters (default 100). For specials, products and catalog it applies per run and store.
  • maxAgeHours: how old our data may be (default 36; anything read before this week's specials change on Wednesday is fetched live; 0 = always fetch live).
  • fetchFullDetails: add barcode, ingredients, allergens, dietary statement, nutrition panel, country of origin and storage from the product page, for products that don't have them yet. It takes one extra request per product and is charged per product.
  • includeRaw: add the original Coles payload (every field, including ones we don't map).

Example output

{
"store": "coles",
"productId": "8150288",
"barcode": "9300601186945",
"name": "Coles Full Cream Milk",
"brand": "Coles",
"size": "3L",
"url": "https://www.coles.com.au/product/coles-full-cream-milk-3l-8150288",
"imageUrl": "https://cdn.productimages.coles.com.au/productimages/8/8150288.jpg",
"price": 4.95,
"wasPrice": 4.95,
"unitPrice": 1.65,
"unitMeasure": "1L",
"pricePerLitre": 1.65,
"isOnSpecial": false,
"specialType": null,
"offerDescription": null,
"inStock": true,
"storeId": "584",
"availableQuantity": 438,
"purchaseLimit": 20,
"aisle": null,
"categoryPath": ["Dairy, Eggs & Fridge", "Milk", "Full Cream Milk"],
"ingredients": "Homogenised and Pasteurised Full Cream Milk.",
"allergens": { "contains": ["Milk"], "mayContain": [] },
"nutrition": {
"servingSize": "250mL",
"servingsPerPack": "12.00",
"items": [{ "name": "Energy (kJ)", "per100": "258 kJ", "perServing": "646 kJ" }, { "name": "Protein", "per100": "3.4 g", "perServing": "8.5 g" }]
},
"dietaryTags": ["Source of Calcium"],
"countryOfOrigin": "Australian Milk",
"storage": "Keep this way up,Keep refrigerated. Store at or below 5°C",
"previousPrice": null,
"priceChangedAt": null,
"lowestPrice30d": 4.95,
"averagePrice90d": null,
"discountCheck": null,
"scrapedAt": "2026-09-27T15:45:14.223Z",
"source": "live"
}

Output fields

GroupFields
Identitystore, productId, barcode (GTIN), name, brand, size, url, imageUrl, images, categoryPath
Priceprice, wasPrice, unitPrice + unitMeasure, pricePerKg, pricePerLitre, pricePerItem
Store & stockstoreId, storeName, storeSuburb, storeState, storePostcode, inStock, availableQuantity, purchaseLimit, aisle
Store directory (mode stores)storeId, name, brand, address, suburb, state, postcode, latitude, longitude, phone, tradingHours, holidayHours, collectionPointId, url
SpecialsisOnSpecial, specialType (Half Price, Multi Buy, Online Special, Special), offerDescription, specialStartedAt, discountCheck, specialCycle
HistorypreviousPrice, priceChangedAt, lowestPrice30d, averagePrice90d, firstSeenAt, priceHistory (with priceHistoryDays)
Product detailsdescription, ingredients, allergens, nutrition, dietaryTags, storage, countryOfOrigin
FreshnessscrapedAt, source (cache or live)

All prices are in AUD, as numbers. wasPrice equals price when nothing is discounted (multi-buy offers have no was-price; see offerDescription). Detail fields are null (or empty lists) until we have the product page for a product.

Deal check for specials: discountCheck.verdict is:

  • genuine when the "was" price was actually charged for at least 28 of the 90 days before the special;
  • questionable when it was not (for example, when the price was raised shortly before the "discount");
  • insufficient-history when the product has less than 28 days of price history.

specialCycle shows how often a product goes on special and when the next one is expected, once we have seen 3 of its specials.

Price alerts in 5 minutes

  1. Save a task with the input you want to watch (examples 6 and 7 above are good starting points).
  2. Add a schedule (for example every Wednesday morning, when specials change, or daily for price drops).
  3. In the task's Integrations tab, send results to email, Slack, Google Sheets, Zapier, Make, n8n or a webhook.

With changedSince: "last-run", each run returns only what changed since the previous one, so quiet days cost nothing.

Run it through the API

cURL (runs synchronously and returns the items):

curl -X POST "https://api.apify.com/v2/acts/crawlplant~coles-au/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"queries": ["milk"], "maxItems": 20}'

JavaScript (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('crawlplant/coles-au').call({ mode: 'specials', specialsGroups: ['halfprice'], maxItems: 200 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((p) => `${p.name}: $${p.price} (was $${p.wasPrice})`));

Python (pip install apify-client):

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("crawlplant/coles-au").call(run_input={"queries": ["coffee"], "sortBy": "unit_price_asc", "maxItems": 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["name"], item["pricePerKg"])

Use with AI agents

The Actor works as a tool in the Apify MCP server: Claude, ChatGPT, Cursor, VS Code, LangChain, CrewAI, OpenAI Agents and others. Small queries are answered from the cache in seconds, and every output field is described, so agents understand the data without extra prompting.

To give an assistant only this tool, use this server URL:

https://mcp.apify.com?tools=crawlplant/coles-au

Example for Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "coles": { "command": "npx", "args": ["mcp-remote", "https://mcp.apify.com?tools=crawlplant/coles-au"] } } }

Try prompts like "find the cheapest olive oil per litre at Coles", "which Coles half-price specials are genuine this week?" or "is Tim Tam in stock at Coles Karratha (store 313)?".

Pricing

Pay per result: you pay for the products returned, and platform usage (compute, proxies) is included.

EventFree planStarterScaleBusiness and up
Product (per 1,000 results)$0.80$0.70$0.60$0.50
Full product details (per 1,000, only with fetchFullDetails)$0.40$0.35$0.30$0.25
Actor start (per run)$0.00005$0.00005$0.00005$0.00005

Store rows count as products (3 stores × 10 products = 30 results), and each store in mode stores counts as one result. Barcodes and details we already have, price history and deal checks are included in the product price. A failed or empty run costs only the start fee.

Example on the Free planResultsCost
Default run: search milk100$0.08
tim tam in the stores of 3 postcodes, 10 each~30-60$0.02-0.05
One product in every Coles store~878$0.70
Store directory~878$0.70
Whole catalogue~27,000~$21.60
Daily watch with changedSince: "last-run"only the changesoften $0.00

Set a maximum cost per run in the run options to stop a large run at your budget.

Compared with other Coles scrapers (Free plan prices on the Apify Store, 27 September 2026): the most-used one charges $1.00 per 1,000 products plus $0.008 per run; the others charge $1.49-10.00 per 1,000, several with a start fee of $0.005-0.10 and extra charges for details. None of them includes price history.

Reliability

  • Most queries are answered from our nightly catalogue in seconds, so a run doesn't depend on Coles answering at that moment. Every Coles store's prices are read every night too; anything newer is fetched live through Australian proxies, included in the price.
  • If a live request doesn't come through, the run still finishes with everything else and a note in its summary. An empty run costs only the start fee.
  • Automated checks test the Actor, the data and its freshness every 3 hours, around the clock.

Price history

We have tracked every Coles online price since 27 September 2026, and every night adds each change. Every product row carries previousPrice, priceChangedAt, lowestPrice30d and averagePrice90d; priceHistoryDays adds the full list of changes. discountCheck rates a special once the product has 28 days of history, and onlyNew / onlyNewSpecials look at the last 7 days.

Data freshness

Every item has scrapedAt (when the price was read from Coles) and source:

  • cache: from our database, no older than your maxAgeHours. The whole catalogue is refreshed every night (Sydney time).
  • live: fetched from Coles during your run.

Store rows from our nightly store read carry that read's time in scrapedAt; their inStock is the store's online availability at that time.

If a live request doesn't come through, the run still finishes with the latest cached data and a note in the run's OUTPUT record.

Troubleshooting

  • Fewer results than expected: filters (price, dietary, allergens) leave out products that don't match or have no data. The OUTPUT record in the run's key-value store lists any warnings, e.g. when up to 30 pages were scanned without enough matches.
  • Health filters return few products: they need product details. Add "fetchFullDetails": true for complete results.
  • "category not found": run mode categories to get the exact category links, then paste one into categoryUrls.
  • previousPrice is null: we have not seen that product's price change since we started tracking it.
  • No history fields on store rows: price history covers Coles' default online store only.
  • onlyNew / onlyNewSpecials return nothing with a warning: these need a week of tracking history; the warning shows the date they start working.
  • A product id isn't returned: the product no longer exists; it is listed in the run warnings and not charged.

FAQ

Do Coles prices and stock differ by store?

Yes, for some products. Without storeIds / postcodes / allStores you get the default online prices Coles shows before you choose a store or postcode. With them, the prices and stock of those stores (and the aisle, when read live), each store as its own rows.

How much does it cost to scrape Coles?

$0.80 per 1,000 products on the Free plan, down to $0.50 on higher plans, plus $0.00005 per run. The default run costs $0.08. See Pricing.

Is a Coles special a real discount?

Check discountCheck.verdict on the product: genuine or questionable, based on what the product really cost before the special. See Check if a Coles special is a real discount.

When do Coles specials change?

Every Wednesday. Schedule a specials run on Wednesday morning (Sydney time) to track each new week.

Which stores does a postcode give?

The stores whose address is in that postcode, from our weekly store directory. For a postcode without a Coles, the warning's nearest store is measured from the centre of the postcode (ABS Postal Areas), as the crow flies.

Why are some products missing price?

The product is currently unavailable at that store.

How is this different from other Coles scrapers?

Runs finish reliably, results are served from a nightly snapshot in seconds, and every product carries price history, a genuine-discount check and normalised unit prices. Barcodes and nutrition come free when we already have them, and there is a full-catalogue mode. See Pricing for a price comparison.

The Actor reads only public product, price and stock information that anyone can see without logging in. It does not collect personal data or reviews. It is not affiliated with Coles Group.

Good to know

  • With filters, up to 30 result pages (~1,400 products) are scanned per query or category and store; the run says so when that cap is hit.
  • Coles has no sort by name; use a price sort for exact, repeatable ordering.
  • Tobacco is excluded by default.

Run summary

The key-value store record OUTPUT shows items returned (cache vs live), invalid records skipped, request statistics, the proxy route used, extra events charged and any warnings.

Data sources

Product, price, stock and store data: public pages of coles.com.au. Postcode locations: Australian Bureau of Statistics, Postal Areas (ASGS Edition 3), CC BY 4.0.

Privacy

The Actor only reads public product pages and does not collect personal data. To decide which features to build next, each run sends the developer usage statistics: the mode, which options were used (e.g. "sortBy: price_asc", "specialsOnly: on", "2 stores"), result counts and duration. It never sends your search terms, URLs, product ids, store ids, postcodes, results or any account details. Your Apify account id is replaced on arrival by a one-way keyed hash (the id itself is never stored), used only to count how many different accounts use the Actor.