# ALDI US API scraper — aldi.us product search, categories, product detail, Weekly Ad, ALDI Finds and store locator with each store's in-store, pickup or delivery price. No account, no browser.

> Search aldi.us at one ALDI store: price (in-store, pickup or delivery), was-price, unit price, stock level, brand, size and badges, in the site's own result order.
> ReefAPI engine `aldi-us` · 7 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/aldi-us/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Send the key as `Authorization: Bearer <key>`, or put it in the URL (`?key=<key>`) when the client has no header field, as ChatGPT does.

## Endpoints

### POST https://api.reefapi.com/aldi-us/v1/search — 3 credits
Search aldi.us at one ALDI store: price (in-store, pickup or delivery), was-price, unit price, stock level, brand, size and badges, in the site's own result order.

**Parameters:**
- `query` (string, required) — What to look for, as typed in aldi.us search ('milk', 'specially selected').
- `page` (integer, optional, default 1) — 1-based page. The site's order can shift between calls, so reading page by page can repeat or skip a product; for a complete scan follow `next_cursor` instead. A page past the end is INVALID_PARAM; read `last_page`/`has_more`.
- `per_page` (integer, optional, default 20) — Products per page (1-40, default 20).
- `include_unmatched` (boolean, optional, default false) — aldi.us pads a no-match search with unrelated products and does not flag them. Every row carries `matches_query`; false (default) drops a page on which no row shares a word with the query (counted in `unmatched_dropped`), true keeps it.
- `cursor` (string, optional) — `next_cursor` from the previous answer, sent WITH the same query/slug/type, store parameters and per_page (and no `page`). Returns the next page without products already returned: rows the site moved are dropped and counted in `duplicates_dropped`, the page is filled from the rest of the current list (`skipped_recovered` = products offset paging would have skipped).
- `postal_code` (string, optional) — US ZIP code whose ALDI store prices the results (ALDI prices and range differ by store). Default 60174 (St. Charles, IL) — then `store_defaulted` is true.
- `store_id` (string, optional) — Optional ALDI store id from `stores` (wins over postal_code for the store choice).
- `service_type` (enum, optional, default "delivery") — Which of the store's ALDI price lists: delivery (default; the price aldi.us prints on its product pages), in_store (aldi.us's In-store shopping list prices; lower than delivery on 31 of 42 products measured) or pickup. [one of: delivery, in_store, pickup]

**Returns:** products[]{product_id (= id), item_id, name (= title), brand, size, url, image, currency, price, price_display, original_price (= was_price), discount_percent, savings, unit_price_text, price_is_estimate, estimated_weight_text, promotions[], deal_terms, available, stock_level, stock_label, likely_out_of_stock, sold_by, dietary[], store_brand, badge, service_type, matches_query (search), retailer{shop_id,service_type,retailer_location_id}}, count, total, page, per_page, last_page, has_more, unmatched_dropped, query, store{store_id,name,street,city_state_zip,latitude,longitude}, service_type, postal_code, store_defaulted, currency

**Example request body:**
```json
{
  "query": "milk",
  "postal_code": "60174"
}
```

### POST https://api.reefapi.com/aldi-us/v1/category — 3 credits
Every product of an aldi.us collection — a category (Milk, All Dairy & Eggs), an ALDI brand (Specially Selected) or a diet (Organic, Gluten Free) — priced at one store.

**Parameters:**
- `slug` (string, required) — Collection slug from `categories` (n-milk-33852, rc-dairy-eggs-all, rc-organic, rc-specially-selected …) or an aldi.us /store/aldi/collections/<slug> URL.
- `page` (integer, optional, default 1) — 1-based page. The site's order can shift between calls, so reading page by page can repeat or skip a product; for a complete scan follow `next_cursor` instead. A page past the end is INVALID_PARAM; read `last_page`/`has_more`.
- `per_page` (integer, optional, default 20) — Products per page (1-40, default 20).
- `cursor` (string, optional) — `next_cursor` from the previous answer, sent WITH the same query/slug/type, store parameters and per_page (and no `page`). Returns the next page without products already returned: rows the site moved are dropped and counted in `duplicates_dropped`, the page is filled from the rest of the current list (`skipped_recovered` = products offset paging would have skipped).
- `postal_code` (string, optional) — US ZIP code whose ALDI store prices the results (ALDI prices and range differ by store). Default 60174 (St. Charles, IL) — then `store_defaulted` is true.
- `store_id` (string, optional) — Optional ALDI store id from `stores` (wins over postal_code for the store choice).
- `service_type` (enum, optional, default "delivery") — Which of the store's ALDI price lists: delivery (default; the price aldi.us prints on its product pages), in_store (aldi.us's In-store shopping list prices; lower than delivery on 31 of 42 products measured) or pickup. [one of: delivery, in_store, pickup]

