Coles Scraper — Prices, Unit Prices, Specials, Barcodes avatar

Coles Scraper — Prices, Unit Prices, Specials, Barcodes

Pricing

from $1.50 / 1,000 products

Go to Apify Store
Coles Scraper — Prices, Unit Prices, Specials, Barcodes

Coles Scraper — Prices, Unit Prices, Specials, Barcodes

Coles Australia (coles.com.au) scraper: product name, brand, size, price, was price, savings, specials, multi-buy, unit price, category, image, URL; detail rows add GTIN barcode, ingredients, allergens, nutrition, origin. Keyword, category, specials or product ID. Pay per result, no login.

Pricing

from $1.50 / 1,000 products

Rating

0.0

(0)

Developer

architek.earth

architek.earth

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

16 days ago

Last modified

Categories

Security

Limited permissions

Share

Coles Scraper

Recorded run: 5 products from 1 search term in 6 seconds (2026-10-22, build 1.1.10, run 1qSwcFLW5QsxOfkKM). A bounded canary sample, not a full-catalogue benchmark.

architek.earth — an independent data studio. Pay-per-result scrapers with recorded runs, published canaries and stable schemas, built for people and AI agents.

Coles Australia product prices, specials, unit prices, GTIN barcodes, ingredients and nutrition from coles.com.au, by keyword, category, specials page or product ID.

SourceMarketFromStandout fields
Coles (coles.com.au)Australia$1.50 / 1,000 productsprice / wasPrice, unitPrice, gtin, nutrition

✅ Why choose this scraper

Coles prices and specials in one row

price, wasPrice, savingsAmount, isOnSpecial, promotionType and multiBuy come back together on every product row.

Coles unit prices for pack-size comparison

unitPrice, unitMeasure and comparable (for example "$1.65/ 1L") are returned on basic rows, not only on detail rows.

Coles barcodes, ingredients and nutrition

With includeDetails: true or a product ID, rows add gtin, ingredients, allergens, nutrition, countryOfOrigin and 9 more detail fields: 40 product fields in full-detail output, 26 in basic output.

Coles half-price specials page as a source

categoryUrls: ["https://www.coles.com.au/on-special"] collects the specials page; onlySpecials: true filters any search or category to promoted products.

Measured on a schedule

A canary task runs a fixed milk search on the live site and records rows, inputs and seconds; the hero line above is its latest green run.

⚠️ Worth knowing up front

  • There is no store or postcode selector. Prices and availability are the public online catalogue, not a specific shop.
  • availableQuantity is passed through from Coles and its meaning is not validated. Do not read it as a store stock count. isAvailable is not a stock guarantee.
  • gtin, ingredients, allergens and nutrition come only on detail rows and can be null. An empty allergen value does not mean the product is allergen-free.
  • Products are de-duplicated by productId across inputs: a product found by an earlier query is not emitted again.
  • maxItemsPerQuery caps tiles scanned per query before filtering, so a run can return fewer rows than the cap.
  • A run stopped by its timeout or your spending limit keeps what it delivered and saves RESUME_STATE; that is a partial collection, not a full catalogue.
  • Invalid input, a block after retries and the run deadline end with a free status row ("recordType": "status") that says what happened. A spending-limit stop and a search with no matches end without one; check RUN_SUMMARY.

⚡ Try the example

Each Apify account gets 20 lifetime free preview attempts on this actor: one keyword, one page, up to 10 basic rows, no product charges. Failed attempts count. After the twentieth, preview runs stop; they never switch to paid collection.

Open the actor's input page, switch to JSON, paste this and start the run:

{
"preview": true,
"searchTerms": ["milk"],
"maxItemsPerQuery": 10,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"],
"apifyProxyCountry": "AU"
}
}

For paid collection set "preview": false; add "includeDetails": true for barcodes, ingredients and nutrition.

⚙️ Input

