# Aldi UK Scraper — Full Product Catalog & Prices (`studio-amba/aldi-uk-scraper`) Actor

Scrape the full Aldi UK (aldi.co.uk) product catalog: names, brands, in-store prices, price-per-unit, categories, images, descriptions, and ingredients/allergens. Browse-only catalog. No cookies, no login.

- **URL**: https://apify.com/studio-amba/aldi-uk-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

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/platform/actors/running/actors-in-store#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 UK Scraper

Scrape the full Aldi UK (aldi.co.uk) product catalog: names, brands, in-store
prices, price-per-unit, categories, images, descriptions, and where available
ingredients and allergens. No cookies, no login.

### What this actor does

Aldi UK publishes its whole product range on aldi.co.uk as a browse-only
catalog. This actor reads that catalog through Aldi's own public JSON API and
returns clean, flat product records you can drop straight into a spreadsheet,
database, or price-monitoring pipeline.

Leave the input empty and it pulls the entire live catalog (around 3,800
products). Add a search keyword or a category key to narrow it down.

### Important: Aldi UK is a browse-only catalog

Read this before you buy. aldi.co.uk is **not** an online shop. You cannot add
products to a basket and check out. It is a reference catalog of Aldi's range
with in-store prices. That has two consequences for the data:

- **No live stock.** Every product is flagged `notForSale` and there is no
  stock level anywhere on the platform. This actor does not return an
  `inStock` field because Aldi does not expose one.
- **No EAN / GTIN barcodes.** Aldi UK uses internal SKUs only. We verified
  this across every layer of the platform: the listing API, the per-product
  detail API, the product page JSON-LD (no `gtin` property) and the embedded
  page state. Even branded products that certainly carry a barcode (Heinz)
  expose none. There is no barcode field anywhere, so this actor cannot
  return one. The `sku` field is Aldi's internal 18-digit identifier, not a
  retail barcode.

If you match products across scrapes or across your own database, key on
`sku`. It is Aldi's article number: it appears in the product URL, it is the
lookup key of the detail API, and it does not change between runs (verified
by re-checking a sample from an earlier full-catalog run: every product still
listed had the identical `sku` and name; the only misses were rotating
Specialbuys that had left the range). Products can appear in several
categories, but always with the same `sku`.

Prices are the in-store reference prices Aldi shows to shoppers. They are real
and current, but they are not a live e-commerce checkout price.

If you need stock levels or barcodes, this data source cannot provide them. Get
in touch and we will tell you honestly whether another source can.

### How to scrape Aldi data

1. Open the actor and leave every field empty to pull the full catalog, or set
   a `searchQuery` (for example `milk`) to filter.
2. Set `maxProducts` to `0` for the entire catalog, or a small number for a
   quick sample.
3. Leave `includeDetails` on to collect ingredients, allergens, and
   descriptions, or turn it off for a faster price-only run.
4. Run the actor. Results stream into the dataset as clean JSON.
5. Export to CSV, Excel, JSON, or connect the dataset to your own pipeline.

The actor talks to Aldi's public JSON API directly, so it is fast and reliable.
No browser rendering, no cookies, no login, no CAPTCHA solving.

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `searchQuery` | String | No | Keyword filter, e.g. `milk`. Empty = full catalog |
| `categoryKey` | String | No | Restrict to one Aldi category key |
| `maxProducts` | Integer | No | Max products to return. `0` = whole catalog (default 1000) |
| `includeDetails` | Boolean | No | Fetch ingredients/allergens/description per product (default true) |
| `proxyConfiguration` | Object | No | Proxy settings. Optional — the API is public |

#### Getting category keys

Category keys come from Aldi's category tree:

```
https://api.aldi.co.uk/v2/product-category-tree?serviceType=walk-in&servicePoint=C092
```

Each node has a `key` you can pass as `categoryKey`. There are 18 top-level and
145 total categories (Fresh Food, Food Cupboard, Chilled, Frozen, Bakery,
Drinks, Alcohol, SpecialBuys, and more).

### Output

Each result contains:

| Field | Type | Example |
|-------|------|---------|
| `name` | String | `"Cowbelle Lactose Free Milk"` |
| `brand` | String | `"Cowbelle"` |
| `price` | Number | `1.50` |
| `currency` | String | `"GBP"` |
| `originalPrice` | Number | `1.99` (when on a price drop) |
| `pricePerUnit` | String | `"£1.50/1 Each"` |
| `discount` | String | `"Save 50p"` |
| `sku` | String | `"000000000000422329"` (internal, not a barcode) |
| `url` | String | Full product page URL |
| `imageUrl` | String | Primary product image (up to 1500px) |
| `imageUrls` | Array | All product images |
| `productDescription` | String | Product description text |
| `category` | String | `"Clothing"` |
| `categories` | Array | `["SpecialBuys", "Clothing"]` |
| `specs` | Object | `{ "ingredients": "...", "allergens": "...", "sellingSize": "1 Each" }` |
| `notForSale` | Boolean | `true` (always — browse-only catalog) |
| `scrapedAt` | String | ISO 8601 timestamp |

