# Marionnaud Scraper - French Perfume and Beauty Prices, EAN (`studio-amba/marionnaud-scraper`) Actor

Scrape product data from marionnaud.fr, the French perfumery and beauty chain. Get EAN barcodes, current and list prices, promotions, stock status, ratings and review counts for every size of perfume, skincare, makeup and haircare products.

- **URL**: https://apify.com/studio-amba/marionnaud-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/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

## Marionnaud Scraper

Pull product data from marionnaud.fr, the French perfumery and beauty chain. The actor returns one row per size with the EAN barcode, current price, list price, discount, promotion, stock status, rating and review count.

Marionnaud sells perfume, skincare, makeup, haircare and body care from several hundred brands. Every row carries the EAN, so you can match a Marionnaud listing to the same product at Sephora, Douglas, Notino or any other shop.

### How to scrape Marionnaud data

There are three ways to tell the actor which products to read.

1. Fill `searchQueries` with brands or product words, for example `givenchy`, `clarins` or `creme visage`. The actor reads the shop's product search page by page, 100 products per request, and stops at `maxResults`.
2. Leave everything empty to read the whole catalogue, about 6,800 rows. Set `maxResults` to the number of rows you want.
3. Paste product pages or product codes into `productUrls`, for example `https://www.marionnaud.fr/soin-visage/hydratant-et-nourrissant/soin-de-jour/skin-perfecto-creme-hydratante-compacte-givenchy/p/BP_102559454` or `102559454`. When product URLs are given, the search keywords are ignored.

Rows from a search carry `searchQuery` and `searchRank`, the position of the product in the shop's own result list for that keyword. Run the same keyword every day to follow the ranking.

The actor reads the shop's public product data. The search pages on www.marionnaud.fr, which the site's robots.txt does not allow, are not requested.

### Input

| Field | Type | Description |
|---|---|---|
| `searchQueries` | list of words | Brands or product words. Empty means the whole catalogue |
| `productUrls` | list of URLs or codes | Marionnaud product pages. Overrides the search keywords |
| `maxResults` | number | Maximum number of rows (default 50) |
| `brightDataApiKey` | secret text | Optional. Falls back to the actor's own key when empty |
| `brightDataZone` | text | Optional. Name of the Bright Data Web Unlocker zone, default `web_unlocker1` |

A product with three sizes gives three rows, because each size has its own EAN and price.

### What you get back

| Field | Description |
|---|---|
| `sku` | Code of this size |
| `productId` | Base product code (BP\_...), shared by all sizes of one product |
| `ean` | EAN/GTIN-13 barcode of this size |
| `name` | Product name |
| `brand` | Brand name |
| `range` | Product range or line |
| `variant` | Size or shade, for example `50ML` |
| `price` | Current selling price in EUR |
| `originalPrice` | List price, only when the shop shows a discount |
| `discountPercent` | Percent below the list price |
| `promotion` | Promotion label such as `-35%` |
| `currency` | ISO currency code (EUR) |
| `inStock` | False when the shop reports out of stock |
| `stockStatus` | `inStock`, `lowStock` or `outOfStock` |
| `stockLevel` | Units the shop reports available |
| `rating` | Average review score out of 5 |
| `reviewCount` | Number of reviews on the product |
| `category` | Category path |
| `supplier` | Supplier name as shown by the shop |
| `imageUrl` | Main product image. Filled when you use `productUrls`, empty for search rows |
| `url` | Product page address |
| `searchQuery`, `searchRank` | Keyword and position in the shop's result list |
| `scrapedAt` | Time of the read |
| `country`, `language` | `fr`, `fr` |

Products without reviews have empty rating fields.

### Example output

```json
{
  "sku": "102568836",
  "productId": "BP_102568836",
  "ean": "3274872451605",
  "name": "Le lait corps",
  "brand": "GIVENCHY",
  "range": "IRRESISTIBLE GIVENCHY",
  "variant": "200ml",
  "price": 73,
  "originalPrice": null,
  "discountPercent": null,
  "promotion": null,
  "currency": "EUR",
  "inStock": true,
  "stockStatus": "lowStock",
  "stockLevel": 2,
  "rating": 5,
  "reviewCount": 3,
  "category": "Parfum > Parfum Femme > Produit complémentaire",
  "supplier": "LVMH FRAGRANCE BRANDS",
  "imageUrl": null,
  "url": "https://www.marionnaud.fr/parfum/parfum-femme/produit-complementaire/irresistible-givenchy-le-lait-corps-givenchy/p/BP_102568836",
  "searchQuery": "givenchy",
  "searchRank": 1,
  "scrapedAt": "2026-10-30T15:10:34.061Z",
  "country": "fr",
  "language": "fr"
}
```

