# Australian Supermarket Prices: Woolworths & Aldi Unit Prices (`subtleasianmerch/australian-grocery-prices`) Actor

Compare Woolworths and Aldi Australia prices, with unit prices per kg, litre or item. Specials, barcodes, Health Star Ratings and nutrition in one format, the cheapest match per search term, and price-change alerts on a schedule.

- **URL**: https://apify.com/subtleasianmerch/australian-grocery-prices.md
- **Developed by:** [Public Data Tools](https://apify.com/subtleasianmerch) (community)
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.64 / 1,000 products

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

## Australian Supermarket Prices: Woolworths & Aldi Unit Prices

Compare **Woolworths** and **Aldi Australia** prices in one table, with every unit price converted to **dollars per kg, per litre or per item**. Shoppers, brands and analysts also get specials, barcodes and price-change alerts.

- 🛒 **Woolworths and Aldi Australia** in one run and one format.
- ⚖️ **Unit prices in $/kg, $/L or $/item,** so the two stores compare directly.
- 🏆 **The cheapest match per search term** at each store, in every run.
- 🏷️ **Specials and was prices,** plus barcodes, Health Star Ratings and nutrition from Woolworths.
- 🔔 **Price-change alerts:** scheduled runs return only new products and price changes.
- 💸 **$0.80 per 1,000 products.** Filtered-out products, repeats and unchanged products are free.

**Try it:** the input comes pre-filled with an example. Click **Start** to compare full cream milk at both stores, per litre, then add your own search terms.

### What you get

One row per product, in the same fields for both stores:

| Data | Woolworths (by search term) | Aldi (by category) |
|---|---|---|
| **Product** | name, brand, pack size, stock code, **barcode (EAN)** | name, brand, pack size, SKU |
| **Price** | price, was price, savings, special flag, promotion label ("Save $0.50") | price, and was price and savings when Aldi shows them |
| **Unit price** | as shown ("$2.10 / 1L"), plus `pricePerKg`, `pricePerLitre` or `pricePerItem` | as shown ("$24.95 per 1 kg"), plus the same converted fields |
| **Category** | department and category | category path |
| **Health** | **Health Star Rating**, allergens; optionally ingredients and the nutrition panel (per 100 g/mL and per serve) | – |
| **Other** | online stock, customer rating, sponsored flag, image, link | image, link |
| **Changes** | with a monitor ID: new product, previous price, change in dollars and percent | the same |

Each product appears once per run, even when Woolworths repeats sponsored products on every page or a product matches several search terms.

**The cheapest per unit, for every search term.** Each run reports the cheapest matching product at each store, in the run summary and the log. A real four-item basket, run on 29 October 2026 (465 products read in 39 seconds, 155 delivered):

| Search term | Cheapest at Woolworths | Cheapest at Aldi |
|---|---|---|
| full cream milk 2l | $1.70/L: Woolworths Full Cream Milk 2L, $3.40 | $1.70/L: Full Cream Milk 2L, $3.39 |
| free range eggs | $9.60/kg: Woolworths 12 Pack X Large Free Range Eggs 700g, $6.70 | $8.80/kg: Free Range Eggs 700g, $6.19 |
| white bread | $3.80/kg: Woolworths White Sandwich Bread Loaf 650g, $2.50 | $3.70/kg: White Sandwich Sliced Bread 650g, $2.39 |
| greek yoghurt | $4.20/kg: Woolworths Natural Greek Style Yoghurt 1kg, $4.20 | $3.90/kg: Light Greek Style Natural Yogurt 1kg, $3.89 |

Prices change every week; these are a snapshot.

### Who it's for

- **Shoppers, budgeting apps and comparison sites:** compare a basket across Woolworths and Aldi on unit price, not just shelf price.
- **Brands and category managers:** track your products' and competitors' shelf prices, specials and promotions week by week.
- **Analysts and journalists:** follow grocery inflation on a fixed list of products, with history from scheduled runs.
- **Deal hunters:** get alerts when products go on special or drop in price.

### How much does it cost?

You pay **$0.80 per 1,000 products** delivered ($0.0008 each), plus Apify's standard run start fee.

| Example | Products | Cost |
|---|---|---|
| The pre-filled example: full cream milk 2L at both stores (a test run) | 17 | about $0.01 |
| The four-item basket above | 155 | about $0.12 |
| Any 1,000 products | 1,000 | $0.80 |

A weekly 50-product basket on monitoring costs $0.04 for the first run; later runs cost only for the products that changed.

**Free:**

- products removed by your filters;
- repeats, such as sponsored products shown on every page;
- with a monitor ID, products whose price and special haven't changed;
- a store that blocks the run delivers nothing and costs nothing.

Set a maximum cost per run in the run options. The run stops cleanly at that amount.

### How to use it

1. **Add search terms:** the products you want, e.g. `full cream milk 2l`, `free range eggs 12`, `coffee beans 1kg`. Woolworths is searched for each one.
2. **Pick Aldi categories:** the categories those products are in, e.g. *Dairy, Eggs & Fridge*, or paste a narrower category link from aldi.com.au, such as the Milk category. With search terms set, Aldi products are kept only when their name or brand contains every word of a term.
3. **Set options (optional):** specials only; the Woolworths order (relevance, price, unit price or name), which decides which products fall within the limit; limits per search and per category; nutrition.
4. **For price alerts,** add a **Monitor ID** and schedule the Actor daily or weekly in Apify Console.
5. **Click Start.** The **Products** view shows images, prices, unit prices and links; **Price changes** is for monitoring. Export as JSON, CSV or Excel.

### Example input

```json
{
  "searchTerms": ["full cream milk 2l", "free range eggs", "white bread"],
  "stores": ["woolworths", "aldi"],
  "aldiCategories": ["dairy-eggs-fridge", "bakery"],
  "filterAldiBySearchTerms": true,
  "specialsOnly": false,
  "woolworthsSort": "relevance",
  "maxProductsPerSearch": 36,
  "maxProductsPerCategory": 300,
  "includeNutrition": false,
  "monitorId": "weekly-basket",
  "onlyChanges": true
}
```

### Example output

A real Woolworths row, saved on 29 October 2026:

```json
{
  "store": "woolworths",
  "productId": "88436",
  "barcode": "9310199012717",
  "name": "Dairy Farmers Full Cream Milk 2L",
  "brand": "Dairy Farmers",
  "size": "2L",
  "price": 4.2,
  "wasPrice": 4.7,
  "onSpecial": true,
  "savings": 0.5,
  "promotion": "Save $0.50",
  "unitPrice": 2.1,
  "unitPriceLabel": "$2.10 / 1L",
  "pricePerKg": null,
  "pricePerLitre": 2.1,
  "pricePerItem": null,
  "inStock": true,
  "department": "Dairy, Eggs & Fridge",
  "category": "Dairy > Milk",
  "healthStarRating": 4,
  "allergens": ["Milk"],
  "rating": null,
  "sponsored": true,
  "imageUrl": "https://cdn1.woolworths.media/content/wowproductimages/large/088436.jpg",
  "url": "https://www.woolworths.com.au/shop/productdetails/88436/dairy-farmers-full-cream-milk-full-cream-milk",
  "searchedFor": "full cream milk 2l"
}
```

An Aldi row has the same fields (shortened):

```json
{
  "store": "aldi",
  "productId": "000000000000281811",
  "name": "Triple Cream Brie Cheese 200g",
  "brand": "EMPORIUM SELECTION",
  "size": "200 g",
  "price": 4.99,
  "unitPriceLabel": "$24.95 per 1 kg",
  "pricePerKg": 24.95,
  "category": "Dairy, Eggs & Fridge > Cheese",
  "url": "https://www.aldi.com.au/product/emporium-selection-triple-cream-brie-cheese-200g-000000000000281811",
  "searchedFor": "category: Dairy, Eggs & Fridge; matches: brie"
}
```

Aldi rows have no barcode, stock or nutrition, because Aldi's listings don't publish them.

#### About the fields

- **With a monitor ID,** rows also carry `isNew` and `priceChange`: `{ previousPrice, change, changePercent, previousOnSpecial, previousSeenAt }`, or null when unchanged.
- **Dataset views:** **Products** (images, prices, unit prices and links) and **Price changes** (for monitoring).
- **Run summary:** the `RUN_SUMMARY` record in the key-value store has the totals listed per search and category; products read and delivered; repeats skipped and products filtered out; new products and price changes; and `cheapestByUnitPrice`, the cheapest matching product per store for each search term.

#### How the unit-price comparison works

Each store states its unit price for a different measure: Woolworths says "$1.50 / 100G", Aldi says "$24.95 per 1 kg". The Actor converts both into `pricePerKg`, `pricePerLitre` or `pricePerItem`. For each search term, it compares the products that actually match the term's words, using the unit most of them are priced in. Products priced by something else, such as a bunch, keep the store's label, and their converted fields are empty.

Word matching ignores case and word order, and treats the stores' different spellings as the same (Woolworths writes "Yoghurt", Aldi "Yogurt").

### Integrations

- **Schedules:** run it daily or weekly in Apify Console. With a monitor ID, each run returns only price changes.
- **Apify API:** start runs and read the products as JSON from your own code, with Apify's API or its JavaScript and Python clients.
- **Webhooks:** call your own endpoint when a run finishes, for example to update a price page.
- **Make, Zapier and n8n:** send specials and price drops to Slack, email or a spreadsheet with Apify's apps for these tools.
- **Monitoring:** Apify's monitoring can alert you when a scheduled run fails or returns fewer results than usual.

### FAQ

#### Is it legal to use?

Both supermarkets' website terms restrict automated access and reuse of their data. Woolworths' terms bar robots and other tools that retrieve or index the site. Aldi's bar automated access and reselling or exploiting its data. The Actor uses no evasion: it reads only paths their robots.txt allows, at a polite pace, and stops at block pages. Make sure your use is appropriate; if in doubt, get legal advice.

#### Why isn't Coles included?

Coles' site blocks automated requests, and this Actor doesn't try to get past blocks.

#### Why is Aldi read by category?

Aldi's robots.txt closes its search page to automated access, so this Actor uses categories. Smaller categories mean fewer pages: 30 products per page, and about 3,300 products in Aldi's whole range in October 2026.

#### Are these the prices in my local store?

They are the stores' online listings. Woolworths shows its default online store's prices; in-store prices can differ. Aldi's listings show its everyday prices; Aldi doesn't sell groceries online.

#### Why does "Specials only" drop Aldi's Lower Prices?

Specials come from each store's own flags and "was" prices. Aldi's "Lower Prices" category lists permanent price cuts with no "was" price, so turn "Specials only" off for it.

#### Can I track specific products?

Use precise search terms (brand, product and size, e.g. `dairy farmers full cream milk 2l`) with a low "Most products per Woolworths search". For Aldi, use a narrow category link, and keep the search-term filter on.

#### Why do Woolworths results include unrelated products?

Woolworths' search is broad and includes sponsored placements. Those rows are marked `sponsored`, and the cheapest-per-unit comparison only counts products whose name contains your words.

#### Why is the cheapest "coffee" a coffee creamer?

A product counts as a match when its name contains every word of your term, so a one-word term matches many kinds of product. Use specific terms, such as `instant coffee 200g` or `coffee beans 1kg`.

#### What if a store slows down or blocks the run?

The Actor reads one page a second per store. If a store asks it to slow down, it waits and retries. If a store blocks it, that store is skipped, the other store is still read, and the run summary says what happened.

### Related Actors

More Actors from the same developer that work well with this one:

| Actor | Use it to |
|---|---|
| [Fuel Prices](https://apify.com/subtleasianmerch/fuel-prices) | track another everyday cost: fuel prices per station in France and Spain |

Questions, bugs or ideas? Open an issue on this Actor's **Issues** tab.

# Actor input Schema

## `searchTerms` (type: `array`):

Woolworths is searched for each term. Aldi products from the categories below are kept only when they match a term, unless you turn that off.

## `stores` (type: `array`):

Which supermarkets to read.

## `aldiCategories` (type: `array`):

Aldi is read by category, because its own search page is closed to automated access (robots.txt). Pick the categories your products are in.

## `aldiCategoryUrls` (type: `array`):

Narrower Aldi categories, copied from aldi.com.au, e.g. https://www.aldi.com.au/products/dairy-eggs-fridge/milk/k/1111111160. Smaller categories mean fewer pages to read.

## `aldiAllProducts` (type: `boolean`):

All of Aldi's products (about 3,300 in October 2026, 30 per page). Replaces the categories above; "Most products per Aldi category" still applies.

## `filterAldiBySearchTerms` (type: `boolean`):

On: an Aldi product is kept when its name or brand contains every word of a search term. Off, or with no search terms: every product in the categories is kept.

## `specialsOnly` (type: `boolean`):

Only products on special (with a lower price than usual).

## `woolworthsSort` (type: `string`):

The order Woolworths returns results in, which decides which products fall within the limit below.

## `maxProductsPerSearch` (type: `integer`):

Woolworths returns 36 per page; popular terms have thousands of results.

## `maxProductsPerCategory` (type: `integer`):

Products read from each Aldi category (30 per page), before the search-term filter.

## `includeNutrition` (type: `boolean`):

Ingredients, the allergy statement and the nutrition panel (per 100 g/mL and per serve). Aldi doesn't publish these on its product listings.

## `monitorId` (type: `string`):

Any name, e.g. "weekly-basket". Runs with the same ID remember each product's last price, so a schedule can report new products and price changes.

## `onlyChanges` (type: `boolean`):

With a monitor ID: on, only products that are new or whose price or special changed since the last run; off, all products with changes marked.

## Actor input object example

```json
{
  "searchTerms": [
    "full cream milk 2l"
  ],
  "stores": [
    "woolworths",
    "aldi"
  ],
  "aldiCategories": [
    "dairy-eggs-fridge"
  ],
  "aldiAllProducts": false,
  "filterAldiBySearchTerms": true,
  "specialsOnly": false,
  "woolworthsSort": "relevance",
  "maxProductsPerSearch": 36,
  "maxProductsPerCategory": 90,
  "includeNutrition": false,
  "onlyChanges": true
}
```

# Actor output Schema

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

The dataset rows this run produced.

## `runSummary` (type: `string`):

Counts, costs and anything skipped, saved as RUN_SUMMARY.

# 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 = {
    "searchTerms": [
        "full cream milk 2l"
    ],
    "stores": [
        "woolworths",
        "aldi"
    ],
    "aldiCategories": [
        "dairy-eggs-fridge"
    ],
    "maxProductsPerSearch": 36,
    "maxProductsPerCategory": 90
};

// Run the Actor and wait for it to finish
const run = await client.actor("subtleasianmerch/australian-grocery-prices").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 = {
    "searchTerms": ["full cream milk 2l"],
    "stores": [
        "woolworths",
        "aldi",
    ],
    "aldiCategories": ["dairy-eggs-fridge"],
    "maxProductsPerSearch": 36,
    "maxProductsPerCategory": 90,
}

# Run the Actor and wait for it to finish
run = client.actor("subtleasianmerch/australian-grocery-prices").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 '{
  "searchTerms": [
    "full cream milk 2l"
  ],
  "stores": [
    "woolworths",
    "aldi"
  ],
  "aldiCategories": [
    "dairy-eggs-fridge"
  ],
  "maxProductsPerSearch": 36,
  "maxProductsPerCategory": 90
}' |
apify call subtleasianmerch/australian-grocery-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,subtleasianmerch/australian-grocery-prices"
        }
    }
}
```

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/tZRMPSEd8L8D4TPPy/builds/BTeugjGQLIJePuglT/openapi.json
