# Auchan.fr Scraper - Grocery, Prices, Promos & Reviews (`abotapi/auchan-fr-scraper`) Actor

Scrape Auchan.fr products: grocery, drinks, household and general merchandise. Real price scoped to your drive/delivery point, genuine was-price and discount % when on offer, unit price, brand, shopper ratings and reviews. Search by keyword or paste product/search/category links.

- **URL**: https://apify.com/abotapi/auchan-fr-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product 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/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

## Auchan France Scraper

Pull product data from Auchan.fr -- the French hypermarket/grocery chain's full storefront: food, drinks, household goods and general merchandise. Search by keyword with brand and "on offer" filters, or paste product/search/category links directly. Every record includes the current price scoped to your chosen drive/click\&collect/delivery point, a genuine strike-through was-price and discount % whenever a product is genuinely on offer, unit price, stock/availability, images, and Auchan's own native shopper rating and review feed.

### Why This Scraper?

- **Real, store-scoped prices.** Auchan.fr only shows prices once a drive/click\&collect point or delivery address is chosen, exactly like the site's own "Choisir vos courses" flow -- this scraper reproduces that with a postal code you provide, so prices and stock match what a real shopper at that address would see.
- **Was-price captured only when it's real.** Auchan runs genuine promotions with a real prior price -- this scraper reads the site's own strike-through price element per item and only ever sets a was-price/discount when it's genuinely present and higher than the current price. Full-price items get `null`, never a fabricated markdown.
- **Loyalty cashback kept separate from a real discount.** Auchan's "Avantages Waaoh" badge is a loyalty rewards-points percentage, not a price cut -- it is surfaced under its own `loyaltyCashbackPercent` field so it can never be mistaken for a genuine promotion.
- **Real shopper reviews, not a third-party vendor.** Ratings and reviews come from Auchan's own on-site review widget (overall rating, star-by-star breakdown, per-review author/date/rating/title/body), included on request.
- **Unit pricing included.** The site's own €/kg or €/L unit price is read directly, never guessed from a pack size.
- **Two ways in.** Keyword search with brand/offer filters and sort, or paste any product, search, or category link.
- **Optional export to your apps.** Send results into Notion, Linear, Airtable, or any Apify MCP connector alongside the dataset.
- **Resume and recurring updates.** Turn on Incremental mode to get only NEW, UPDATED, and REAPPEARED products on every scheduled run, or resume one specific interrupted crawl with `resumeFromRunId`.

### A note on store scope and product detail

Auchan.fr's whole catalogue is scoped to a chosen store/delivery point -- this scraper resolves one from the postal code/city you provide (`postalCode`) the same way the site's own picker does, before any search or product fetch. If a postal code can't be resolved to a real address, identity fields (title, brand, images, rating) still populate but price/stock may come back empty rather than fabricated. The product card already carries price, was-price, unit price, rating and one image; the genuinely additive per-product fetch is the detail page's full category breadcrumb, EAN, complete image gallery and native review feed -- turned on with `fetchDetails` (always on for a pasted product URL).

### Data You Get

| Field | Example value |
|---|---|
| productId / title | `1e83a750-95a1-463d-a817-89b67188b8d1`, `AUCHAN Lait demi-écrémé UHT` |
| brand / category / categoryPath | `AUCHAN`, `Laits, boissons végétales, oeufs`, `["Produits laitiers, oeufs, fromages", "Laits, boissons végétales, oeufs", "Lait demi-écrémé"]` |
| productUrl / images | `https://www.auchan.fr/auchan-lait-demi-ecreme-uht/pr-C1177774`, full-resolution image list |
| price / currency | `6.42`, `EUR` |
| wasPrice / discountAmount / discountPercent | `12.15`, `3.65`, `30.0` (only when genuinely on offer) |
| isOnSpecial / loyaltyCashbackPercent | `true`, `10.0` (Waaoh loyalty cashback, kept separate from a real discount) |
| packSize / unitPrice / unitOfMeasure | `"6x1L"`, `1.07`, `"€/L"` |
| availability / deliveryPromise / stock | `"InStock"`, `"Dans mon drive"`, `78` |
| averageRating / reviewCount | `4.6`, `256` |
| ean | `3428274060013` |
| reviews | `null` by default, full feed with `fetchDetails: true` |

> Sample shape: values above are illustrative placeholders, not from a live product.

### How to Use

**1. Keyword search (default):**