### Use cases

- Compare Marionnaud prices to other shops by EAN.
- Track list price, discount percent and promotions on a brand over time.
- Check which sizes of a brand are in stock and how many units are left.
- Follow the search rank of your brand for a keyword.
- Monitor review counts and ratings for your own brand.

### Cost and speed

A search reads 100 products per request, so a brand with 150 sizes takes about one minute. The whole catalogue is about 70 requests. Product URLs cost one or two requests per size and are slower. Pricing is per result, see the pricing box on this page. The usage cost of a run only settles after the run reports SUCCEEDED, so a cost checked during the run is too low.

The shop is protected by Akamai, so the actor reaches it through Bright Data Web Unlocker. That cost is part of the per-result price.

### Notes and limits

- Prices are in EUR for the French storefront. Other country storefronts are not covered.
- A keyword that matches only a few products returns fewer rows than `maxResults`.
- `originalPrice` and `promotion` come from the shop's own price data. They are empty when the shop shows no discount.
- Some shades and sizes in the shop carry no size label, so `variant` can be empty.
- The actor reads publicly visible data only. It does not log in and does not use cookies.
- You are responsible for how you use the data. Check Marionnaud's terms and the rules that apply to your use case. We are not responsible for restrictions the source website imposes.

### Frequently asked questions

#### Does it return EAN barcodes?

Yes. The `ean` field holds the barcode of each size.

#### Can I search by brand?

Yes, put the brand into `searchQueries`, for example `clarins`. Raise `maxResults` to the number of rows you need.

#### Can I read the whole catalogue?

Yes. Leave `searchQueries` and `productUrls` empty and set `maxResults` to 7000 or more.

#### Why are there more rows than products?

Each size or shade is its own row, because each has its own EAN and price.

#### How often can I run it?

As often as you like. Daily runs with the same keywords give a clean price history.

#### Why is a rating empty?

The product has no reviews yet.

### Related scrapers

- [Sephora Scraper](https://apify.com/studio-amba/sephora-scraper) for Sephora France and Spain
- [Flaconi Scraper](https://apify.com/studio-amba/flaconi-scraper) for Flaconi Germany
- [Lookfantastic Scraper](https://apify.com/studio-amba/lookfantastic-scraper) for Lookfantastic UK
- [Notino Scraper](https://apify.com/studio-amba/notino-scraper) for Notino beauty prices
- [dm Scraper](https://apify.com/studio-amba/dm-scraper) for dm drugstore products

# Actor input Schema

## `searchQueries` (type: `array`):

Brand or product words searched on marionnaud.fr, e.g. givenchy, creme visage or clarins. Each keyword is read page by page, 100 products per request. Leave empty to read the whole catalogue (about 6,800 products).

## `productUrls` (type: `array`):

Product pages from marionnaud.fr, e.g. https://www.marionnaud.fr/soin-visage/hydratant-et-nourrissant/soin-de-jour/skin-perfecto-creme-hydratante-compacte-givenchy/p/BP_102559454, or a code such as 102559454. When given, search keywords are ignored. Each size becomes one row.

## `maxResults` (type: `integer`):

Maximum number of rows (one row per size). The whole catalogue is about 6,800 rows.

## `brightDataApiKey` (type: `string`):

Bright Data API key used to reach marionnaud.fr. Falls back to the actor's own BRIGHT_DATA_API_KEY environment variable if left empty.

## `brightDataZone` (type: `string`):

Name of the Bright Data Web Unlocker zone. Default is web_unlocker1.

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

Not used. This actor reaches Marionnaud through Bright Data Web Unlocker. Kept for input-shape compatibility.

## Actor input object example

```json
{
  "searchQueries": [
    "givenchy"
  ],
  "maxResults": 20,
  "brightDataZone": "web_unlocker1",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchQueries": [
        "givenchy"
    ],
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/marionnaud-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 = {
    "searchQueries": ["givenchy"],
    "maxResults": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/marionnaud-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 '{
  "searchQueries": [
    "givenchy"
  ],
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call studio-amba/marionnaud-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/marionnaud-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/eFvbqu7kCKoa6akRW/builds/O5Wuk3373XN3BNCC4/openapi.json
