# Australian Supermarkets Scraper - Woolworths & ALDI Prices (`dami_studio/australian-supermarkets-scraper`) Actor

Search Woolworths and ALDI the way you would on their websites, or paste category and product links, and get one row per product: price, was-price, unit price, size, special, availability, image and link. Coles isn't covered yet. No account needed.

- **URL**: https://apify.com/dami_studio/australian-supermarkets-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** E-commerce, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.27 / 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

**Search Woolworths and ALDI the way you would on their websites, or paste a category or product link, and get one row per product**: name, brand, size, price, was-price and saving, unit price, availability, image and link. Both stores answer the same search in one run, so a price comparison is a sort away.

Two things to know first. Coles isn't covered yet; Coles links are skipped and not charged. And Woolworths shows prices for the store picked by your suburb. Nobody picks one here, so you get the prices Woolworths shows when no suburb is set, and each row says which store that was (`storeId`). Your local shelf can differ.

| | |
|---|---|
| **Input** | Search words, or Woolworths and ALDI category, product and search links |
| **Output** | One row per product: name, brand, size, price, was-price, saving, unit price, special, availability, categories, barcode (Woolworths), image, link |
| **Ceiling** | 2,000 products per search or category, 20,000 per run |
| **Speed** | Roughly 600 to 1,100 Woolworths products a minute; ALDI is quicker |
| **Account needed** | None from you |
| **Price** | $0.28 per 1,000 products, flat on every plan. The free plan's $5 a month covers about 17,800 |

### 🔍 What Australian Supermarkets Scraper does

You give it what you'd type into the search box, `full cream milk` or `vegemite`, and it runs that search at Woolworths and at ALDI and returns every product each store lists, in the store's own order. Or paste links: a category page returns the products in it, a product page returns that product.

Prices are numbers, not text: `4.5`, not "$4.50". Specials come with the old price and the saving worked out. The unit price comes both ways, `2.25` plus `1L`, and as the shelf label prints it, `$2.25 / 1L`, so you can compare a 2L bottle with a 3L one without doing the sums.

Woolworths also lists products that other businesses sell through its website. On a search for milk that was two listings in three, mostly bulk packs and things that aren't groceries. You get Woolworths' own range unless you tick **Include other sellers at Woolworths**.

### 📋 What data you get from each Woolworths and ALDI product

| What you get | Field |
|---|---|
| Which store, and what found it | `store`, `searchTerm`, `inputUrl`, `position` |
| The store's product number, name, brand and pack size | `productId`, `name`, `brand`, `size` |
| Price, old price, saving and the special's wording | `price`, `wasPrice`, `savings`, `onSpecial`, `promotion` |
| Unit price, as a number and as printed | `unitPrice`, `unitPriceUnit`, `unitPriceText` |
| Sold by weight (the price is for a typical pack) | `soldByWeight` |
| Availability | `available`, `inStock`, `availableFrom` |
| The store's own aisles for the product | `categories` |
| Barcode, Woolworths only | `barcode` |
| Sponsored listing and marketplace seller flags, Woolworths only | `sponsored`, `marketplace` |
| The store whose prices these are, Woolworths only | `storeId` |
| Product page and picture | `url`, `imageUrl` |

### ▶️ How to scrape Woolworths and ALDI prices

