# ALDI Australia Scraper (`solidcode/aldi-com-au-scraper`) Actor

\[💰 $2.5 / 1K] Extract product and pricing data from ALDI Australia (aldi.com.au). Search by keyword or paste category and product URLs to collect names, brands, AUD prices, price-per-unit, pack sizes, images, categories, and ALDI's own limited-run availability notes.

- **URL**: https://apify.com/solidcode/aldi-com-au-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 11 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ALDI Australia Scraper

Pull the entire ALDI Australia grocery catalogue at scale — product names, AUD prices, normalized unit pricing, pack sizes, brands, SKUs, two-level category paths, 600px images, and ALDI's own limited-run availability notes, one clean row per product. Search by keyword or paste any aldi.com.au URL, sort five ways, and collect unlimited results. Built for grocery price analysts, retail intelligence teams, and product-feed builders who need fresh ALDI AU pricing without manually clicking through the online catalogue page by page.

### Why This Scraper?

- **Keyword search OR URL input** — type "cheese", "milk", or "coffee" and get matching products instantly. The leading alternative is URL-only, forcing you to hand-build category links; here you search like a shopper.
- **Limited-run availability labels** — Special Buys and other short-run lines carry `onSale: true` plus ALDI's exact shopper-facing note in `availabilityLabel`. Around 4% of a full catalogue sweep carries one; roughly six in seven read "While Stocks Last" and the rest name the in-store date ("On Sale Wed 16 Sept"), so you can archive a limited line before it sells out.
- **True unit-price comparison** — `pricePerUnit` arrives normalized ALDI's way (e.g. "$18.73 per 1 kg") on roughly 89% of rows, letting you compare cost-per-kilo across pack sizes instead of just sticker price. Alcohol is the one category ALDI publishes no unit price for.
- **Full AUD pricing on every row** — `price`, the AUD currency code, `sku`, and a canonical product link land on 100% of rows, ready for spreadsheets and price-tracking dashboards.
- **Five sort orders** — Best match, Name A–Z, Name Z–A, Price low→high, and Price high→low, so the cheapest shelf prices lead a deal sweep and A–Z keeps a catalogue export stable between runs.
- **Brand, pack size & age-restriction flags** — an `ageRestricted` flag on 100% of rows (alcohol and restricted items), plus `brand` on ~85% and `packSize` on ~89% — the gaps are loose fresh produce, which ALDI sells unbranded, and alcohol, which carries no pack size.
- **Product images, hi-res** — primary `imageUrl` plus a full `images[]` gallery delivered at 600px, ready to drop into a catalogue feed or content site.
- **Unlimited results** — set `maxResults: 0` to capture an entire category or search; no 20-item ceiling, no pagination links to chase.
- **Whole-catalogue coverage** — works across every ALDI Australia category from pantry and fresh produce to Limited Time Only, with `sku`, a two-level `categories` path, and a canonical `productUrl` on each row.

### Use Cases

**Grocery Price Monitoring & Competitive Retail Intelligence**

- Track ALDI AU shelf prices over time to benchmark against Coles, Woolworths, and IGA
- Compare cost-per-unit across brands and pack sizes using `pricePerUnit`
- Detect price moves by scheduling repeat runs and diffing `price` per `sku` between datasets
- Feed live AUD pricing into internal pricing and margin models

**Special Buys & Limited-Run Tracking**

- Capture every product carrying an `availabilityLabel` the moment a new Special Buys drop is listed
- Read `availabilityLabel` verbatim: it usually says "While Stocks Last", and on the minority of lines where ALDI publishes an in-store date ("On Sale Wed 16 Sept") you can plan coverage ahead of the drop
- Archive ALDI's rotating Limited Time Only range before items sell out
- Separate permanent range from short-run stock using the `onSale` flag

**Market Research**

- Map ALDI's private-label range by brand and category
- Size up an entire category with `maxResults: 0` for share-of-shelf analysis
- Spot newly listed and delisted lines by diffing `sku` sets between scheduled runs; ALDI drops a discontinued product out of its catalogue rather than flagging it
- Compare assortment breadth across pantry, fresh, frozen, and household categories