Fields intentionally absent: `inStock` and `ean`. Aldi UK exposes neither.

### Example output

```json
{
    "name": "Pork Chipolata Sausages 12 Pack",
    "brand": "Ashfields",
    "price": 1.99,
    "currency": "GBP",
    "pricePerUnit": "£0.30/100g",
    "sku": "000000000000418762",
    "url": "https://www.aldi.co.uk/product/pork-chipolata-sausages-000000000000418762",
    "imageUrl": "https://dm.emea.cms.aldi.cx/is/image/aldiprodeu/.../product",
    "category": "Fresh Meat",
    "categories": ["Fresh Food", "Fresh Meat"],
    "specs": {
        "sellingSize": "660g",
        "pricePerUnit": "£0.30/100g",
        "ingredients": "BRITISH PORK 90%, Water, Rice Flour, Sea Salt, ...",
        "allergens": "Rice"
    },
    "notForSale": true,
    "language": "en",
    "scrapedAt": "2026-07-03T14:30:00.000Z"
}
```

### Catalog size and completeness

The live Aldi UK catalog is around **3,750–3,790 products**. The API reports a
`totalCount` near 3,787, but that figure is a search-index aggregate that sits a
hair above the set the API will actually return: paging the whole catalog yields
about **3,756 unique products**. This is not a scraper gap. Walking all 145
categories independently converges on the same set (and is in fact a subset of
it), so unfiltered paging is the most complete method available and the ~1%
difference is index items the API counts but never serves. The actor runs a
completeness check every run: it compares captured unique SKUs against
`totalCount` and, if paging is ever truncated by an error, it fails the run
rather than deliver a silent partial catalog.

The sitemap lists more URLs (about 5,352) but many are stale or rotated-out
listings such as past SpecialBuys, so the live API set is the authoritative
current range, not the sitemap.

SpecialBuys (Aldi's rotating non-food deals such as clothing and homeware)
appear only while active, roughly 330 at any time, and are included. The actor
dedupes by SKU, so cross-cutting collections like Price Drops, Specially
Selected or Summer Range never produce duplicate rows.

Field coverage on a full run: name, price, url, sku and currency are populated
on 100% of rows; brand on ~99.6% (some own-label lines carry no brand);
category on ~99.7%; image on ~95.8%. The image and category gaps are products
that carry no asset or category in Aldi's own data, not scraping misses.

### Cost estimate

A full-catalog run with details is roughly 3,850 API requests (about 64 catalog
pages plus one detail call per product). A price-only run (`includeDetails`
off) is about 64 requests for the whole catalog. Both are light — the API is
fast and needs no browser.

### Limitations

- Browse-only catalog: no live stock, no `inStock` field, no online purchasing.
- No EAN/GTIN barcodes anywhere on the platform. `sku` is Aldi's internal code.
- Some descriptions contain placeholder text on newer or non-food lines.
- Prices are in-store reference prices, current but not a checkout price.
- Data is scraped from the public catalog and may change without notice.

### Need this data on a schedule, or a custom version?

We run this scraper as a managed service for businesses: scheduled runs,
deduplication, delta detection, and delivery to your inbox, Google Sheets,
or API — maintenance included. We can also build a custom version with your
exact fields and filters, or combine multiple sources into one feed.

See [studioamba.dev/services](https://studioamba.dev/services/) or email
<hello@studioamba.dev> for a free data sample.
We maintain 300+ European web scrapers and answer within one business day.

# Actor input Schema

## `searchQuery` (type: `string`):

Optional keyword to filter products, e.g. 'milk' or 'sausages'. Leave empty to browse the full catalog.

## `categoryKey` (type: `string`):

Optional Aldi category key to restrict results to one category, e.g. '1588161416584096' (SpecialBuys). Get keys from https://api.aldi.co.uk/v2/product-category-tree?serviceType=walk-in\&servicePoint=C092 . Leave empty for all categories.

## `maxProducts` (type: `integer`):

Maximum number of products to return. Set to 0 for the entire catalog (~3,800 products). The full live catalog is roughly 3,787 items.

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

Fetch ingredients, allergens, description, storage and origin for each product (one extra request per product). Turn off for a faster, price-only run.

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

Proxy settings. The Aldi UK API is public and low anti-bot, so a proxy is optional. Residential GB is the safe default for large runs.

## Actor input object example

```json
{
  "searchQuery": "milk",
  "maxProducts": 20,
  "includeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# 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 = {
    "searchQuery": "milk",
    "maxProducts": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "GB"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/aldi-uk-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 = {
    "searchQuery": "milk",
    "maxProducts": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "GB",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/aldi-uk-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "searchQuery": "milk",
  "maxProducts": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}' |
apify call studio-amba/aldi-uk-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=studio-amba/aldi-uk-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/XXfE8J7cpxKE4SujF/builds/8fqoZ7j4Ni2x7iwlI/openapi.json