1. Open [Australian Supermarkets Scraper](https://apify.com/dami_studio/australian-supermarkets-scraper) and click **Try for free**.
2. Type your searches into **Search words**, one per line, and tick the stores under **Stores to search**.
3. Or paste links copied from woolworths.com.au or aldi.com.au into **Category or product links**.
4. Set **Products per search or category** while you're testing, since you pay per product.
5. Click **Start**, then download the table as CSV, Excel or JSON, or read it through the Apify API.

Start it with everything empty and you get one labelled sample row, free, so you can see the columns first.

### 💰 How much does it cost to scrape Woolworths and ALDI prices?

**$0.28 per 1,000 products.** Flat on every Apify plan, no volume tiers. On the free plan, the $5 Apify gives you each month covers about 17,800 products.

You pay for products delivered and nothing else. A search that finds nothing, a misspelt search, a product link that no longer exists, a Coles link and the sample row are all free. A product the store lists twice in one search, which Woolworths does with sponsored products, is returned and charged once.

### 📥 What you give it

```json
{
  "searchTerms": ["full cream milk", "vegemite"],
  "stores": ["woolworths", "aldi"],
  "urls": [
    "https://www.woolworths.com.au/shop/browse/dairy-eggs-fridge/milk",
    "https://www.aldi.com.au/products/dairy-eggs-fridge/k/960000000"
  ],
  "maxResultsPerSearch": 100
}
```

| Field | Default | What it is |
|---|---|---|
| `searchTerms` | none | Searches, one per line, run at each ticked store. Up to 200. |
| `stores` | both | `woolworths`, `aldi`, or both. Applies to search words only. |
| `urls` | none | Woolworths or ALDI links: a category page, a product page or a search results page. Up to 500. |
| `includeMarketplace` | `false` | Also return products other businesses sell through the Woolworths website. |
| `maxResultsPerSearch` | `100` | The most products from one search at one store, or from one category link. Up to 2,000. |
| `maxResults` | `5000` | The most products in the whole run. Up to 20,000. |

A link from anywhere else gets a free row saying it was skipped, and the rest of the run carries on.

### 📤 What you get back

A real row from a run on 3 October 2026:

```json
{
  "recordType": "product",
  "store": "Woolworths",
  "searchTerm": "milk",
  "inputUrl": null,
  "position": 9,
  "productId": "44528",
  "name": "Norco Full Cream Milk 2L",
  "brand": "Norco",
  "size": "2L",
  "price": 4.5,
  "wasPrice": 5.05,
  "onSpecial": true,
  "savings": 0.55,
  "promotion": "Save $0.55",
  "unitPrice": 2.25,
  "unitPriceUnit": "1L",
  "unitPriceText": "$2.25 / 1L",
  "soldByWeight": false,
  "available": true,
  "inStock": true,
  "availableFrom": null,
  "categories": ["Dairy, Eggs & Fridge", "Milk", "Full Cream Milk"],
  "url": "https://www.woolworths.com.au/shop/productdetails/44528/norco-full-cream-milk",
  "imageUrl": "https://cdn1.woolworths.media/content/wowproductimages/large/044528.jpg",
  "barcode": "9322042000048",
  "sponsored": false,
  "marketplace": false,
  "storeId": "1101",
  "currency": "AUD",
  "scrapedAt": "2026-10-03T16:03:05.288Z"
}
```

| Field | How to read it |
|---|---|
| `price` | Dollars, as the store shows it today. For meat ALDI sells by weight it's the price of a typical pack, and `unitPrice` is the per-kilo price. A product Woolworths lists as unavailable comes back with `price: null` and `available: false`. |
| `wasPrice`, `savings` | Only on a special; `null` otherwise. |
| `position` | Where the product sat in that store's results for that search, from 1. |
| `inStock` | Woolworths says; ALDI doesn't publish stock, so it's `null` there. |
| `availableFrom` | ALDI's date for Special Buys that go on sale on a set day. |
| `storeId` | The Woolworths store these prices belong to. Listings from other sellers carry their own number. `null` for ALDI, which lists one price per product online. |
| `sponsored` | Woolworths mixes paid listings into its results. They're real products at real prices; filter them out if you only want the plain search. |
| `marketplace` | `true` on a listing from another seller, which only appears when you ask for them. |

### 🧾 Reading the output

Three kinds of row can land in your dataset, and `recordType` tells them apart.

| Row | How to spot it | Billed |
|---|---|---|
| A product | `recordType: "product"` | yes |
| The sample row | `recordType: "sample"`, `_sample: true` | no |
| A note about one search or link | `recordType: "diagnostic"`, `_diagnostic: true`, an `errorCode` | no |

Filter on `recordType == "product"` and you have your products. The notes say:

| Code | What it means |
|---|---|
| `NO_RESULTS` | The store has nothing for that search or link. |
| `DIFFERENT_SEARCH` | The store didn't recognise the words and showed results for its own correction instead, named in `suggestion`. Nothing from that search is returned or charged; search for the suggestion if it's what you meant. |
| `NOT_FOUND` | The product link no longer leads to a product. |
| `NOT_COVERED` | A Coles link. Coles isn't covered yet. |
| `BAD_INPUT` | A setting or link that can't be used, or a Woolworths category that doesn't exist. |
| `NOT_ANSWERED` | The store didn't answer that search this time. Run it again later. |
| `PARTIAL` | A later page of results didn't come back. What came before it is in the dataset. |
| `NOT_LOOKED_UP` | The run stopped before reaching it: your spending limit, the run's total, or its timeout. |
| `MAX_CHARGE_TOO_LOW` | Your spending limit for the run doesn't cover one product. |

`RUN_REPORT` in the run's storage lists every search and link with its outcome and how many products the store said it had.

### 💡 What people use it for

- Comparing a shopping list across both stores. Run the list as search words, then sort each search by `unitPrice`.
- Tracking prices over time. Schedule the same searches weekly and keep the rows; `productId` stays the same between runs.
- Watching specials in one aisle. Paste a category link and keep the rows where `onSpecial` is true.
- Feeding a budgeting or meal-planning app that needs real prices, unit prices and pictures.

A weekly price check in three steps:

1. Put your regular items into **Search words** with **Products per search or category** at 10.
2. Schedule the run for the same time every week.
3. Join each week's rows on `store` and `productId` and look at `price` and `wasPrice`.

### 🚧 What it does not do

- **No Coles.** Coles links get a free row and nothing else.
- **No choice of suburb or store.** Woolworths prices are the ones it shows with no suburb set, and `storeId` says which store that is.
- **No stock counts.** Woolworths says in stock or not; ALDI says nothing about stock.
- **No reviews, nutrition panels or ingredients.**
- **No online orders at ALDI.** ALDI Australia doesn't sell groceries online, so its rows are the prices it lists on its website.
- **Search results follow the store's own search**, sponsored listings included. A broad word like milk brings back milk chocolate and meal-replacement shakes too.
- **Long Woolworths searches come up a little short.** Its result pages repeat some products, so a search it says has 689 products returned 621 different ones. Reading past its last page brings back nothing new.

### 🧭 Which supermarket scraper do you need?

| If you want | Use |
|---|---|
| Woolworths and ALDI products and prices | This one |
| An alert when a product page on an online shop changes price or stock | [Product Price & Stock Monitor](https://apify.com/dami_studio/structured-product-price-stock-monitor) |
| Supermarket locations and ratings from Google Maps | [Google Maps Scraper](https://apify.com/dami_studio/google-maps-scraper) |
| What shoppers say about one store | [Google Maps Reviews Scraper](https://apify.com/dami_studio/google-maps-reviews-scraper) |
| The same kind of product rows from Amazon | [Amazon Scraper](https://apify.com/dami_studio/amazon-scraper) |
| Products and prices from a Shopify shop | [Shopify Products Scraper](https://apify.com/dami_studio/shopify-products-scraper) |

### ❓ Questions people ask

#### Do I need a Woolworths or ALDI account?

No. It reads what anyone can see on the two websites without logging in.

#### Why is a Woolworths price different from what I see in the app?

The app shows prices for the store your suburb or delivery area picks. This reads the prices Woolworths shows when no suburb is set, and `storeId` names that store. To check a row, open its link in a private browser window without choosing a suburb.

#### Can it scrape Coles prices?

Not yet. Coles links are accepted and skipped with a free note, so a list that mixes all three stores still runs.

#### Can I call it from code or connect it to an AI assistant?

Yes. The [API tab](https://apify.com/dami_studio/australian-supermarkets-scraper/api/python) has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect `https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/australian-supermarkets-scraper`. Either way the run happens on your Apify account at the same price.

#### Is it legal to scrape supermarket prices?

It reads public product pages, the same ones any shopper sees, and no personal data. Apify's write-up on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Include your searches or links and the run ID, and the log is enough for us to see what happened.

# Actor input Schema

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

What you'd type into the store's search box, one search per line: <code>full cream milk</code>, <code>vegemite</code>, <code>nappies size 4</code>. Each search runs at every store ticked below. Up to 200 searches a run.

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

Which stores your search words run against. Leave both ticked to compare them. Links below always go to the store they belong to, whatever is ticked here.

## `urls` (type: `array`):

Links copied from woolworths.com.au or aldi.com.au, one per line. A category page such as <code>https://www.woolworths.com.au/shop/browse/dairy-eggs-fridge/milk</code> or <code>https://www.aldi.com.au/products/dairy-eggs-fridge/k/960000000</code> returns the products in it; a product page returns that one product. Search result links work too. Coles links are skipped for now, without charge.

## `includeMarketplace` (type: `boolean`):

Woolworths also lists products sold by other businesses through its website, often bulk packs and non-grocery items. Off, you get Woolworths' own range at Woolworths' prices. On, those listings come too, marked <code>marketplace: true</code>. A Woolworths product link always returns its product either way.

## `maxResultsPerSearch` (type: `integer`):

The most products from one search at one store, or from one category link. A broad search like milk has two thousand products at Woolworths, so this is your main spending cap.

## `maxResults` (type: `integer`):

The most products in the whole run, across every search and link. Each product returned is one charge.

## Actor input object example

```json
{
  "searchTerms": [
    "full cream milk"
  ],
  "stores": [
    "woolworths",
    "aldi"
  ],
  "includeMarketplace": false,
  "maxResultsPerSearch": 20,
  "maxResults": 5000
}
```

# Actor output Schema

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

One row per product, search by search, in the order the store listed them. Free rows marked \_diagnostic say when a search found nothing, a store suggested a different spelling, a product link no longer exists, or something was not looked up.

## `report` (type: `string`):

What happened for each search and link: its status, products returned, how many the store listed, pages read, and why the run stopped.

# 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"
    ],
    "maxResultsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/australian-supermarkets-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 = {
    "searchTerms": ["full cream milk"],
    "maxResultsPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/australian-supermarkets-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 '{
  "searchTerms": [
    "full cream milk"
  ],
  "maxResultsPerSearch": 20
}' |
apify call dami_studio/australian-supermarkets-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/australian-supermarkets-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/lUeID73geq976vrfd/builds/i8ubkJZ0Kg3MUUZt0/openapi.json