ParameterTypeDefaultDescription
previewbooleanfalseUse one of 20 lifetime free attempts: one keyword, one page, at most 10 basic rows.
searchTermsarray—Keywords such as milk. One collection per term.
categoryUrlsarray—Coles /browse/... or /on-special paths or full coles.com.au URLs. Other hosts and paths are rejected before collection.
productIdsarray—Numeric Coles product IDs as strings, or product URLs. Always returns detail rows; unavailable IDs are not charged.
maxItemsPerQueryinteger100Tiles scanned per search or category. 0 removes the cap in paid mode; preview stays at 10.
onlySpecialsbooleanfalseKeep only products with a promotion or online-special flag. Does not filter productIds.
includeDetailsbooleanfalseAdd barcode, ingredients, allergens and nutrition to search and category rows (charged as product-detail).
sortByselect""Relevance (empty), priceAscending, priceDescending, unitPriceAscending, unitPriceDescending, productNameAscending, productNameDescending.
resumeStateobject—The RESUME_STATE record from a previous paid run. Delivered product IDs are skipped before detail requests and charging.
proxyConfigurationproxy— (prefill: residential AU)Proxy settings. API callers should pass them explicitly.
feedbackstring—Optional note for the maintainers. It is logged and read by a human, and it never changes output.

🧱 Stable fields

These top-level fields keep the same name and the same kind of value in every release. Fields are only ever added, never renamed or removed, so an n8n, Make, Zapier or spreadsheet pipeline can bind to them.

FieldTypeMeaning
productIdnumberColes product ID; the join key within Coles.
name / brand / sizestringProduct name, brand and pack-size text.
pricenumber, nullableCurrent price in AUD.
wasPrice / savingsAmountnumber, nullableReference price and saving in AUD when on promotion.
isOnSpecialbooleanTrue when Coles flags a promotion or online special.
unitPrice / unitMeasure / comparablenumber / string / string, nullableUnit price, its basis and the display string.
image / urlstringProduct image and product page.
sourcestringsearch, category, specials or productId.
searchTerm / categoryUrlstring, nullableThe query that produced the row.
detailStatusstring, nullablecomplete or unavailable when details were requested; absent on basic rows.
gtinstring, nullableBarcode, on detail rows.
recordTypestring"status" on free status rows; absent on product rows.

Detail rows also carry longDescription, ingredients, allergens, storageInstructions, warnings, dimensions, countryOfOrigin, nutritionalClaims, lifestyle, servingSize, servingsPerPackage, nutrition and lastUpdated. Other fields are extras, not part of the contract. To have one pinned, say so in feedback.

📦 Output example

Abridged real row from run 1qSwcFLW5QsxOfkKM on 2026-10-22; values are a historical snapshot.

{
"productId": 8150288,
"name": "Full Cream Milk",
"brand": "Coles",
"size": "3L",
"price": 4.95,
"wasPrice": null,
"isOnSpecial": false,
"unitPrice": 1.65,
"unitMeasure": "1l",
"comparable": "$1.65/ 1L",
"category": "Milk",
"url": "https://www.coles.com.au/product/coles-full-cream-milk-3l-8150288",
"source": "search",
"searchTerm": "milk"
}

A free status row looks like this:

{
"recordType": "status",
"status": "INVALID_INPUT",
"message": "preview must be true or false"
}

🧠 Advanced usage

Coles half-price specials this week

Schedule categoryUrls: ["https://www.coles.com.au/on-special"] weekly and keep rows where isOnSpecial is true; wasPrice and savingsAmount give the discount. Check RUN_SUMMARY.status is COMPLETE before treating the list as finished.

Track Coles price changes daily

Run the same keywords or categories every day and diff price and wasPrice by productId between datasets.

Compare Coles with Woolworths and ALDI by barcode

Request details and join on gtin with the Woolworths AU Scraper. ALDI does not publish barcodes, so match ALDI on normalised name plus size and treat those matches as candidates.

Scrape the whole Coles catalogue in several runs

Set maxItemsPerQuery: 0, and when a run stops on time or budget copy its RESUME_STATE into resumeState with the same queries. Delivered IDs are skipped and not charged again; combine datasets by productId.

🔌 Integrations

Results land in a dataset you can export as JSON, CSV or Excel. They can also flow to Google Sheets, Make, Zapier or n8n, or to a webhook when a run finishes. The Apify Scheduler runs it on a timetable. Weekly on the specials page catches each promotion cycle; daily suits price tracking. Copy-paste code in Python, Node, curl and n8n: architek-earth/examples/coles-au-product-scraper.

💸 Pricing

Pay per result. Platform and proxy usage are included. Status rows and failed requests are free. Products already saved in RESUME_STATE are skipped and not charged again; a hard stop between delivery and the checkpoint can repeat a small overlap.