**Returns:** collection{id,name,slug,url}, products[]{product_id (= id), item_id, name (= title), brand, size, url, image, currency, price, price_display, original_price (= was_price), discount_percent, savings, unit_price_text, price_is_estimate, estimated_weight_text, promotions[], deal_terms, available, stock_level, stock_label, likely_out_of_stock, sold_by, dietary[], store_brand, badge, service_type, matches_query (search), retailer{shop_id,service_type,retailer_location_id}}, count, total, page, per_page, last_page, has_more, store{store_id,name,street,city_state_zip,latitude,longitude}, service_type, postal_code, store_defaulted, currency

**Example request body:**
```json
{
  "slug": "n-milk-33852",
  "postal_code": "60174"
}
```

### POST https://api.reefapi.com/aldi-us/v1/offers — 3 credits
ALDI's current offer lists at one store: the Weekly Ad, this week's or next week's ALDI Finds, or Price Drops.

**Parameters:**
- `type` (enum, optional, default "weekly_ad") — Which ALDI offer list: weekly_ad, aldi_finds (this week's), upcoming_aldi_finds (next Wednesday's) or price_drops. [one of: weekly_ad, aldi_finds, upcoming_aldi_finds, price_drops]
- `date` (string, optional) — Optional, aldi_finds only: the Wednesday an ALDI Finds list starts (YYYY-MM-DD).
- `page` (integer, optional, default 1) — 1-based page. The site's order can shift between calls, so reading page by page can repeat or skip a product; for a complete scan follow `next_cursor` instead. A page past the end is INVALID_PARAM; read `last_page`/`has_more`.
- `per_page` (integer, optional, default 20) — Products per page (1-40, default 20).
- `cursor` (string, optional) — `next_cursor` from the previous answer, sent WITH the same query/slug/type, store parameters and per_page (and no `page`). Returns the next page without products already returned: rows the site moved are dropped and counted in `duplicates_dropped`, the page is filled from the rest of the current list (`skipped_recovered` = products offset paging would have skipped).
- `postal_code` (string, optional) — US ZIP code whose ALDI store prices the results (ALDI prices and range differ by store). Default 60174 (St. Charles, IL) — then `store_defaulted` is true.
- `store_id` (string, optional) — Optional ALDI store id from `stores` (wins over postal_code for the store choice).
- `service_type` (enum, optional, default "delivery") — Which of the store's ALDI price lists: delivery (default; the price aldi.us prints on its product pages), in_store (aldi.us's In-store shopping list prices; lower than delivery on 31 of 42 products measured) or pickup. [one of: delivery, in_store, pickup]

**Returns:** type, collection{id,name ('Weekly Ad Oct 14 - Oct 20', 'All 10/14 ALDI Finds'),slug,url}, finds_date, products[]{product_id (= id), item_id, name (= title), brand, size, url, image, currency, price, price_display, original_price (= was_price), discount_percent, savings, unit_price_text, price_is_estimate, estimated_weight_text, promotions[], deal_terms, available, stock_level, stock_label, likely_out_of_stock, sold_by, dietary[], store_brand, badge, service_type, matches_query (search), retailer{shop_id,service_type,retailer_location_id}}, count, total, page, has_more, store{store_id,name,street,city_state_zip,latitude,longitude}, service_type, postal_code, store_defaulted, currency

**Example request body:**
```json
{
  "type": "weekly_ad",
  "postal_code": "60174"
}
```

### POST https://api.reefapi.com/aldi-us/v1/promotions — 3 credits
Which ALDI offer lists are live now: Weekly Ad (with its dates), this week's and next week's ALDI Finds and Price Drops, each with its product count.

