flaconi Scraper - Perfume & Beauty Price Watch (Germany)
Pricing
from $2.10 / 1,000 product scrapeds
flaconi Scraper - Perfume & Beauty Price Watch (Germany)
flaconi scraper: flaconi.de category listings (perfume, skincare, make-up, hair) to one row per product size with price in EUR, UVP and percent off, 30-day lowest price, price per litre, brand, EAN, badges and fragrance notes. For German beauty price and discount watching.
Pricing
from $2.10 / 1,000 product scrapeds
Rating
0.0
(0)
Developer
Superslow Sloth
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
flaconi scraper: perfume and cosmetics price and discount watch (Germany)
This flaconi scraper reads the category pages of flaconi.de
(perfume, skincare, make-up, hair, body, sale) and returns one flat row per
product size: the price in EUR, the struck-through UVP (recommended
retail price) and the percent off, the lowest price of the last 30 days,
the price per litre or per piece, brand, product line, EAN barcode, badges
(Neu, Limitiert, + Geschenk), voucher code and fragrance notes. Run it on a
schedule and diff the dataset to get a German beauty price and discount watch:
which Dior, Chanel, Gucci or Jean Paul Gaultier perfume dropped, which products
sit 40% under the UVP, and what is new.
No account, no API key, no login, no browser. One request returns about 50 products.
Input
| Field | Notes |
|---|---|
categories | One or more flaconi categories, one per line: the slug from the page address (parfum, damenparfum, make-up, sale) or the page URL (https://www.flaconi.de/kategorie/parfum/). Only /kategorie/<slug>/ listings are supported, not brand pages, search or product pages. A slug flaconi does not know fails with a message and costs nothing. |
maxItems | Products to read per category (default 100, up to 1,000). About 50 a page. flaconi serves about 1,000 products per category however many pages its pager claims, so 1,000 is the most a category yields. |
proxyConfiguration | Apify RESIDENTIAL proxy by default. flaconi.de sits behind Cloudflare, which refuses most datacenter addresses. |
Example input:
{"categories": ["parfum", "damenparfum", "https://www.flaconi.de/kategorie/sale/"],"maxItems": 100}
Output
Prices are numbers in euros, gross, as the shop shows them; currency is EUR.
One row is one size (variant) of a product: flaconi sells a perfume in several
sizes under one product page and the grid shows one size per tile, so a page can
appear as several rows. product_id is the unique key within a category.
| Field | Notes |
|---|---|
category, position, page | The category slug the row was read from, the place in that category's own list counting from 1 across pages (taken before repeats are dropped), and the 1-based page. flaconi's default order drifts between requests. |
product_id, config_id, ean | The size's SKU (80062316-60), the product's SKU shared by its sizes (80062316-C), and the EAN-13 barcode. ean is null on sponsored tiles, which the page does not list in its structured data. |
name, brand, line, product_type | The name as the tile prints it (DIOR Sauvage Elixir Parfum), and its parts: brand DIOR, line Sauvage Elixir, type Parfum (Eau de Parfum, Duftset, Haarserum...). |
url, image_url | The product link with ?variant=<product_id> (opens that size) and the tile photo. image_url is null for a tile with a placeholder (7 of 1,000 parfum rows). |
price, price_from | The price now for the size in size. price_from is true when the tile prints "ab" ("from"): flaconi has other sizes of the product and this is the cheapest price the tile stands for; size and base_price stay those of the tile's variant. |
original_price, on_sale, discount_percent | The "UVP" (unverbindliche Preisempfehlung) the tile strikes through, whether it is above price, and (1 - price / original_price) * 100 to one decimal. Null when the tile shows no UVP. The UVP is the manufacturer's recommended price, not a price history. The tile prints "(-31%)" on only some discounted tiles (194 of 233 measured); the printed integer matched the computed figure within one point every time, so the column is computed for all of them. |
lowest_price_30d | The lowest price of the last 30 days, the figure EU law makes the shop disclose beside a reduction ("Niedrigster Preis in den letzten 30 Tagen"), from the search record the page embeds. Null when flaconi sends none (208 of 2,000 rows on sale and damenparfum). It can be above price (73 of 1,792): on an "ab" tile it belongs to the product's headline price, not necessarily the size's. |
voucher_code | The code of a campaign the tile advertises as a badge (the badge CALVINKLEIN is the code CALVINKLEIN). price does not include the voucher's saving. Null when there is no campaign (56 of 2,000 rows had one). |
size, base_price, base_unit | The size the tile prices (60 ml, 3 Stk), the price per base unit the tile prints (1.853,50 € / 1 l gives 1853.5) and the unit (1 l, 1 Stk, 1 kg). |
badges, sponsored | The badge texts on the tile (Neu, Limitiert, + Geschenk, + Try me, Exklusiv, a campaign code); empty list when none. sponsored is true on a tile flaconi marks "Gesponsert" (a paid placement; 47 of the first 1,000 parfum rows). |
top_notes, heart_notes, base_notes | Fragrance notes as flaconi writes them (Kopfnoten, Herznoten, Basisnoten). Null for a non-fragrance product, a product with none listed, and sponsored tiles. |
currency | EUR. |
Example row (real values, 2026-11-05, parfum category):
{"category": "parfum","position": 1,"page": 1,"product_id": "80062316-60","config_id": "80062316-C","ean": "3348901567572","name": "DIOR Sauvage Elixir Parfum","brand": "DIOR","line": "Sauvage Elixir","product_type": "Parfum","url": "https://www.flaconi.de/parfum/dior/sauvage/dior-sauvage-elixir-parfum.html?variant=80062316-60","image_url": "https://cdn.flaconi.net/media/catalog/product/3/3/3348901567572-1_c_live.jpg?r=1WAIEA&c=de","currency": "EUR","price": 111.21,"price_from": true,"original_price": 184.0,"on_sale": true,"discount_percent": 39.6,"lowest_price_30d": 111.21,"voucher_code": null,"size": "60 ml","base_price": 1853.5,"base_unit": "1 l","badges": [],"sponsored": false,"top_notes": "Grapefruit","heart_notes": "Lavendel","base_notes": null}
Honest nulls, and what the listing does not carry
A field the tile did not show is null, never 0 or ""; badges is an empty
list when there are none.
- No rating or review count. The category grid prints neither.
- No stock column. All 365 search records measured on 2026-11-05 said in stock, and no tile showed an out-of-stock state, so there is nothing to report.
- A price is not a price history.
original_priceis the manufacturer's UVP andlowest_price_30dcovers 30 days. Keep your own history by running on a schedule. - Other sizes. An "ab" tile (
price_fromtrue) stands for several sizes; the others appear as their own rows only if the category lists them as their own tiles. - Repeats. Consecutive pages share 4 to 5 products and the same product can
appear on two pages; a
product_idis returned and charged once per category. Reading 1,000parfumproducts took 21 pages and skipped 128 repeated tiles.
Pricing
Pay per event:
- $0.002 per run (
actor-start), charged only after your input is validated, so a run that fails on bad input costs nothing. - $0.0021 per product written (
product-scraped), i.e. $2.10 per 1,000 products. A row that is not written is not charged: repeats of a product the same category already returned, and a category that fails, are free.
How it fetches
flaconi.de is a server-rendered Next.js shop behind Cloudflare. A category page
(https://www.flaconi.de/kategorie/parfum/) is about 1.7 MB of HTML holding 45 to
55 product tiles, a schema.org list of the non-sponsored ones (EAN, fragrance
notes) and the search records the page embeds (30-day lowest price, voucher). This
actor reads that page with a browser's TLS fingerprint through Apify's RESIDENTIAL
proxy and rotates the exit address on every refused attempt. A plain HTTP client is
answered 403 ("Just a moment...").
Things worth knowing, all measured on 2026-11-05:
- Paging is zero-based
?page=. The bare address is page 0;?page=1is the second page.?p=,?seite=and?pageNumber=are ignored. - Depth is about 1,000 products a category, not what the pager says.
parfumclaims 124 pages; the last page with tiles is?page=20(21 pages) and?page=21answers HTTP 200 with flaconi's "no products found" message, which the actor reads as the end. A short category stops on its pager (duftoel: 2 pages, 79 products). - An unknown slug is HTTP 404 and fails that category with a message; the other categories still run.
- Weight. About 1.7 MB and 2 to 3 seconds a page from the build machine, so a 30-product run is one request and a 1,000-product category is 21.
- Proxy. A probe from the Apify platform read the category page through datacenter addresses 3 of 10 times (HTTP 403 the other seven) and through RESIDENTIAL ones 10 of 10, so RESIDENTIAL is the default and the log warns when it is not selected.
If flaconi changes the page, the run fails with a message instead of returning empty rows.