# Fnac API scraper — fnac.com (France) plus Belgium, Switzerland and Portugal: search products, read the product (EAN, price with the struck 30-day-lowest price and eco-fee, member price, seller, other offers, specs), list every marketplace offer and read reviews. No account, no browser.

> Search a Fnac storefront by keyword with the site's own sorts and filters (price range, sold by Fnac). Each row: product id, title, URL, brand or contributors, the price with the struck 30-day-lowest price and discount when shown, the member price where the storefront shows one, the store-pickup price on books, condition (new/used + grade), seller (Fnac or marketplace), availability, rating + count, other new/used offers with their from-prices, badges and image.
> ReefAPI engine `fnac` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/fnac/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, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /fnac/v1/search — 3 credits
Search a Fnac storefront by keyword with the site's own sorts and filters (price range, sold by Fnac). Each row: product id, title, URL, brand or contributors, the price with the struck 30-day-lowest price and discount when shown, the member price where the storefront shows one, the store-pickup price on books, condition (new/used + grade), seller (Fnac or marketplace), availability, rating + count, other new/used offers with their from-prices, badges and image.

**Parameters:**
- `query` (string, required) — Keyword to search (in the storefront's language: 'casque bluetooth', 'livro'). When Fnac answers a keyword with a category page instead of a result list, the response says so in `redirected_to` / `redirect_type` and returns that page's products.
- `country` (enum, optional, default "fr") — Fnac storefront. Prices come back in that storefront's currency (CHF for ch). Product ids are shared across storefronts but price, stock and sellers differ. A pasted product URL sets the country itself. [one of: fr, be, ch, pt, es]
- `page` (integer, optional, default 1) — Result page, 1-based. Fnac serves 20 products per page; `total_pages` says how many exist.
- `sort` (enum, optional, default "relevance") — Order of the results — the site's own orderings. [one of: relevance, price_asc, price_desc, rating]
- `price_min` (number, optional) — Lowest price in the storefront currency. Sent to Fnac's own price filter and re-checked on the returned rows (outliers dropped, counted in `dropped_outside_price_range`). Part of fnac.com's traffic only offers fixed price bands; the response's `price_filter_mode` says which applied ('exact' or 'bands' — with bands, `total_results` counts the bands).
- `price_max` (number, optional) — Highest price in the storefront currency (see price_min).
- `sold_by_fnac` (boolean, optional) — Only products sold by Fnac itself (Fnac's 'Vendu par Fnac' filter).
- `include_fallback_results` (boolean, optional, default false) — When no product on the page contains a query word, Fnac pads the page with fuzzy matches. false (default): results are empty and `fallback_results_dropped` counts them. true: they are returned apart, in `fallback_results`.
- `max_rotations` (integer, optional, default 5) — Advanced: how many times to retry a difficult request (1-8, default 5).

**Returns:** results[]{position, product_id, catalog, product_code, offer_id, title, url, brand, product_type, contributors[{name, role}], price, currency, struck_price, struck_price_type, discount_percent, member_price, member_price_label, store_pickup_price, store_pickup_label, condition ('new'|'used'), condition_grade, seller{name, id, type, is_fnac}, fulfilled_by, availability, availability_code, rating, rating_count, rating_scale, other_offers[{condition, count, from_price}], lowest_new_offer_price, lowest_used_offer_price, badges[], image}, count, total_results, total_pages, page, page_size, sort, sort_applied, query, country, currency, applied_filters, dropped_outside_price_range, keyword_matches_on_page, fallback_results_dropped, fallback_total, fallback_results[] (only with include_fallback_results=true), sponsored_dropped, page_notice

**Example request body:**
```json
{
  "query": "casque bluetooth"
}
```

### POST /fnac/v1/product/detail — 2 credits
The Fnac product record by URL or product_id: title, brand or contributors, EAN, SKU, MPN, the buy-box price with the struck 30-day-lowest price and discount, the eco-participation and copie-privée levy it includes, member price where shown, store-pickup price on books, availability (in stock / pre-order), condition, seller (Fnac or marketplace, with rating and sales count), delivery, the other new/used offers summary, star rating + count, energy class, images, video, description, specs and breadcrumb.

**Parameters:**
- `url` (string, optional) — A Fnac product URL (fnac.com, fr.fnac.be, fr.fnac.ch, fnac.pt). Every search row returns one.
- `product_id` (string, optional) — Instead of url: the Fnac product id (digits, as `product_id` in search rows) or the URL code (a17689644, mp50936938).
- `country` (enum, optional, default "fr") — Fnac storefront. Prices come back in that storefront's currency (CHF for ch). Product ids are shared across storefronts but price, stock and sellers differ. A pasted product URL sets the country itself. [one of: fr, be, ch, pt, es]
- `max_rotations` (integer, optional, default 5) — Advanced: how many times to retry a difficult request (1-8, default 5).

**Returns:** product{product_id, catalog, product_code, sku, ean, mpn, title, url, brand, contributors[], price, currency, struck_price, struck_price_type, discount_percent, eco_participation, copy_levy, price_includes_eco_fee, member_price, member_price_label, member_perk, store_pickup_price, store_pickup_label, store_pickup_only, store_availability, badges[], availability (headline offer: in_stock|out_of_stock|pre_order|limited), availability_text (the page's wording when Fnac sells the headline offer, else null), availability_type, fnac_availability, fnac_availability_type, fnac_availability_code (Fnac's own status, kept apart), stock_status, in_stock, is_preorder, condition, condition_grade, seller{name, id, type, is_fnac, location, rating, rating_scale, sales_count}, fulfilled_by, delivery{label, price, estimate}, other_offers[{condition, count, from_price}], lowest_new_offer_price, lowest_used_offer_price, page_offers[], rating, rating_count, rating_scale, energy_class, images[], video_url, description, specs[{name, value}], breadcrumb[{name, url}], category, country}

**Example request body:**
```json
{
  "product_id": "17689644"
}
```

### POST /fnac/v1/product/offers — 1 credit
Every offer for one product (Fnac/Darty and marketplace sellers, new and used), by URL or product_id, with the site's condition filter and sorts: seller name + rating + review count, condition (new/refurbished/used + grade), price, shipping price, total price, delivery estimate and badges.

**Parameters:**
- `url` (string, optional) — A Fnac product URL (fnac.com, fr.fnac.be, fr.fnac.ch, fnac.pt). Every search row returns one.
- `product_id` (string, optional) — Instead of url: the Fnac product id (digits, as `product_id` in search rows) or the URL code (a17689644, mp50936938).
- `country` (enum, optional, default "fr") — Fnac storefront. Prices come back in that storefront's currency (CHF for ch). Product ids are shared across storefronts but price, stock and sellers differ. A pasted product URL sets the country itself. [one of: fr, be, ch, pt, es]
- `condition` (enum, optional, default "all") — Fnac's own offer filter. [one of: all, new, used]
- `sort` (enum, optional, default "relevance") — Order of the offers — the site's own orderings. [one of: relevance, best_selling, price_asc, price_desc, seller_rating, delivery]
- `page` (integer, optional, default 1) — Offer page, 1-based. Fnac serves 10 offers per page.
- `max_rotations` (integer, optional, default 5) — Advanced: how many times to retry a difficult request (1-8, default 5).

**Returns:** offers[]{offer_id, seller{name, is_fnac_group, rating, rating_scale, rating_count}, condition, condition_label, condition_grade, price, currency, shipping_price, total_price, delivery_estimate, badges[]}, count, product_id, catalog, country, currency, filter_applied, sort_applied, cheapest_total_on_page, page, page_size

**Example request body:**
```json
{
  "product_id": "17689644"
}
```

### POST /fnac/v1/product/reviews — 2 credits
Customer reviews for a product, by URL or product_id, paged and sortable: score, title, text, author display name, date, purchase date, verified-purchase flag and helpful votes, plus the average rating and review count.

**Parameters:**
- `url` (string, optional) — A Fnac product URL (fnac.com, fr.fnac.be, fr.fnac.ch, fnac.pt). Every search row returns one.
- `product_id` (string, optional) — Instead of url: the Fnac product id (digits, as `product_id` in search rows) or the URL code (a17689644, mp50936938).
- `country` (enum, optional, default "fr") — Fnac storefront. Prices come back in that storefront's currency (CHF for ch). Product ids are shared across storefronts but price, stock and sellers differ. A pasted product URL sets the country itself. [one of: fr, be, ch, pt, es]
- `sort` (enum, optional, default "newest") — Order of the reviews. [one of: newest, most_helpful, rating_desc, rating_asc]
- `page` (integer, optional, default 1) — Review page, 1-based. Fnac serves 10 reviews per page.
- `max_rotations` (integer, optional, default 5) — Advanced: how many times to retry a difficult request (1-8, default 5).

**Returns:** reviews[]{id, score, title, content, author, date, purchase_date, verified_purchase, origin, trust_note, helpful_yes, helpful_no}, count, total_reviews, average_rating, rating_scale, page, total_pages, sort, page_notice, product_id, country

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