```json
{
  "mode": "search",
  "postalCode": "75001",
  "searchTerm": "lait",
  "maxItems": 20
}
```

**2. Offers only, biggest discount first, home delivery instead of drive:**

```json
{
  "mode": "search",
  "postalCode": "69001",
  "deliveryMode": "shipping",
  "specialsOnly": true,
  "sortBy": "BIGGEST_DISCOUNT",
  "maxItems": 50
}
```

**3. One brand, with full detail and reviews:**

```json
{
  "mode": "search",
  "postalCode": "75001",
  "searchTerm": "lait",
  "brand": "LACTEL",
  "fetchDetails": true,
  "maxItems": 20
}
```

**4. Paste product / search / category links directly:**

```json
{
  "mode": "url",
  "postalCode": "75001",
  "urls": [
    "https://www.auchan.fr/lactel-lait-demi-ecreme-bio-uht/pr-C1177205",
    "https://www.auchan.fr/oeufs-produits-laitiers/cremerie-oeufs-laits/ca-n0101"
  ],
  "maxItems": 50
}
```

### Input Parameters

| Parameter | Type | Description |
|---|---|---|
| `mode` | string | `search` or `url`. |
| `postalCode` | string | French postal code or city used to resolve a drive/click\&collect/delivery point, exactly like the site's own picker. Applies to every mode. |
| `deliveryMode` | string | `drive` (drive/click\&collect, default) or `shipping` (home delivery). |
| `searchTerm` | string | Keyword against Auchan's own search index (search mode only). |
| `brand` | string | Exact brand name to keep, as shown on the site (search mode only); best-effort match against the site's own brand facet. |
| `specialsOnly` | boolean | Keep only products on a genuine current promotion (search mode only). |
| `sortBy` | string | `RELEVANCE`, `PRICE_ASC`, `PRICE_DESC`, `UNIT_PRICE_ASC`, `UNIT_PRICE_DESC`, `BIGGEST_DISCOUNT`, `BESTSELLERS`, `TOP_RATED`, `BRAND_ASC`, or `BRAND_DESC` (search mode only). |
| `urls` | array | Product, search, or category listing URLs to scrape (url mode only). |
| `fetchDetails` | boolean | Fetch the full breadcrumb/EAN/image gallery and native review feed. Always on for a pasted product URL. |
| `maxPages` | integer | Cap on search result pages fetched; empty = unlimited. |
| `maxItems` | integer | Cap on total products returned; `0` = unlimited. |
| `resumeFromRunId` | string | Continue one specific previous run/dataset: products already collected there are skipped, so this run only appends new products. For recurring daily monitoring of the same search, use Incremental mode instead -- see "Resume and recurring updates" below. |
| `incrementalMode` | boolean | Daily/recurring monitoring of this same search. First run returns everything as `NEW`; later runs return only `NEW`/`UPDATED`/`REAPPEARED` by default. See "Resume and recurring updates" below. |
| `stateKey` | string | Optional name for a monitoring campaign, so its incremental state stays stable or is deliberately shared. Auto-derived from postal code, delivery mode, search/URL and filter settings when left empty. |
| `emitUnchanged` | boolean | Incremental mode only. Also return products unchanged since the last run, marked `UNCHANGED`. Adds and bills extra rows you already have. |
| `emitExpired` | boolean | Incremental mode only. Also return products from a previous run no longer found, marked `EXPIRED`, once a run has fully scanned the search (not capped, not a resume). Adds and bills extra synthetic rows. |
| `proxy` | object | Apify Proxy configuration used to route requests. The default works out of the box. |
| `mcpConnectors` | array | Optional MCP connectors to export results into (Notion, Linear, Airtable, Apify). |
| `notionParentPageUrl` | string | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | Cap on items exported to each connector per run. Does not affect the dataset. |

### Output Example