**Parameters:**
- `postal_code` (string, optional) — US ZIP code whose ALDI store prices the results (ALDI prices and range differ by store). Default 60174 (St. Charles, IL) — then `store_defaulted` is true.
- `store_id` (string, optional) — Optional ALDI store id from `stores` (wins over postal_code for the store choice).
- `service_type` (enum, optional, default "delivery") — Which of the store's ALDI price lists: delivery (default; the price aldi.us prints on its product pages), in_store (aldi.us's In-store shopping list prices; lower than delivery on 31 of 42 products measured) or pickup. [one of: delivery, in_store, pickup]

**Returns:** promotions[]{type,name,slug,url,finds_date,product_count,available}, store{store_id,name,street,city_state_zip,latitude,longitude}, service_type, postal_code, store_defaulted, currency

**Example request body:**
```json
{
  "postal_code": "60174"
}
```

### POST https://api.reefapi.com/aldi-us/v1/product/detail — 3 credits
One ALDI product: name, brand, size, category, ingredients, directions, warnings, images, rating — and its price, unit price and stock at one store.

**Parameters:**
- `product_id` (string, required) — Product id (every row's `product_id`) or an aldi.us /store/aldi/products/ URL.
- `postal_code` (string, optional) — US ZIP code whose ALDI store prices the results (ALDI prices and range differ by store). Default 60174 (St. Charles, IL) — then `store_defaulted` is true.
- `store_id` (string, optional) — Optional ALDI store id from `stores` (wins over postal_code for the store choice).
- `service_type` (enum, optional, default "delivery") — Which of the store's ALDI price lists: delivery (default; the price aldi.us prints on its product pages), in_store (aldi.us's In-store shopping list prices; lower than delivery on 31 of 42 products measured) or pickup. [one of: delivery, in_store, pickup]

**Returns:** product{product_id,name,brand,size,category{id,name},url,description,details,ingredients,directions,nutrition_text,warnings,other_sections[],images[],breadcrumb[],rating,rating_count,currency}, price, retailer_item (the store's row: price, was-price, unit price, stock, nutrition) or null + retailer_item_note when this store does not list it, store{store_id,name,street,city_state_zip,latitude,longitude}, service_type, postal_code, store_defaulted, currency

**Example request body:**
```json
{
  "product_id": "16902710",
  "postal_code": "60174"
}
```

### POST https://api.reefapi.com/aldi-us/v1/categories — 3 credits
aldi.us departments (Fresh Produce, Dairy & Eggs …), a department's collections, a collection's sub-collections, and the ALDI brand and diet collections.

**Parameters:**
- `department` (string, optional) — Optional department slug from the `departments` list (dairy-and-eggs, fresh-produce …): returns that department's collections. Without it: departments + ALDI brand and diet collections.
- `slug` (string, optional) — Optional parent collection slug: returns its sub-collections.
- `postal_code` (string, optional) — US ZIP code whose ALDI store prices the results (ALDI prices and range differ by store). Default 60174 (St. Charles, IL) — then `store_defaulted` is true.
- `store_id` (string, optional) — Optional ALDI store id from `stores` (wins over postal_code for the store choice).
- `service_type` (enum, optional, default "delivery") — Which of the store's ALDI price lists: delivery (default; the price aldi.us prints on its product pages), in_store (aldi.us's In-store shopping list prices; lower than delivery on 31 of 42 products measured) or pickup. [one of: delivery, in_store, pickup]

**Returns:** departments[]{slug,name,url}, collections[]{slug,name,url,children[]} — slugs feed `category`

**Example request body:**
```json
{
  "department": "dairy-and-eggs"
}
```

### POST https://api.reefapi.com/aldi-us/v1/stores — 2 credits
ALDI stores around a US ZIP code, nearest first, with address, coordinates, distance and which services (in-store, pickup, delivery) aldi.us offers there.

**Parameters:**
- `postal_code` (string, required) — US ZIP code to find ALDI stores around (nearest first).
- `page` (integer, optional, default 1) — 1-based page. The site's order can shift between calls, so reading page by page can repeat or skip a product; for a complete scan follow `next_cursor` instead. A page past the end is INVALID_PARAM; read `last_page`/`has_more`.
- `limit` (integer, optional, default 20) — Stores per page (1-100, default 20).

**Returns:** stores[]{store_id,name,street,city_state_zip,postal_code,latitude,longitude,distance_miles,service_types[],services_text,unavailable_text}, count, total, page, has_more

**Example request body:**
```json
{
  "postal_code": "10001"
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=aldi-us
- Human docs page: https://reefapi.com/docs/aldi-us
- Overview page: https://reefapi.com/aldi-us-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