**Product Catalogue & Content Feeds**

- Build a structured ALDI AU product feed with images, SKUs, and category paths
- Power price-comparison sites and shopping apps with normalized unit pricing
- Keep an internal product database in sync with current names, sizes, and prices
- Generate image-rich content listings from the 600px `images[]` gallery

**Deal Sites & Shopper Alerts**

- Auto-publish ALDI's newest limited-run lines to deal sites and newsletters
- Filter to short-run stock by checking the `onSale` flag, then show the shopper the `availabilityLabel` text verbatim
- Rank a category by `pricePerUnit` to surface the genuinely cheapest option, not just the lowest sticker price
- Alert subscribers when a watched keyword product changes price between runs

### Getting Started

#### Simple Keyword Search

Just name a product — no URLs required:

```json
{
    "searchTerms": ["cheese"]
}
```

#### Multiple Searches, Cheapest First

Search several products at once and bring the lowest shelf prices to the top. One word per term matches best:

```json
{
    "searchTerms": ["cheese", "milk", "coffee"],
    "sortBy": "price_asc",
    "maxResults": 50
}
```

#### Whole Category from a URL

Paste any ALDI Australia category, product, or search URL — filters already in the URL are applied automatically. Set `maxResults` to 0 to capture the full category:

```json
{
    "startUrls": [
        "https://www.aldi.com.au/products/pantry/"
    ],
    "maxResults": 0
}
```

#### Advanced — Keywords and URLs Combined

Mix keyword searches with pasted URLs in a single run. Each product is saved once even when several of your terms or URLs return it, so overlapping searches never cost you twice:

