# Ceneo API scraper — Polish price comparison: search products, read the full product record, and get every merchant's offer (price, shop rating, delivery) for one product on ceneo.pl. Prices in PLN. No account, no browser.

> Search ceneo.pl by keyword and get the matching products: Ceneo product id, title, brand, image, the FROM price (the cheapest offer Ceneo knows for that product), how many shops sell it, the customer rating and review count, the category, and Ceneo's own key-parameter preview. Use the returned `product_id` with `product/offers` to get every shop's price for that product.
> ReefAPI engine `ceneo` · 3 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/ceneo/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 or blocked calls are free.
- **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 /ceneo/v1/search — 1 credit
Search ceneo.pl by keyword and get the matching products: Ceneo product id, title, brand, image, the FROM price (the cheapest offer Ceneo knows for that product), how many shops sell it, the customer rating and review count, the category, and Ceneo's own key-parameter preview. Use the returned `product_id` with `product/offers` to get every shop's price for that product.

**Parameters:**
- `query` (string, required) — What to look for on ceneo.pl. Polish keywords match best, but brand and model numbers (e.g. 'logitech g733', 'iPhone 15 128GB') work directly. Ceneo matches loosely, so a two-word query returns accessories as well as the product itself.
- `page` (integer, optional, default 1) — Result page, 1-BASED (1, 2, 3…). 30 products per page. `total_results` tells you how many exist when Ceneo answered as a keyword search; on a category answer it is null and you page until a page comes back empty.
- `sort` (enum, optional, default "relevance") — Result ordering. Only orderings ceneo.pl actually honours are accepted; anything else is rejected rather than silently ignored. Note that `price_asc` sorts on each product's CHEAPEST offer. [one of: relevance, price_asc, price_desc, rating_desc, popularity]
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1–8, default 4 — leave unchanged for typical use).

**Returns:** results[]{product_id, title, brand, url, image, price_min, price_min_display, price_max (null — the search card publishes no upper bound; product/detail has the band), currency=PLN, offer_count (how many shops sell it — null when Ceneo prints no shop count on the card), free_delivery_offer_count, rating, review_count, category, category_id, category_url, key_specs[], variant_count, promoted}, count, excluded_shop_offers (single shop-offer tiles Ceneo mixes into the grid; they have no Ceneo product page, so they are counted, not returned), total_results (null when Ceneo answered with a category page — see search_mode), search_mode ('keyword' | 'category' when Ceneo redirected the keyword onto one of its own category pages), resolved_category, resolved_url (meta.pagination for paging)

**Example request body:**
```json
{
  "query": "logitech g733"
}
```

### POST /ceneo/v1/product/detail — 1 credit
The full Ceneo product record by `product_id` (or product URL): title, brand, description, image gallery, the price BAND across all shops (price_min/price_max) with Ceneo's own offer count, the customer rating, the category breadcrumb and the complete technical specification, grouped exactly as Ceneo groups it.

**Parameters:**
- `product_id` (string, required) — Ceneo product id — the number in the product URL (https://www.ceneo.pl/108733030). A full product URL is also accepted. Every `search` row returns this as `product_id`.
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1–8, default 4 — leave unchanged for typical use).

**Returns:** product{product_id, title, brand, url, description, images[], price_min, price_max, price_min_display, price_max_display, currency=PLN, offer_count, availability, condition, rating, review_count, rating_scale, category, breadcrumb[], specs[]{group, attributes{name: value}}}

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

### POST /ceneo/v1/product/offers — 2 credits
Every shop offer for one product — the price comparison itself. For the given `product_id` you get one row per merchant: merchant name, Ceneo merchant id, merchant domain, price (numeric and formatted), the Ceneo shop rating and how many reviews it rests on, the delivery cost line, whether delivery is free, the declared dispatch time and a working offer link. Rows are ordered cheapest first. Ceneo shows only part of the list on the product page; by default this action returns the complete one.

**Parameters:**
- `product_id` (string, required) — Ceneo product id — the number in the product URL (https://www.ceneo.pl/108733030). A full product URL is also accepted. Every `search` row returns this as `product_id`.
- `all_offers` (boolean, optional, default true) — true (default) returns EVERY merchant offer Ceneo lists for the product. false returns only the offers the product page shows without expanding the list (about 15) and costs one request less.
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1–8, default 4 — leave unchanged for typical use).

**Returns:** product{product_id, title, brand, price_min, price_max, currency=PLN, offer_count (Ceneo's own published count)} + offers[]{position, offer_id, seller{id, name, domain, rating (0-5, null for a shop Ceneo has not rated), rating_count}, price (number), price_display, currency=PLN, offer_url, offer_title (the merchant's own listing title), delivery, free_delivery, dispatch, promoted, product_id} + count, cheapest, most_expensive

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

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