```json
{
  "productId": "1e83a750-95a1-463d-a817-89b67188b8d1",
  "title": "AUCHAN Lait demi-écrémé UHT",
  "brand": "AUCHAN",
  "packSize": "6x1L",
  "productUrl": "https://www.auchan.fr/auchan-lait-demi-ecreme-uht/pr-C1177774",
  "price": 6.42,
  "currency": "EUR",
  "unitPrice": 1.07,
  "unitOfMeasure": "€/L",
  "wasPrice": null,
  "discountAmount": null,
  "discountPercent": null,
  "isOnSpecial": false,
  "loyaltyCashbackPercent": 10.0,
  "availability": "InStock",
  "deliveryPromise": "Dans mon drive",
  "deliveryChannel": "PICK_UP",
  "stock": 78,
  "averageRating": 4.6,
  "reviewCount": 256,
  "images": ["https://cdn.auchan.fr/media/sample/PRIMARY_0x0/B2CD/"],
  "categoryPath": ["Produits laitiers, oeufs, fromages", "Laits, boissons végétales, oeufs"],
  "category": "Laits, boissons végétales, oeufs",
  "ean": "3428274060013",
  "reviews": {
    "averageRating": 4.4,
    "reviewCount": 39,
    "ratingBreakdown": { "5": 25, "4": 10, "3": 1, "2": 0, "1": 3 },
    "items": [
      { "reviewId": "1216547230", "author": "Sample Shopper", "date": "03/04/26", "rating": 5.0, "title": "Excellent rapport qualité prix", "body": "Sample review text.", "verifiedPurchase": true }
    ]
  }
}
```

> Sample shape: values above are illustrative placeholders, not from a live product.

**Incremental mode only.** When `incrementalMode` is on, every returned record also carries:

| Field | Description |
|---|---|
| `changeType` | `NEW` | `UPDATED` | `UNCHANGED` | `REAPPEARED` | `EXPIRED` |
| `changedFields` | Top-level fields that changed since last seen; non-empty only for `UPDATED` |
| `firstSeenAt` | When this product was first observed by this monitoring campaign |
| `lastSeenAt` | When this product was last observed |

### Resume and recurring updates

There are two different things here -- pick the one that matches what you're doing:

| Need | Use |
| --- | --- |
| A crawl stopped and should continue | `resumeFromRunId` |
| Run the same search every day and receive only changes | `incrementalMode` |
| Keep separate daily campaigns for similar searches | distinct `stateKey` values |
| Run a normal full snapshot | leave both off |

**Resume** (`resumeFromRunId`) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips products already collected there, returning only the remaining new products.

**Incremental mode** (`incrementalMode`) is for a schedule (for example, daily): the actor remembers the previous run of the *same* search by itself, so you never paste a run ID. The first run returns everything as `NEW`. Later runs return only `NEW`, `UPDATED`, and `REAPPEARED` products by default -- duplicates and unchanged products are suppressed (and not charged). Turn on `emitUnchanged` or `emitExpired` only when you also want those rows returned (and billed for). State is isolated per postal code, delivery mode, search/URL and detail-mode setup automatically -- Auchan scopes the price itself to the postal code/delivery point, so two different drive points are always tracked separately; set `stateKey` to name or deliberately share a monitoring campaign.

Scheduled-run example -- same search, run daily:

Day 1 (first run ever for this search):

```json
{ "mode": "search", "postalCode": "75001", "searchTerm": "lait", "incrementalMode": true }
```

→ every product comes back with `"changeType": "NEW"`.

Day 2 (the schedule fires again, identical input):

```json
{ "mode": "search", "postalCode": "75001", "searchTerm": "lait", "incrementalMode": true }
```

→ products whose price/promotion/stock/etc. changed come back as `"changeType": "UPDATED"` with `changedFields` listing what changed, brand-new products come back as `"changeType": "NEW"`, products that vanished and came back come back as `"changeType": "REAPPEARED"` -- and products that are still there, unchanged, are **not** returned at all (suppressed, not charged) unless `emitUnchanged` is on.

### A note on was-price and loyalty cashback

`wasPrice`/`discountAmount`/`discountPercent`/`isOnSpecial` are only ever set when Auchan's own strike-through price element is genuinely present and higher than the current price -- most full-price items simply carry no was-price, reported honestly rather than invented. This is a completely separate signal from `loyaltyCashbackPercent`, which reflects Auchan's "Avantages Waaoh" loyalty rewards-points percentage on a purchase -- it never affects the price you pay at checkout and is never folded into the discount fields.

One quirk worth knowing: when sorting by price (`PRICE_ASC`/`PRICE_DESC`), Auchan ranks a genuinely discounted item by its reference/list price (`wasPrice`), not the discounted `price` you'll actually pay -- so the returned order can look slightly out of sequence against `price` alone for an on-offer item. This is the site's own ranking behavior, not a scraper defect.

### Send results into your apps (MCP connectors)

