# ALDI Ireland Scraper — Prices, Unit Prices, Specialbuys (`architekture/aldi-ie-scraper`) Actor

ALDI Ireland (aldi.ie) scraper: product name, brand, size, price in EUR, was price, saving, unit price, availability, Specialbuys on-sale date, category, image, URL; detail rows add ingredients, storage, nutritional claims, origin. Keyword, category or SKU. Pay per result, no login.

- **URL**: https://apify.com/architekture/aldi-ie-scraper.md
- **Developed by:** [architek.earth](https://apify.com/architekture) (community)
- **Categories:** AI, E-commerce
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.

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

## ALDI Ireland Scraper — Prices, Unit Prices, Specialbuys

**Recorded run: 60 products from 1 search term in 5 seconds** (2026-10-22, build 0.0.207, run `ddfu7naWWHXAsRBvn`). 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.

ALDI Ireland product prices, unit prices, Specialbuys dates and ingredients from aldi.ie, by keyword, category or SKU.

| Source | Market | From | Standout fields |
|---|---|---|---|
| ALDI (aldi.ie) | Ireland | $1.00 / 1,000 products | `price` / `wasPrice`, `unitPrice`, `onSaleDate`, `ingredients` |

### ✅ Why choose this scraper

#### ALDI Ireland prices and sale prices in one row

`price` (EUR), `wasPrice`, `onSale` and ALDI's own `savingsText` (for example `"7%"`) come back together on every product row. `wasPrice` appears only when it is above the current price.

#### ALDI Ireland unit prices for pack-size comparison

`unitPrice` and `unitPriceLabel` (for example `1.49` per `"1 L"`) are on basic rows wherever ALDI publishes a comparison price, with `size` as the pack-size text.

#### ALDI Ireland Specialbuys with on-sale dates

`categories: ["Specialbuys"]` lists the SpecialBuys range, and `onSaleDate` / `onSaleDateText` (for example `"2026-10-22"` / `"In Store Thu 22 Oct"`) mark products ALDI schedules for a date.

#### ALDI Ireland ingredients and storage instructions

With `includeDetails: true` or `skus`, rows add `ingredients`, `storageInstructions`, `nutritionalClaims` and `description` where ALDI publishes them. A row is charged as `product-detail` only when at least one detail field came back; on 2026-10-22, 10 of 10 rows from Chilled Food > Milk did.

#### Measured on a schedule

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

### ⚠️ Worth knowing up front

- ALDI Ireland does not sell groceries online. The API lists the in-store range, and every product recorded so far has `availability: "in_store_only"`. There is no store selector, so prices are the single aldi.ie price list, not a specific shop.
- No barcodes (EAN/GTIN), no per-100 g nutrition table and no stock levels: ALDI's Irish product API does not publish them.
- `allergens` is in the schema but was empty on every detail row recorded so far; ALDI puts allergen statements in `nutritionalClaims` (`"May contain"`, `"Free from"`). Detail is sparse on some products, and fields ALDI does not publish are omitted, never null.
- Products are de-duplicated by `sku` across all inputs, and SKUs run first. `maxItemsPerQuery` caps each search term or category (default 100; `0` means up to 5,000). A run takes at most 50 search terms plus categories and 500 SKUs.
- A run stopped by your spending limit (`BUDGET_LIMIT`) or 45 seconds before its timeout (`TIME_LIMIT`) keeps what it delivered and saves `PROGRESS`; that is a partial collection. A resurrected or migrated run skips delivered SKUs and never charges them again.
- Unknown categories, unknown SKUs and blocked or failed queries return a free status row (`"recordType": "query"`) that says what happened. Invalid input stops before collection with one free `"recordType": "status"` row, a status message and `RUN_SUMMARY.status` `INVALID_INPUT`; a run stopped by your spending limit, the timeout or a failed progress save adds one free status row naming the stop; a search with no matches ends as `NO_PRODUCTS`. None of these is charged.

### ⚡ Try the example

This actor has no free preview; the example below costs about $0.02.

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

```json
{
  "searchTerms": ["milk"],
  "maxItemsPerQuery": 20,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

Add `"includeDetails": true` for ingredients and storage instructions, or `"categories": ["Chilled Food"]` for a whole aisle.

### ⚙️ Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `searchTerms` | array | — (prefill: `milk`) | Keywords such as `milk` or `coffee pods`. Up to 50 search terms plus categories per run. |
| `categories` | array | — | Category name (`Chilled Food`, `Milk`, `Specialbuys`), slug (`chilled-food/milk`) or aldi.ie category URL. A category that does not exist gets one free status row. |
| `skus` | array | — | SKU (`422541` or `000000000000422541`) or aldi.ie product URL. Returns detail fields where ALDI has them. Up to 500. |
| `maxItemsPerQuery` | integer | `100` | Cap per search term or category. `0` means everything, up to 5,000. |
| `includeDetails` | boolean | `false` | Adds ingredients, allergens, storage and usage instructions, nutritional claims, origin and description. One extra request per product. |
| `sort` | select | `relevance` | `relevance`, `price_asc`, `price_desc`, `name_asc`, `name_desc`. Matters when `maxItemsPerQuery` cuts a result set. |
| `proxyConfiguration` | proxy | `{"useApifyProxy": true}` (datacenter) | Blocked or rate-limited requests are retried on a fresh IP, up to 4 attempts. |
| `feedback` | string | — | 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.

| Field | Type | Meaning |
|---|---|---|
| `retailer` | string | Always `"ALDI IE"`. |
| `sku` | string | 18-digit ALDI SKU; the join key within ALDI Ireland. |
| `name` / `brand` / `size` | string | Product name, brand and pack-size text (for example `"1 l"`). |
| `price` / `currency` | number / string | Current shelf price and `"EUR"`. |
| `wasPrice` / `savingsText` | number / string, omitted when absent | Previous price and ALDI's saving label, when the product is on sale. |
| `onSale` | boolean | True when a was-price or saving label is shown. |
| `unitPrice` / `unitPriceLabel` | number / string, omitted when absent | Comparison price and its unit, for example `1.49` per `"1 L"`. |
| `availability` | string | `in_store_only`, `available`, `discontinued` or `unknown`. |
| `onSaleDate` / `onSaleDateText` | string, omitted when absent | Specialbuys date and ALDI's date label. |
| `category` / `categoryPath` | string | Leaf category and full path, for example `"Chilled Food > Milk"`. |
| `image` / `url` | string | 800 px product image and aldi.ie product page. |
| `source` | object | `{"source": "search" \| "category" \| "sku", "searchTerm", "category", "categoryUrl", "page"}`. |
| `recordType` | string | `"product"` on product rows; `"query"` on free per-query status rows (with `query`, `status`, `reason`); `"status"` on free run status rows (with `status`, `message`: `INVALID_INPUT`, `BUDGET_LIMIT`, `TIME_LIMIT`, `STATE_SAVE_FAILED`). |

Detail rows also carry `description`, `ingredients`, `allergens`, `countryOfOrigin`, `storageInstructions`, `usageInstructions`, `nutritionalClaims` and `warnings` where ALDI publishes them. Other fields are extras, not part of the contract. To have one pinned, say so in `feedback`.

### 📦 Output example

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

```json
{
  "recordType": "product",
  "retailer": "ALDI IE",
  "sku": "000000000000422541",
  "name": "Protein Milk",
  "brand": "CLONBAWN",
  "size": "1 l",
  "price": 1.49,
  "currency": "EUR",
  "onSale": false,
  "unitPrice": 1.49,
  "unitPriceLabel": "1 L",
  "availability": "in_store_only",
  "category": "Milk",
  "categoryPath": "Chilled Food > Milk",
  "url": "https://www.aldi.ie/product/clonbawn-protein-milk-000000000000422541",
  "source": { "source": "search", "searchTerm": "milk", "page": 1 }
}
```

With details on, the same product adds `"ingredients": "1% Fat"`, `"storageInstructions": "Keep refrigerated below 5°C."` and `"nutritionalClaims": [{"label": "May contain", "value": "Nuts"}]`.

A free status row looks like this:

```json
{
  "recordType": "query",
  "query": "category:Nope",
  "status": "NOT_FOUND",
  "reason": "no ALDI IE category matches 'Nope'"
}
```

### 🧠 Advanced usage

#### Track ALDI Ireland price changes weekly

Run the same categories every week and diff `price` and `wasPrice` by `sku` between datasets. Check that `RUN_SUMMARY.status` is `COMPLETE` before treating a run as finished.

#### List this week's ALDI Ireland Specialbuys

Set `categories: ["Specialbuys"]` and `maxItemsPerQuery: 0`, then sort by `onSaleDate`; `categoryPath` (for example `"SpecialBuys > DIY"`) splits the range by aisle.

#### Check ingredients for a list of ALDI Ireland products

Pass product SKUs or URLs in `skus`. Each returns a detail row; an SKU ALDI does not have returns a free `NOT_FOUND` row with the reason `"ALDI IE has no product with this SKU"`.

#### Scrape a whole ALDI Ireland aisle

Use a top-level category such as `Chilled Food` with `maxItemsPerQuery: 0`. `RUN_SUMMARY.queries[]` gives `listed` (ALDI's count) and `delivered` per query; on 2026-10-18 Chilled Food listed and delivered 578 products.

### 🔌 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 Specialbuys category picks up new `onSaleDate` items; daily suits price tracking. Copy-paste code in Python, Node, curl and n8n: [architek-earth/examples/aldi-ie-scraper](https://github.com/architek-earth/examples/tree/main/aldi-ie-scraper).

### 💸 Pricing

Pay per result. Platform and proxy usage are included. Status rows, failed requests and blocked pages are free.

| Event | Price | What it covers |
|---|---|---|
| `product` | $1.00 / 1,000 products | One delivered search, category or SKU row, including a row requested with details that came back without any detail field. |
| `product-detail` | $4.00 / 1,000 products | One delivered row that carries detail fields (ingredients, storage, claims and so on), from `includeDetails` or `skus`. |

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

### ❓ FAQ

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

**Do I need an ALDI account or login?** No. No account, cookies or API key from ALDI.

**Can I get ALDI Ireland prices for a specific store?** No. There is no store selector; the actor returns the single aldi.ie price list.

**Can I get ALDI Ireland Specialbuys?** Yes. Use `categories: ["Specialbuys"]`; scheduled products carry `onSaleDate` and `onSaleDateText`.

**Can I get ALDI Ireland barcodes (EAN) or nutrition information?** No barcodes and no per-100 g nutrition table; ALDI does not publish them. Detail rows give `ingredients` and `nutritionalClaims` such as `"Free from"` and `"May contain"`.

**Can I check ALDI Ireland stock or order online?** No. ALDI Ireland has no online grocery shop, products come back as `in_store_only`, and there are no stock levels.

### 🤖 For AI agents & LLM apps

Paste this into your AI assistant:

`architekture/aldi-ie-scraper` on Apify. Python: `from apify_client import ApifyClient; client = ApifyClient("TOKEN"); run = client.actor("architekture/aldi-ie-scraper").call(run_input={"searchTerms": ["milk"], "maxItemsPerQuery": 20, "proxyConfiguration": {"useApifyProxy": True}}); items = client.dataset(run["defaultDatasetId"]).list_items().items` (page with `offset`/`limit` for large exports). Rows with `recordType == "query"` are free and explain unknown, blocked or failed inputs. Full input schema and README: `GET https://api.apify.com/v2/acts/architekture~aldi-ie-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**

- [Coles Scraper](https://apify.com/architekture/coles-au-product-scraper) — prices, unit prices, specials, barcodes
- [Woolworths AU Scraper](https://apify.com/architekture/woolworths-au-product-scraper) — prices, specials, barcodes, nutrition
- [ALDI AU Scraper](https://apify.com/architekture/aldi-au-product-scraper) — prices, unit prices, Special Buys
- [Woolworths NZ Scraper](https://apify.com/architekture/woolworths-nz-scraper) — prices, club prices, specials
- [New World NZ Scraper](https://apify.com/architekture/new-world-nz-scraper) — store prices, Clubcard offers, promotions
- [Pak'nSave Scraper](https://apify.com/architekture/paknsave-nz-scraper) — store prices, unit prices, promotions
- [Tesco UK Scraper](https://apify.com/architekture/tesco-uk-scraper) — prices, Clubcard offers, barcodes
- [Sainsbury's Scraper](https://apify.com/architekture/sainsburys-uk-scraper) — prices, unit prices, offers, barcodes
- ALDI Ireland Scraper — *you are here*
- [Dunnes Stores Scraper](https://apify.com/architekture/dunnes-ie-scraper) — fashion and home prices, sizes, EANs
- [Mercadona Scraper](https://apify.com/architekture/mercadona-es-scraper) — prices, unit prices, categories

Full catalogue: [github.com/architek-earth](https://github.com/architek-earth).

architek.earth · code like concrete

### 🙋 Support & legal

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 aldi.ie, the same pages any visitor sees without logging in. It does not bypass authentication. It is not affiliated with or endorsed by ALDI. 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-25** — \[internal] Studio core 1.0.5 (from 1.0.4). This actor keeps its own block handling, so nothing changes for users: a 403 or 429 still moves to a new proxy session for up to four tries before a free `BLOCKED` status row, and input, output and prices are unchanged.
- **2026-10-24** — A search, category or SKU stopped as `BLOCKED` now saves the site's last response (redacted) in the run's key-value store so the cause can be checked; pricing, input and output are unchanged.
- **2026-10-22** — Runs on the studio core: a challenge page from ALDI is reported as `BLOCKED` at once; a run whose last row spends the spending limit exactly ends `COMPLETE`; invalid input and clean stops add one free `"recordType": "status"` row. Output fields and prices unchanged.
- **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-18** — 1.0: search, category and SKU modes; detail charged only when ALDI returns detail; free status rows; clean stops at spending limit and timeout; resumable after platform migration.

# Actor input Schema

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

Keywords to search on aldi.ie, e.g. milk or coffee pods. Results are de-duplicated by SKU across all terms and categories.

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

ALDI IE categories by name (Chilled Food, Milk), slug (chilled-food/milk) or aldi.ie category URL. A category that does not exist gets one free status row.

## `skus` (type: `array`):

Specific products by SKU (422541 or 000000000000422541) or aldi.ie product URL. Always returns detail fields where ALDI publishes them. Up to 500.

## `maxItemsPerQuery` (type: `integer`):

0 = everything (up to 5,000 per query).

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

One extra request per product. Rows that come back with detail fields are charged as product-detail; rows ALDI publishes no detail for are charged as product.

## `sort` (type: `string`):

Order in which ALDI returns results (matters when maxItemsPerQuery cuts a result set).

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

Apify datacenter proxy is the tested default. Blocked or rate-limited requests are retried on a fresh IP.

## `feedback` (type: `string`):

Tell the maintainers what you needed and did not get. Read by a human; does not change the output.

## Actor input object example

```json
{
  "searchTerms": [
    "milk"
  ],
  "maxItemsPerQuery": 60,
  "includeDetails": false,
  "sort": "relevance",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per product; queries that found nothing or failed add one free recordType: query row.

## `summary` (type: `string`):

RUN_SUMMARY: status per query and charges.

# 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": [
        "milk"
    ],
    "maxItemsPerQuery": 60,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("architekture/aldi-ie-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": ["milk"],
    "maxItemsPerQuery": 60,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("architekture/aldi-ie-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": [
    "milk"
  ],
  "maxItemsPerQuery": 60,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call architekture/aldi-ie-scraper --silent --output-dataset

```

## MCP server setup

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