# Coles Product Scraper – Prices, Specials & Stock (`genial_candlestand/coles-product-scraper`) Actor

Returns Coles (coles.com.au) products with price, was-price, unit price, special or multibuy offer, availability and stock quantity. Search terms, categories, specials or URLs; optional GTIN, ingredients and nutrition. No login.

- **URL**: https://apify.com/genial_candlestand/coles-product-scraper.md
- **Developed by:** [Flowo](https://apify.com/genial_candlestand) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Coles Product Scraper – Prices, Specials & Stock

This actor returns public product data from coles.com.au, the online store of the Australian supermarket Coles. Each product is one flat row with `price`, `wasPrice`, `unitPrice`, the special breakdown (`priceDescription`, `savePercent`, `multibuyPrice`), `isAvailable`, `stockQuantity` and the category path. No login is needed.

### What does Coles Product Scraper do?

You give it search terms, Coles category paths, a specials list (all, half price or multibuy) or pasted coles.com.au URLs. Any mix of these goes into one run, and every source is paged automatically until its results or your limits run out.

- Current price, was-price, unit price (`comparablePrice`, `unitOfMeasure`) and currency (AUD).
- Specials: `isOnSpecial`, `promotionType`, `offerDescription`, `saveAmount`, `savePercent`, `multibuyMinQuantity`, `multibuyPrice`.
- Availability and limits: `isAvailable`, `availabilityType`, `stockQuantity`, `retailLimit`, `promotionalLimit`.
- Optional product details: barcode (`gtin`), `ingredients`, `allergens`, `countryOfOrigin` and nutrition per 100 g as numeric columns.
- Sponsored products are flagged with `isSponsored` and can be excluded.
- Each product is saved once per run, even if several sources list it.

### How to use it

1. Open the actor in Apify Console and fill at least one of **Search terms**, **Categories**, **Specials** or **Start URLs**.
2. Set **Max products** (and optionally **Max products per source**) to control size and cost.
3. Tick **Include product details** if you need GTIN, ingredients, allergens or nutrition.
4. Optionally enter a **Store ID** (3–4 digits, e.g. `0584`) to get that store's stock quantity.
5. Keep the proxy setting. Coles blocks requests without a proxy; Apify datacenter proxy works, and Residential with country Australia is the most reliable.
6. Run it and download the dataset as JSON, CSV or Excel, or read it through the API.

### Pricing

Pay per event, no start fee:

| Event | Price |
|---|---|
| Product saved to the dataset | $0.0011 (about $1.10 per 1,000 products) |
| Add-on: product details | $0.0005 per product, only when **Include product details** opens the product page |

Searches with no results, blocked pages and sponsored products you filtered out are free. Pasted product URLs include the details at no add-on charge. The add-on is not charged when the product page fails.

### Input

| Field | What it does |
|---|---|
| `queries` | Search terms, one per line (e.g. `milk`, `tim tams`). |
| `categories` | Category paths after `/browse/`, e.g. `pantry` or `dairy-eggs-fridge/milk` (up to 3 levels). |
| `specials` | `none`, `halfprice`, `multibuy` or `all`. |
| `startUrls` | coles.com.au search, category, specials or product URLs. Other hosts or paths fail the run with an input error. |
| `includeDetails` | Add GTIN, ingredients, allergens, nutrition and more (add-on event). |
| `storeId` | Optional store number for stock quantity. |
| `sortBy` | `relevance`, `priceAscending`, `priceDescending`, `productNameAscending`, `productNameDescending`. |
| `includeSponsored` | Keep sponsored products (default on). |
| `maxItems` | Total product limit (default 1000, up to 100000). |
| `maxItemsPerSource` | Optional limit per search term, category, list or URL. |
| `proxyConfiguration` | Proxy settings; a proxy is required. |

At least one source must be given; an input with none fails with an input error before any request.

Example:

```json
{
  "queries": ["milk", "tim tams"],
  "specials": "halfprice",
  "maxItems": 100,
  "maxItemsPerSource": 48
}
```

### Output

One row per product. Real example from a search for "milk":

```json
{
  "id": "8150288",
  "url": "https://www.coles.com.au/product/coles-full-cream-milk-3l-8150288",
  "title": "Full Cream Milk",
  "brand": "Coles",
  "size": "3L",
  "price": 4.95,
  "wasPrice": null,
  "currency": "AUD",
  "unitPrice": 1.65,
  "unitOfMeasure": "1l",
  "comparablePrice": "$1.65/ 1L",
  "isOnSpecial": false,
  "isAvailable": true,
  "availabilityType": "InStoreAndOnline",
  "stockQuantity": 3361,
  "retailLimit": 20,
  "promotionalLimit": 12,
  "category": "Dairy, Eggs & Fridge",
  "subCategory": "Milk",
  "aisle": "Full Cream Milk",
  "isSponsored": false,
  "position": 1,
  "query": "milk",
  "source": "https://www.coles.com.au/search/products?q=milk",
  "scrapedAt": "2026-10-15T15:52:25.285Z"
}
```

Fields that do not apply (for example `wasPrice` on a product not on special) are `null`. With **Include product details** the row also has `gtin`, `ingredients`, `allergens`, `dietary`, `storageInstructions`, `dimensions`, `countryOfOrigin`, `longDescription`, `servingSize`, `servingsPerPackage` and per-100 g columns such as `energyKjPer100g`, `proteinGPer100g`, `sugarsGPer100g` and `sodiumMgPer100g`.

### Use cases

- Track Coles prices and weekly specials over time, next to other supermarkets.
- Check shelf price, promotion and availability of your own and competing products.
- Feed deal apps and AI agents with "what is on half price this week" as JSON.
- Collect GTIN, ingredients, allergens and nutrition for product-data work.

### Limitations

- A proxy is required; without one Coles blocks the requests.
- Prices are national; a `storeId` changes stock quantity and range, not prices.
- Coles can show a bot-challenge page; the actor retries blocked pages through new proxy IPs, but a run can still lose pages if blocking tightens.
- Datacenter proxies have no Australian IPs; if you choose country AU without the Residential group, the actor logs a warning and runs without the country setting. Use Residential for Australian IPs.
- An unknown category is skipped with a warning; an unknown product URL is skipped.
- A very large list may be capped by Coles; set `maxItems` to what you need.

### FAQ

**Is it legal to scrape Coles?**
The actor reads only publicly visible product pages, with no login and no personal data. Laws and site terms vary by country and use, so check your own use case and Coles' terms. Note that Coles' robots.txt disallows `/search/`, while browse, product and specials pages are allowed.

**Do I need a Coles account?**
No.

**Can I get several stores?**
Run once per `storeId`; each run uses one store number.

**Why are some rows marked `isSponsored`?**
Coles shows paid placements above results. They have no `position`; switch **Include sponsored products** off to skip them.

### Other actors

Other public data actors from the same author:

- [Google Trends Scraper — Interest, Regions & Related Queries](https://apify.com/genial_candlestand/google-trends-scraper): search interest timelines and related queries for your terms.
- [Apple App Store Reviews API – iOS Reviews & Ratings](https://apify.com/genial_candlestand/apple-app-store-reviews-api): public App Store reviews as structured JSON across apps and countries.
- [Firefox Add-ons Reviews Parser](https://apify.com/genial_candlestand/firefox-addons-reviews-parser): public Firefox add-on ratings and reviews.

# Actor input Schema

## `queries` (type: `array`):

Products to search for on coles.com.au, one term per line (e.g. "milk", "gluten free bread"). Each term is paged until its results or the limits run out. Blank lines are ignored. Give at least one of: Search terms, Categories, Specials or Start URLs.

## `categories` (type: `array`):

Coles category paths as they appear after /browse/ in the site URL, one per line: a department ("pantry", "liquorland") or a sub-category ("dairy-eggs-fridge/milk"). Full browse URLs are accepted too. Lowercase letters, digits and dashes, up to 3 levels. An unknown category is skipped with a warning.

## `specials` (type: `string`):

Also scrape the Coles specials list: all specials, only half-price, or only multibuy ("2 for $X") offers. "none" scrapes no specials list. Use Categories or Search terms for specials of one product type.

## `startUrls` (type: `array`):

coles.com.au URLs to scrape: search (/search/products?q=…), category (/browse/…), specials (/on-special…, /half-price-specials) or product pages (/product/…). Filters in the URL (e.g. filter_Brand) are kept. Any other URL or host fails the run with an input error before scraping.

## `includeDetails` (type: `boolean`):

Open each listed product's own page to add barcode (GTIN), ingredients, allergens, dietary info, storage, dimensions, country of origin, description and nutrition per 100 g. One extra page per product, charged as a separate add-on event. Product URLs in Start URLs always include details at no extra charge.

## `storeId` (type: `string`):

Optional Coles store number (3–4 digits, e.g. "0584"). Stock quantity and the product range then come from this store; prices are national. Empty = Coles online defaults. A store number Coles does not know fails the run with an input error.

## `sortBy` (type: `string`):

Order of search, category and specials results (matters with limits). "relevance" keeps the Coles default order. Does not apply to product URLs; a Start URL that already has sortBy keeps its own.

## `includeSponsored` (type: `boolean`):

Keep sponsored (paid placement) products that Coles shows above the results. They are marked isSponsored = true and have no position. Turn off to get and pay for organic results only.

## `maxItems` (type: `integer`):

Stop after this many products in total across all sources. Each saved product is one charged event.

## `maxItemsPerSource` (type: `integer`):

Optional cap for each search term, category, specials list or start URL, so one big source cannot use up Max products. Empty = no per-source cap.

## `proxyConfiguration` (type: `object`):

Coles blocks requests without a proxy, so a proxy is required. Apify datacenter proxy (default) works; Residential with country Australia is the most reliable. Datacenter IPs have no Australia country (it is dropped with a warning).

## Actor input object example

```json
{
  "queries": [
    "milk",
    "tim tams"
  ],
  "specials": "none",
  "startUrls": [
    {
      "url": "https://www.coles.com.au/on-special?filter_Special=halfprice"
    }
  ],
  "includeDetails": false,
  "sortBy": "relevance",
  "includeSponsored": true,
  "maxItems": 100,
  "maxItemsPerSource": 48,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset with all scraped products

## `overview` (type: `string`):

Products table in the Overview view

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "queries": [
        "milk",
        "tim tams"
    ],
    "startUrls": [
        {
            "url": "https://www.coles.com.au/on-special?filter_Special=halfprice"
        }
    ],
    "maxItems": 100,
    "maxItemsPerSource": 48
};

// Run the Actor and wait for it to finish
const run = await client.actor("genial_candlestand/coles-product-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "queries": [
        "milk",
        "tim tams",
    ],
    "startUrls": [{ "url": "https://www.coles.com.au/on-special?filter_Special=halfprice" }],
    "maxItems": 100,
    "maxItemsPerSource": 48,
}

# Run the Actor and wait for it to finish
run = client.actor("genial_candlestand/coles-product-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "milk",
    "tim tams"
  ],
  "startUrls": [
    {
      "url": "https://www.coles.com.au/on-special?filter_Special=halfprice"
    }
  ],
  "maxItems": 100,
  "maxItemsPerSource": 48
}' |
apify call genial_candlestand/coles-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,genial_candlestand/coles-product-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QzbcaTdqLvFjfftIP/builds/5csELcpoHW9V4dhMS/openapi.json