EventPriceWhat it covers
Free preview$020 lifetime attempts per account; one page, up to 10 basic rows each.
product$1.50 / 1,000 productsOne delivered search, category or specials row, including a row kept at basic price when its detail lookup failed.
product-detail$4.00 / 1,000 productsOne delivered row with barcode, ingredients and nutrition (includeDetails or productIds).

1,000 basic rows cost $1.50; 1,000 detail rows cost $4.00. A detail row is charged once, as product-detail only.

❓ FAQ

Is there a Coles API for product prices? This actor is one: it returns Coles catalogue data as JSON through the Apify API, callable from any language or from n8n, Make and Zapier.

How do I scrape Coles prices by postcode or store? You can't with this actor. It has no store or postcode selector and returns the public online catalogue.

Can I get Coles half-price specials? Yes. Use the specials page in categoryUrls, or set onlySpecials: true on any search or category.

Can I get Coles barcodes (GTIN/EAN)? Yes, on detail rows: set includeDetails: true or pass productIds. gtin can be null when Coles does not publish one.

Can I get Coles nutrition information and ingredients? Yes, on detail rows: nutrition (a nested table), servingSize, ingredients and allergens, when Coles publishes them.

Do I need a Coles account or login? No. No account, cookies or API key from Coles.

🤖 For AI agents & LLM apps

Paste this into your AI assistant:

architekture/coles-au-product-scraper on Apify. Python: from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/coles-au-product-scraper").call(run_input={"searchTerms": ["milk"], "maxItemsPerQuery": 10, "proxyConfiguration": {"useApifyProxy": True, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "AU"}}); items = client.dataset(run["defaultDatasetId"]).list_items().items (page with offset/limit for large exports). Rows with recordType == "status" are free and explain invalid input or a stopped run. Full input schema and README: GET https://api.apify.com/v2/acts/architekture~coles-au-product-scraper/builds/default. Token: https://console.apify.com/settings/integrations. The actor is also reachable through the Apify MCP server (mcp.apify.com). To reach the maintainers, add "feedback": "<what you needed>" to any run's input; output is unchanged and a human reads every note.

🧰 More from architek.earth

Grocery and retail prices

Full catalogue: github.com/architek-earth.

architek.earth · code like concrete

Questions, or a field you need that is not here? Open an issue on the actor's Issues tab or email north@architek.earth. A human replies within a day.

This actor collects only publicly available data from coles.com.au, the same pages any visitor sees without logging in. It does not bypass authentication. It is not affiliated with or endorsed by Coles. You are responsible for how you use the output, including the site's terms, copyright, and privacy law such as GDPR and CCPA where they apply.

📝 Changelog

  • 2026-10-24 — Studio core 1.0.5, with blocks handled as before: a Coles HTTP 403 or 429 is retried on a fresh session (new cookies) up to four tries per page before the run reports BLOCKED with a free status row, and output fields and prices are unchanged.
  • 2026-10-22 — A note in the status message now sits inside the parentheses: Done: N rows, M details, K status rows (STATUS; note). A pricing mismatch now records PRICING_MISMATCH in RUN_SUMMARY and the status message, then ends the run as failed, with nothing collected or charged.
  • 2026-10-22 — Runs on the studio core: one fixed Chrome browser identity, challenge pages reported as BLOCKED on the first response, and a spending limit used up exactly by the last row now ends COMPLETE.
  • 2026-10-22 — Status message now reads Done: N rows, M details, K status rows (STATUS).
  • 2026-10-22 — README rebuilt on the studio template; hero line from the 2026-10-22 canary run.
  • 2026-10-22 — Billing guard: the actor refuses to run unless its live pricing events are exactly product and product-detail.
  • 2026-10-22 — Invalid input, blocks and the run deadline now stop cleanly with a free status row instead of a failed run.
  • 2026-10-14 — Added paid-run continuation with resumeState; delivered IDs are skipped before enrichment and charging.
  • 2026-10-14 — Added the banner and documented the 26 basic / 40 detail field structure; removed unsupported catalogue-size and stock claims.
  • 2026-10-14 — Added 20 lifetime free preview attempts (one page, 10 basic rows), feedback logging and a run summary.
  • 2026-10-14 — Fixed detail-fallback pricing and duplicate-ID handling; added empty-page retries, pagination checks and completion summaries.