ALDI AU Scraper - Groceries, Special Buys & Prices
Pricing
from $1.00 / 1,000 product results
ALDI AU Scraper - Groceries, Special Buys & Prices
Scrape ALDI Australia (aldi.com.au) products: name, brand, price, was-price, savings, unit price, size, category, images, availability and Special Buys on-sale date, plus full detail (ingredients, allergens, nutrition). Search by keyword or category, filter by brand/theme, or paste any ALDI URL.
Pricing
from $1.00 / 1,000 product results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
2
Bookmarked
8
Total users
6
Monthly active users
2.4 hours
Issues response
2 days ago
Last modified
Categories
Share
ALDI Australia Scraper: Prices, Special Buys & Full Product Detail
ALDI Australia Scraper turns aldi.com.au into structured product data. Get product name, canonical title, brand, current price, numeric was-price with savings amount and percent, unit (comparison) pricing, selling size, full category path, image gallery, availability and Special Buys on-sale date on every record. Search by keyword or category, pull the Special Buys, Lower Prices or Super Savers range directly, or paste any ALDI product, category or search link. Switch on detail enrichment for the full description, ingredients, allergen statements, nutritional claims, storage and usage instructions and country of origin, then export to JSON, CSV or Excel, or read results straight from the API.
Why This Scraper?
- Four ways to collect. Pull a Special Buys, Lower Prices or Super Savers range directly, search by keyword, list any grocery category, or paste ALDI product, category or search links.
- Real pricing detail. Numeric was-price with savings amount and percent alongside the pre-formatted display strings, plus unit (comparison) pricing on every record.
- Optional full detail. Description, ingredients, allergen statements, nutritional claims, storage and usage instructions and country of origin, switched on per run.
- Department control. Filter by brand or theme, and drop whole departments from your output by each product's own reported category, even when a promo range cross-lists it from elsewhere.
- Built for schedules. Incremental mode returns only new, updated, reappeared and expired products on recurring runs, and continuing one interrupted crawl never re-collects or re-charges what it already gathered.
- Ready-to-use media and links. A direct product URL, its category page URL, a main image and the full ready-to-download image gallery on every record.
- Special Buys themes and calendar. Every Special Buys product is tagged with its ALDI theme (BBQ, Gardening, Christmas...), and each run that touches Special Buys saves ALDI's current on-sale calendar with the themes of every date.
Use Cases
- Price monitoring teams: track ALDI's everyday-low prices and Special Buys week over week to catch changes before shoppers do.
- Grocery comparison sites: combine numeric price, unit price and savings percent across categories to power a comparison engine.
- Range and promo research: pull Special Buys, Lower Prices or Super Savers directly to see what ALDI is currently promoting.
- Nutrition and compliance review: collect ingredients, allergen statements and nutritional claims for a whole category at once with detail enrichment on.
- Catalogue history: run Incremental mode on a schedule to build a running record of price changes, new listings and discontinued products.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
sku | "000000000011112222" (the canonical per-product key; use this to dedupe/join, not abstractSku) |
abstractSku | "000000000011112222A" (groups sibling variants that are still different products, e.g. different flavours or sizes of the same base item) |
name / title | "Full Cream Milk 2L" / "SAMPLE BRAND Full Cream Milk 2L" (title prefixes the brand when it isn't already part of the name) |
brand | "SAMPLE BRAND" |
price / priceDisplay | 7.29 / "$7.29" |
wasPrice / wasPriceDisplay | 8.99 / "$8.99" (populated only while the product is actually discounted) |
savingsAmount / savingsPercent | 1.7 / 18.9 |
savingsDisplay / promoLabel | "Save $1.70" / "Save $1.70" |
onSale | true |
unitPrice / unitPriceDisplay | 3.65 / "$3.65 per 1 L" |
unitOfMeasure / unitMeasure | "L" / "1L" (parsed from the same display string as unitPrice; always read the two together, never unitPrice alone) |
perUnitQuantity / perUnitQuantityUnit | 0.18 / "kg" (loose-produce configured weight, not a price; empty on packaged items like this one) |
sellingSize | "2 L" |
categoryPath / category / categoryUrl | "Dairy, Eggs & Fridge > Milk" / "Milk" / "https://www.aldi.com.au/products/dairy-eggs-fridge/milk/k/1111111160" (the listing page of the product's own category) |
categories | [{"id": "960000000", "name": "Dairy, Eggs & Fridge", "path": "dairy-eggs-fridge"}, {"id": "1111111160", "name": "Milk", "path": "dairy-eggs-fridge/milk"}] |
promotions / themes | ["Lower Prices"] / ["Pet Essentials"] (the promotional ranges the product sits on: Limited Time Only, Lower Prices, Super Savers; and its ALDI theme, e.g. a Special Buys theme. [] when none; themes is left empty when ALDI's theme list for that search is too long to read completely) |
position / input / inputType | 3 / "milk" / "searchTerm" (rank in ALDI's own result list, and which search term, category, Special Buys date or URL found it) |
scrapedAt | "2026-10-06T01:02:03Z" |
isSpecialBuy / onSaleDateDisplay | true / "On Sale Sat 5 Jul" (set whenever the product carries a Special Buys on-sale date) |
images / imagesCount / imageUrl | ["https://cdn.aldi.com.au/products/full-cream-milk-2l.jpg"] / 1 / "https://cdn.aldi.com.au/products/full-cream-milk-2l.jpg" (imageUrl is the main image on its own, ready for a table or spreadsheet) |
url | "https://www.aldi.com.au/product/full-cream-milk-2l-000000000011112222" |
description | "Full product description appears here when Fetch product details is on." |
ingredients | "Full-cream milk." |
allergenStatements | ["Contains: Milk"] (derived from nutritionalClaims; ALDI's own allergens array is always empty) |
changeType / changedFields / previousValues | "UPDATED" / ["price", "wasPrice"] / {"price": 7.99, "wasPrice": null} (Incremental mode only; previousValues is each changed field's value on the previous run) |
Every record also carries the product's own top-level department, a notForSale flag, currency and currency symbol, quantity/weight metadata, bottle deposit and fee text where they apply, age restriction and alcohol content on restricted items, badges, images-gallery detail such as usage/storage instructions and warnings once detail enrichment is on, and a detailFetched flag. perUnitPrice is always empty: it is a deprecated field kept for compatibility; the honest per-kg price is unitPrice read together with unitMeasure. Incremental mode also adds firstSeenAt / lastSeenAt timestamps.
How to Use
- Pick a mode:
search(keyword, category or a Specials range) orurl(paste ALDI links). - In search mode, add search terms and/or categories, optionally pick a Specials/offers range, and filter by brand or theme.
- Turn on Fetch product details if you need the full description, ingredients and allergen data, and set Max products to control run size and cost.
- Click Start, then download the dataset as JSON, CSV or Excel, or read it through the API.
Search by keyword:
{"mode": "search","searchTerms": ["milk", "coffee"],"maxItems": 50}
Scrape a Specials range directly, with full detail:
{"mode": "search","specialsCategory": "special-buys","fetchDetails": true,"maxItems": 100}
Paste URLs (every supported shape):
{"mode": "url","urls": ["https://www.aldi.com.au/product/sample-product-000000000099998888","https://www.aldi.com.au/products/dairy-eggs-fridge/milk/k/1111111160","https://www.aldi.com.au/products","https://www.aldi.com.au/special-buys/2026-10-07?theme=Pet+Essentials","https://www.aldi.com.au/special-buys","https://www.aldi.com.au/results?q=milk","https://www.aldi.com.au/products/dairy-eggs-fridge/milk/k/1111111160?brand-name=FARMDALE&sort=price_asc"]}
Recurring monitoring, with a full uncapped scan so expired products can be detected:
{"mode": "search","categories": ["Dairy, Eggs & Fridge"],"incrementalMode": true,"emitExpired": true,"maxItems": 0}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/aldi-com-au-scraper").call(run_input={"mode": "search", "searchTerms": ["milk"], "maxItems": 50})for product in client.dataset(run["defaultDatasetId"]).iterate_items():print(product["name"], product["price"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/aldi-com-au-scraper').call({ mode: 'search', searchTerms: ['milk'], maxItems: 50 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Every supported URL shape (url mode)
A pasted product URL always returns that single product with its full detail page, regardless of Fetch product details; there is no way to get a catalogue-only row for a single product URL. The detail-enrichment charge for it still only applies when Fetch product details is on, same as any other record. Every other shape below behaves like the equivalent search-mode run: it returns the full result set up to Max products and respects Fetch product details.
| Shape | Example | What it returns |
|---|---|---|
| Product detail | https://www.aldi.com.au/product/<slug>-<sku> | That one product, full detail. |
| Category listing | https://www.aldi.com.au/products/<path>/k/<categoryKey> | That category's full result set. |
| Whole range | https://www.aldi.com.au/products | The entire catalogue (3184+ products), no category filter applied. |
| Special Buys (one date) | https://www.aldi.com.au/special-buys/<YYYY-MM-DD> | Everything on sale that day. Append ?theme=<Theme Name> to narrow to one theme (e.g. Pet Essentials). |
| Special Buys (landing page) | https://www.aldi.com.au/special-buys | Auto-walks every on-sale date the landing page currently lists, one scope per date, no need to know the dates in advance. |
| Keyword search | https://www.aldi.com.au/results?q=<term> (or /search?q=<term>) | That keyword's full result set, same as Search mode. |
| Any listing + filter params | append ?brand-name=<Brand>&category-tree=<key>&theme=<Theme>&sort=<order>&page=<n> to any category/Special-Buys/search link above | The filters the pasted URL's own query string carries are read straight off it and override the Brands/Themes/Sort by inputs for that URL; page=<n> starts the walk at that page instead of page 1; a page-started link never looks at the pages before it, so it skips Incremental mode's EXPIRED detection for that scope on that run (see below). |
Two ALDI pages are not product listings at all and are not supported: a pasted link to either logs a clear warning and is skipped rather than silently returning zero, https://www.aldi.com.au/christmas (a fixed, hand-curated showcase, not a filterable listing) and https://www.aldi.com.au/aldi-prices (a marketing/explainer page with no product data). Special Buys and weekly-specials ranges that only exist as ordinary category nodes (not date-scoped promotions) still work via the plain category-listing shape above, e.g. pasting the "Limited Time Only" category link.
Dates on the Special Buys pages are the site's own current promotion window and change weekly. The examples above (and in the URL field's prefill) show the form a link takes; paste today's actual link from aldi.com.au/special-buys for a live date, or just paste the bare landing page and let the actor find every current date for you.
Specials ranges and department control
Lower Prices, Super Savers and similar promo ranges report a large product count on ALDI's own site, but adding them to categories alongside your grocery aisles usually yields few additional rows: they cross-list products that already belong to a real department, and the actor's within-run dedupe keeps only the first copy it sees. To find what's currently discounted, filter on onSale / wasPrice on the record itself rather than on which range you queried it under. Use excludeCategories to drop a whole department from your output after the fact: it matches each record's own reported categoryPath, so it also removes products a promo range cross-listed from a department you never queried at all.
Resume and recurring updates
- Resume from run/dataset (
resumeFromRunId) continues one specific interrupted crawl: paste the earlier run's id and this run skips every product id it already collected, so you don't pay twice. If this run itself is resumed by the Apify platform (a migration or Resurrect), that in-progress state always takes precedence and the pasted id is ignored. - Incremental mode (
incrementalMode) is for a search/category/URL set you run on a schedule. Each product is classifiedNEW,UPDATED(withchangedFieldsnaming exactly what changed),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEARED, orEXPIRED.REAPPEAREDonly ever fires for a product a previous run had already tombstoned asEXPIRED; it is not a generic "back after a gap" signal.EXPIREDitself is only ever produced once a run has proved a complete, uncapped scan of every search term, category and URL it was given, with noresumeFromRunIdin play; a Max-products cap, an unresolved category or URL, or a fetch failure all withholdEXPIREDdetection for that run rather than risk a false positive, and the run log explains why. EveryUPDATEDrow also carriespreviousValues, the value each changed field had last time, so a price change reads as "was 7.99, now 7.29" without keeping your own copy of the last run. If a field turns out to be noisy on your own run cadence, list it inignoreFieldsForChangesso it no longer makes a product count asUPDATED(it is still returned in the output). With Incremental mode off, output is exactly as before.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each product, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | How to find products: search (keyword/category/specials) or url (paste ALDI links). |
searchTerms | array | no default (prefill: ["milk"]) | Keywords to search the catalogue (search mode); each term is paginated fully up to Max products. |
categories | array | no default (empty) | Category names, URL slugs or numeric keys to list, including Special Buys, Lower Prices, Super Savers and any grocery aisle. |
specialsCategory | string | "" (no specials filter) | Add a promotional range directly: Special Buys, Lower Prices or Super Savers (search mode). |
excludeCategories | array | no default (empty) | Department names to drop from the OUTPUT, matched against each product's own reported categoryPath. |
brands | array | no default (empty) | Filter by brand name as shown on ALDI. |
themes | array | no default (empty) | Filter by ALDI theme label. |
specialBuysDates | array | no default (empty) | Special Buys on-sale dates to scrape (search mode), e.g. 2026-10-08, 8 Oct or Wed 8 October; all covers every date on ALDI's Special Buys page, upcoming the dates from today onward. Brands/Themes still apply. |
sortBy | string | relevance | Result ordering, applied by ALDI itself before Max products is reached: relevance, price_asc, price_desc, name (A-Z) or name_desc (Z-A). |
onSaleOnly | boolean | false | Only return products on a promotion: a Special Buy, a promotional range (Limited Time Only, Lower Prices, Super Savers) or a was-price. Filtered-out products are not returned and not charged. |
minPrice | number | no default (empty) | Inclusive minimum price in AUD. Filtered-out products are not returned and not charged. |
maxPrice | number | no default (empty) | Inclusive maximum price in AUD. Filtered-out products are not returned and not charged. |
urls | array | no default (prefill: one example of every supported shape) | ALDI URLs to scrape (url mode): product, category, whole-range, Special Buys date/landing, or search URLs. A pasted URL's own filter query params override the Brands/Themes/Sort by inputs for that URL. See the URL-shape table above. |
fetchDetails | boolean | false | Add full detail fields to every product; one extra request and one detail-enrichment charge per product. A pasted product URL always fetches full detail regardless of this toggle, but is only charged for it when this is on. |
maxItems | integer | 20 | Maximum products to scrape across all terms/categories/URLs. 0 = unlimited. |
maxPages | integer | no default (empty = no extra page cap) | Optional safety cap on result pages per term/category (60 products per page); the run still stops at Max products. |
includeCategoryTree | boolean | false | Also save ALDI's full category tree (key, name, path, URL, parent, depth) to the key-value store record CATEGORY_TREE. Not added to the dataset, not charged. |
proxy | object | no default (prefill: Apify Proxy, automatic) | Proxy used for requests. On a plan without Apify proxy access the run warns once and continues on a backup connection (see Plan Requirement). |
resumeFromRunId | string | no default (empty) | Paste a previous run id from this actor to continue one interrupted crawl without duplicate pushes or charges. |
incrementalMode | boolean | false | Remember this search's baseline across scheduled runs and return only NEW/UPDATED/REAPPEARED/EXPIRED products. |
stateKey | string | no default (empty) | Manual key for Incremental mode's baseline; leave empty to derive one automatically from this run's search scope. |
emitUnchanged | boolean | false | Also return (and bill) every unchanged product every run (Incremental mode). |
emitExpired | boolean | false | Also return (and bill) products no longer found after a complete scan (Incremental mode). |
ignoreFieldsForChanges | array | no default (empty) | Incremental mode only: output field names that should NOT make a product count as UPDATED, even when they change (matches a field name at any nesting depth, e.g. inside a nested object). Measured empty by default: a live re-fetch of the same products found no rotating/volatile field on this actor's data. Ignored fields are still returned in the output. |
mcpConnectors | array | no default (empty) | Optional: send a summary of each product to apps you authorized under Integrations. |
notionParentPageUrl | string | no default (empty) | Notion connector only: page under which product pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run; does not affect the dataset. |
Output views
Next to the default table, the dataset's Products Overview output carries every field in one row. Three narrower views give you the same rows with just the columns for one job: Detail enrichment (the fields fetchDetails adds), Changes (incremental mode) (changeType, changedFields, previousValues, firstSeenAt/lastSeenAt next to the product's name, price and link) and Special Buys (main image, on-sale date, theme, promo label and savings alongside price). Switch between them on the run's Dataset tab, or fetch one directly through the API with ?view=detail, ?view=changes or ?view=specialBuys.
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "000000000011112222","sku": "000000000011112222","abstractSku": "000000000011112222A","name": "Full Cream Milk 2L","title": "SAMPLE BRAND Full Cream Milk 2L","brand": "SAMPLE BRAND","slug": "full-cream-milk-2l","url": "https://www.aldi.com.au/product/full-cream-milk-2l-000000000011112222","price": 7.29,"priceDisplay": "$7.29","wasPrice": 8.99,"wasPriceDisplay": "$8.99","savingsAmount": 1.7,"savingsPercent": 18.9,"savingsDisplay": "Save $1.70","promoLabel": "Save $1.70","onSale": true,"promotions": ["Lower Prices"],"unitPrice": 3.65,"unitPriceDisplay": "$3.65 per 1 L","unitOfMeasure": "L","unitMeasure": "1L","perUnitPrice": null,"perUnitQuantity": null,"perUnitQuantityUnit": null,"sellingSize": "2 L","currency": "AUD","category": "Milk","categoryPath": "Dairy, Eggs & Fridge > Milk","department": "Dairy, Eggs & Fridge","categories": [{ "id": "960000000", "name": "Dairy, Eggs & Fridge", "path": "dairy-eggs-fridge" }, { "id": "1111111160", "name": "Milk", "path": "dairy-eggs-fridge/milk" }],"isSpecialBuy": false,"notForSale": false,"images": ["https://cdn.aldi.com.au/products/full-cream-milk-2l.jpg"],"imagesCount": 1,"imageUrl": "https://cdn.aldi.com.au/products/full-cream-milk-2l.jpg","categoryUrl": "https://www.aldi.com.au/products/dairy-eggs-fridge/milk/k/1111111160","themes": [],"description": "Full product description appears here when Fetch product details is on.","ingredients": "Full-cream milk.","allergens": [],"allergenStatements": ["Contains: Milk"],"storageInstructions": "Keep refrigerated.","countryOrigin": "Australia","detailFetched": true,"position": 3,"input": "milk","inputType": "searchTerm","scrapedAt": "2026-10-06T01:02:03Z"}
Extra outputs in the key-value store
These never go into the dataset and are never charged:
| Record | When | What it holds |
|---|---|---|
OUTPUT | every run | Run summary, plus one entry per search term, category, Special Buys date or URL with ALDI's reported total, how many new rows it gave, and availableFilters: the brands, themes and categories ALDI offers for that search (each with its product count) and its sort orders. Use those values directly in the Brands, Themes and Sort by inputs. |
SPECIAL_BUYS_CALENDAR | runs that touch Special Buys (the landing-page URL, or the all / upcoming dates) | Every on-sale date ALDI currently lists, with its title (e.g. "Available from Wed 7th October"), its themes and its link. |
CATEGORY_TREE | includeCategoryTree on | ALDI's full category tree (key, name, path, URL, parent, depth). |
Plan Requirement
ALDI's product and detail data is served by the storefront's own JSON backend, so the prefilled connection (Apify Proxy, automatic) is enough for most searches, categories and URL runs on a paid plan. A residential connection is available under Proxy & connection if you want one for large or very frequent runs. Apify free plans include no Apify proxy access, so a free run says so in a boxed warning at the start and continues on a backup connection; if that connection cannot load the requested pages either, the run fails with a message saying so instead of returning an empty result. For residential access, upgrade your Apify plan or supply your own proxy URLs. The Pricing tab on the Store page shows the current per-event rates for this Pay-Per-Event actor.
FAQ
How much does it cost?
This is a Pay-Per-Event actor: you pay for each product returned in the dataset, plus a detail-enrichment charge only for products returned while Fetch product details is on (a pasted product URL always fetches full detail, but is only charged for it under the same condition). A start event is charged once per run based on the memory used. The Pricing tab shows the current per-event rates. Use Max products to cap the cost of any run.
Is it legal to scrape ALDI Australia?
This actor collects only publicly available product and pricing data from aldi.com.au. You are responsible for how you use it: follow ALDI's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution.
Can I get only new, changed or expired products on a schedule?
Yes. Schedule the actor from the Schedules tab with Incremental mode on. Each run then returns only NEW and UPDATED products by default; UNCHANGED ones are suppressed and not billed. Turn on Emit expired products to also get a one-time EXPIRED row for anything that disappeared, but only once a run completes a full, uncapped scan of every search term, category and URL you gave it; a capped, partial or resumed run skips EXPIRED detection for that run and logs why.
Why did Lower Prices or Super Savers return fewer new products than ALDI's own count?
Those promotional ranges cross-list products that already belong to a real grocery aisle. If your run also scrapes that aisle, the actor's within-run dedupe keeps only the first copy of each product, so the promo range itself contributes few additional rows even though ALDI reports a large total for it. This is expected, not under-scraping: filter on onSale / wasPrice on the record itself to see what's currently discounted.
Why did my run fail instead of returning an empty dataset?
If no ALDI results page could be loaded at all, the run fails with a clear status message instead of silently returning nothing, so "blocked" is never confused with "no matching products". There are three: the proxy connection was refused for your account (your plan has no proxy access, or your own proxy URLs have wrong credentials); a free-plan run whose backup connection could not load the pages either; or any other connection problem, which usually clears if you run it again in a few minutes. By contrast, a search with no matching results completes normally with an empty dataset and a status message, and a URL list where every link is unrecognizable completes normally with an empty dataset and an explanatory log message, since neither is a connectivity problem.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push a summary of each product into Notion, Linear or Airtable.
🔗 Want more grocery data?
Pair this actor with these related scrapers from the same team:
| 🥦 Coles AU Scraper Scrape Coles.com.au grocery products and customer reviews. Search by keyword, browse... | 🥦 Woolworths AU Scraper Scrape Woolworths Australia (woolworths.com.au) grocery products and reviews. Search by... |
| 🥦 Carrefour Spain Scraper Scrape Carrefour Spain (carrefour.es) products. Search by keyword, browse a category, or... | 🥦 Instacart Scraper Scrape Instacart grocery catalogs with per-store prices. Run keywords across several... |
| 🥦 Flashfood Scraper Scrape Flashfood discounted groceries and stores by location or store. Extract current... | 🍷 Dan Murphy’s Scraper Scrape Dan Murphy’s products by category, keyword, or specials. Extract 45+ fields... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.