Optionally pipe results into the apps you already use through Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it in the `mcpConnectors` field. Each connector receives a condensed, human-readable summary per product (title plus key fields), while the complete record always stays in the Apify dataset. For Notion, set `notionParentPageUrl` to the page the item pages should be created under, and use `maxNotifyListings` to cap how many items are exported per connector per run. Supported connectors: Notion, Linear, Airtable, and Apify. Leave the field empty to skip; it never changes the dataset output.

# Actor input Schema

## `mode` (type: `string`):

'search' browses Auchan.fr by keyword with brand/offer filters and sort. 'url' scrapes any product, search, or category link you paste.

## `postalCode` (type: `string`):

Auchan.fr scopes prices, promotions and stock to a drive/click\&collect/delivery point resolved from this postal code or city, exactly like the site's own 'Choisir vos courses' picker. Applies to every mode.

## `deliveryMode` (type: `string`):

Scopes the store context to a drive/click\&collect point (nearest, usually cheapest to resolve) or a home-delivery point for the postal code above.

## `searchTerm` (type: `string`):

Free-text keyword against Auchan.fr's own search index, e.g. 'lait' or 'lessive'. Leave empty to browse the store-wide catalogue (narrow with Brand / On offer only below).

## `brand` (type: `string`):

Only return products from this brand, as shown on the site (e.g. 'AUCHAN', 'LACTEL'). Leave empty for all brands. Best-effort match against the site's own brand facet.

## `specialsOnly` (type: `boolean`):

Narrows to the site's own 'Promo' merchandising set, then keeps only the records that genuinely carry a real strike-through was-price and discount % -- never a fabricated one.

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

Sort order for the results, using Auchan.fr's own real sort options.

## `urls` (type: `array`):

Paste one or more Auchan.fr product pages (auchan.fr/<slug>/pr-C<id>), search pages (auchan.fr/recherche?text=<term>), or category listing pages (auchan.fr/<slug-path>/ca-n<code>). Filter fields above are ignored in this mode.

## `fetchDetails` (type: `boolean`):

Adds the full category breadcrumb, EAN, complete image gallery and Auchan's own native shopper review feed (overall rating, rating breakdown, per-review author/date/rating/title/body) for each product. Current price, was-price/discount, unit price and the card image are already included without this toggle. Always on for a pasted product URL.

## `maxPages` (type: `integer`):

Stop after fetching this many result pages. Leave empty for no limit -- the run stops at Max products total.

## `maxItems` (type: `integer`):

Hard cap on total products returned across the run. 0 = unlimited (still bounded by Max search pages).

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large crawl of products without returning or charging for products already collected there. Use this after an interrupted run, or when continuing a product pull in another run. For recurring daily monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching products as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED products. Turn on "Emit unchanged" or "Emit expired" only when you also want those products returned (and billed). State is kept separately for each postal code/delivery mode/search/URL and filter setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the postal code, delivery mode, search/URL and filter settings -- different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED. This returns -- and bills -- extra rows you already have, so leave it off unless you specifically want the full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return products that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search -- not when Max products capped it or when Resume was used. This returns -- and bills -- extra synthetic rows, so leave it off unless you need expiry tracking.

## `proxy` (type: `object`):

Apify Proxy configuration used to route requests. The default works out of the box.

## `mcpConnectors` (type: `array`):

Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify -> Settings -> Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "postalCode": "75001",
  "deliveryMode": "drive",
  "searchTerm": "lait",
  "specialsOnly": false,
  "sortBy": "RELEVANCE",
  "urls": [
    "https://www.auchan.fr/lactel-lait-demi-ecreme-bio-uht/pr-C1177205"
  ],
  "fetchDetails": false,
  "maxItems": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "mode": "search",
    "postalCode": "75001",
    "searchTerm": "lait",
    "urls": [
        "https://www.auchan.fr/lactel-lait-demi-ecreme-bio-uht/pr-C1177205"
    ],
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/auchan-fr-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 = {
    "mode": "search",
    "postalCode": "75001",
    "searchTerm": "lait",
    "urls": ["https://www.auchan.fr/lactel-lait-demi-ecreme-bio-uht/pr-C1177205"],
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/auchan-fr-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 '{
  "mode": "search",
  "postalCode": "75001",
  "searchTerm": "lait",
  "urls": [
    "https://www.auchan.fr/lactel-lait-demi-ecreme-bio-uht/pr-C1177205"
  ],
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/auchan-fr-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/g1TlbIxoTUtMCcoSW/builds/xPCKozKbluWdgyfgx/openapi.json