```json
{
    "searchTerms": ["chocolate", "coffee"],
    "startUrls": [
        "https://www.aldi.com.au/products/pantry/",
        "https://www.aldi.com.au/results?q=chips"
    ],
    "sortBy": "name_asc",
    "maxResults": 200
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchTerms` | string\[] | `["cheese"]` | Products to search for on ALDI Australia, one per line (e.g. "cheese", "milk", "coffee"). Each term runs as its own search. Use one word per term — ALDI matches each word on its own, so a two-word term returns everything matching either word. |
| `startUrls` | string\[] | `[]` | Paste ALDI Australia category, product, or search-result URLs (e.g. https://www.aldi.com.au/products/pantry/). Any filters already in the URL are applied automatically. Leave empty if you only use Search Terms. |

#### Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum number of products to collect for **each** search term or URL, not for the whole run. The cap applies to each one separately, so five terms at 100 can return 500 results. Set to 0 for no limit. Tip: start with 20–50 to test, then increase. |
| `sortBy` | select | `Best match` | How to order products within each search or category: **Best match**, **Name (A to Z)**, **Name (Z to A)**, **Price (low to high)**, or **Price (high to low)**. |

### Output

Every product is one flat row. Here's a representative result:

```json
{
    "sku": "000000000000401221",
    "name": "Chicken Breast Schnitzel Panko & Quinoa Crumb 4 Pack 600g",
    "brand": "STEGGLES",
    "price": 8.99,
    "onSale": true,
    "availabilityLabel": "While Stocks Last",
    "pricePerUnit": "$14.98 per 1 kg",
    "packSize": "0.6 kg",
    "currency": "AUD",
    "categories": ["Meat & Seafood", "Poultry"],
    "imageUrl": "https://dm.apac.cms.aldi.cx/is/image/aldiprodapac/product/jpg/scaleWidth/600/839ad8a6-3659-4347-a000-572c3a8417f1/steggles-chicken-breast-schnitzel-panko-quinoa-crumb-4-pack-600g",
    "images": [
        "https://dm.apac.cms.aldi.cx/is/image/aldiprodapac/product/jpg/scaleWidth/600/839ad8a6-3659-4347-a000-572c3a8417f1/steggles-chicken-breast-schnitzel-panko-quinoa-crumb-4-pack-600g",
        "https://dm.apac.cms.aldi.cx/is/image/aldiprodapac/product/jpg/scaleWidth/600/123d6c47-8f7d-4193-9fff-bfc0ecbaa000/steggles-chicken-breast-schnitzel-panko-quinoa-crumb-4-pack-600g"
    ],
    "inStock": true,
    "discontinued": false,
    "ageRestricted": false,
    "productUrl": "https://www.aldi.com.au/product/steggles-chicken-breast-schnitzel-panko-quinoa-crumb-4-pack-600g-000000000000401221",
    "sourceUrl": "https://www.aldi.com.au/products/limited-time-only/k/1588161420755352"
}
```

Fields that are empty for a given product are left out of that row entirely, so a row is only as wide as the data ALDI publishes for it.

#### Product & Pricing

| Field | Type | Description |
|-------|------|-------------|
| `sku` | string | ALDI product identifier (SKU) |
| `name` | string | Full product name |
| `brand` | string | Brand name, often an ALDI private label. Present on ~85% of rows; ALDI sells loose fresh produce unbranded |
| `price` | number | Current price in AUD (on every row) |
| `onSale` | boolean | True when ALDI attaches an availability note to the product, which means limited-run or dated stock rather than a price reduction |
| `availabilityLabel` | string | ALDI's own availability note when there is one (e.g. "While Stocks Last", "On Sale Wed 16 Sept") |
| `pricePerUnit` | string | Normalized unit price for comparison (e.g. "$18.73 per 1 kg"). Present on ~89% of rows; ALDI publishes none for alcohol |
| `packSize` | string | Selling size / pack quantity (e.g. "0.4 kg", "6 pack"). Present on ~89% of rows; ALDI publishes none for alcohol |
| `currency` | string | Currency code (always AUD) |

#### Catalogue & Media

| Field | Type | Description |
|-------|------|-------------|
| `categories` | string\[] | Category path the product belongs to |
| `imageUrl` | string | Primary product image URL (600px) |
| `images` | string\[] | All product image URLs (600px) |
| `productUrl` | string | Canonical ALDI Australia product page URL |

#### Availability & Source

| Field | Type | Description |
|-------|------|-------------|
| `inStock` | boolean | True for every product ALDI currently lists. It only turns false when you paste a product URL for a line ALDI has stopped stocking |
| `discontinued` | boolean | ALDI's own discontinued flag. ALDI removes delisted lines from the catalogue instead of flagging them, so on keyword and category runs this is false on every row |
| `ageRestricted` | boolean | Age-restricted flag (alcohol and restricted items) |
| `searchTerm` | string | The first search term that returned this product (null for URL input). When several terms match the same product it is saved once, under the first term that found it |
| `sourceUrl` | string | The first input URL this product came from (null for keyword search). Same rule: one row per product per run, credited to the input that found it first |

### Tips for Best Results

- **Search one word per term** — ALDI matches every word in a term separately, so "frozen pizza" returns all 182 products matching *frozen* or *pizza* and not one of them is both, while "pizza" on its own returns 28 real pizzas. "baby formula" gives you 61 loosely related products; "formula" gives you 4, every one of them infant formula. Pick the single most specific word and you get a cleaner dataset for a fraction of the results.
- **Budget with the cap, and remember it is per search** — `maxResults` applies to each search term and each URL separately, not to the run as a whole, so five terms at 100 can return 500 results. Multiply the cap by how many terms and URLs you entered to see what a run will cost before you start it. Set 20–50 on your first run to confirm the data matches what you need, then raise it or set 0 for everything. Results arrive best-match first, so a lower cap keeps the loosely related tail out of your dataset, and the cap counts products actually saved, so overlapping terms still fill it.
- **Capture a full category with `maxResults: 0`** — paste a category URL and set the cap to 0 to collect every product in that category, then pair it with `price_asc` sort to bring the cheapest shelf prices to the top (ALDI sorts on shelf price, so rank on `pricePerUnit` yourself for true cost-per-kilo).
- **Build your own price history** — ALDI Australia publishes no strike-through was-price, so run this on a schedule and diff `price` by `sku` across datasets; pair that with `onSale` and `availabilityLabel` to tell a short-run Special Buy apart from permanent range.
- **Compare cost-per-unit, not sticker price** — use `pricePerUnit` rather than `price` when benchmarking across brands; a larger pack often wins on cost-per-kilo even at a higher shelf price. Liquor rows are the exception and carry no unit price, so benchmark those on `price` alone.
- **Run keyword searches for moving targets** — keyword searches always reflect the live range, so they catch newly added products and weekly specials that fixed category URLs can miss.
- **Use sort to shape your dataset** — `name_asc` keeps catalogue exports tidy and stable, while `price_desc` surfaces premium products first for assortment analysis.

### Pricing

**From $2.50 per 1,000 results** — among the most affordable ALDI Australia product extractors available, undercutting comparable tools. No compute or time-based charges — you pay per result, plus a small fixed per-run start fee. Bronze, Silver, and Gold subscribers pay progressively less; the table below shows total cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.30 | $0.29 | $0.27 | $0.25 |
| 1,000 | $3.00 | $2.85 | $2.65 | $2.50 |
| 10,000 | $30.00 | $28.50 | $26.50 | $25.00 |
| 100,000 | $300.00 | $285.00 | $265.00 | $250.00 |

A "result" is any product row in the output dataset. The small per-run start fee and any platform fees (storage) are additional and depend on your Apify plan.

**Estimating a run:** `maxResults` caps each search term and each URL separately, so a run can return the cap multiplied by how many terms and URLs you entered. Five terms at 100 can return 500 results, not 100. Multiply before you run, or set the cap to 0 only when you want the full category. A product matched by two of your terms is saved once and billed once, so overlap never costs you twice.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This actor is designed for legitimate price research, market analysis, and product catalogue work. You are responsible for complying with applicable laws and ALDI Australia's Terms of Service. Collect only publicly available product information, do not overload the source site, and do not use the data for any unlawful or deceptive purpose.

# Actor input Schema

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

Products to search for on ALDI Australia, one per line (e.g. 'cheese', 'milk', 'coffee'). Each term runs as its own search. Use one word per term: ALDI matches each word on its own, so 'frozen pizza' returns every product matching 'frozen' OR 'pizza' (182 products, not one of them both), while 'pizza' returns 28 actual pizzas. Every product returned counts as a result, so a single specific word gives you a cleaner dataset for less.

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

Paste ALDI Australia category, product, or search-result URLs (e.g. https://www.aldi.com.au/products/pantry/). Any filters already in the URL are applied automatically. Leave empty if you only use Search Terms above.

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

Maximum number of products to collect for each search term or URL, not for the whole run. This limit multiplies: the cap applies to each search term and each URL separately, so five terms at 100 can return 500 products and you are charged for all 500. To budget a run, multiply this number by how many search terms and URLs you entered. Set to 0 for no limit. A product found by more than one of your terms or URLs is saved once, and only products actually saved count towards this limit. Tip: start with 20-50 to test, then increase.

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

How to order the products within each search or category.

## Actor input object example

```json
{
  "searchTerms": [
    "cheese"
  ],
  "startUrls": [],
  "maxResults": 100,
  "sortBy": "relevance"
}
```

# Actor output Schema

## `products` (type: `string`):

Table of ALDI Australia products with name, brand, price, price-per-unit, pack size, and ALDI's own availability note where one is published.

# 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": [
        "cheese"
    ],
    "startUrls": [],
    "maxResults": 100,
    "sortBy": "relevance"
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/aldi-com-au-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": ["cheese"],
    "startUrls": [],
    "maxResults": 100,
    "sortBy": "relevance",
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/aldi-com-au-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": [
    "cheese"
  ],
  "startUrls": [],
  "maxResults": 100,
  "sortBy": "relevance"
}' |
apify call solidcode/aldi-com-au-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/aldi-com-au-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/lzxFaU4VkjVRdMiIW/builds/piFVtms06kxUC7yHd/openapi.json
