Douglas Germany Scraper - Beauty Products, Prices & Reviews
Pricing
from $1.50 / 1,000 product results
Douglas Germany Scraper - Beauty Products, Prices & Reviews
Scrape Douglas.de beauty and fragrance products by keyword, category, brand, or URL. Extract brands, current and original prices, discounts, unit prices, size variants, stock, images, ratings, reviews, ingredients, and specifications.
Pricing
from $1.50 / 1,000 product results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
6
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Douglas DE Scraper: Beauty, Perfumery & Cosmetics Products
Douglas DE Scraper turns douglas.de, Germany's leading beauty, perfumery and cosmetics retailer, into a clean product data API. Get full pricing (current price, crossed-out original price and discount), unit price, availability, image URLs and rating summary, plus a best-effort layer of ingredient lists, how-to-use text, spec tables and per-review text when detail or review enrichment is requested. Search by keyword, browse a category or brand, or paste Douglas links, then export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Two ways to find products. Search by keyword or category, or paste any Douglas product, category or search URL. A brand filter or a pasted brand URL without a keyword or category covers the Parfum department only.
- Real specials, never guessed. Douglas has no dedicated sale category; a special is detected from the crossed-out original price, and every product carries an explicit
isOnSpecialflag plus the exact savings amount and percent. - Filters that actually narrow. Price band and discounted-only filters apply to every mode, including a pasted category, brand or search URL, not just keyword search.
- Deep product data, best effort. Turn on ingredient lists (INCI), how-to-use text and the full spec table, or pull rating breakdowns and per-review text; these come from a separate, harder-to-reach route than the listing data and can come back empty on a given run, and you're never charged the enrichment surcharge when they do.
- A single pasted product is never filtered out. Paste one product URL and you get that exact product back, whatever its price or discount, though the record is thinner than a listing result (see the FAQ).
- Unresolvable URLs are named, not guessed. A pasted link that matches no Douglas category is reported by name and skipped rather than silently swapped for a different department's products.
- Built for schedules. Set Max items and Max pages to control run size and cost, and a run that never gets a usable connection fails loudly instead of returning an empty dataset billed as a success.
Use Cases
- Price and discount tracking: monitor current price, was price and savings percent across a brand or category to spot restocks and markdowns.
- Catalog and assortment analysis: pull a whole category or brand with availability and images to compare range depth against competitors.
- Review and rating research: turn on review enrichment to attempt the rating histogram and per-review text for a product line, best effort.
- Ingredient and formulation research: turn on detail enrichment to attempt INCI ingredient lists and spec tables across a category, best effort.
- Affiliate and content catalogs: build product feeds with clean pricing and images for a beauty comparison site or newsletter.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
id / sku | "5010207032" / "1269078" |
ean | "4064666325144" (from reviews enrichment, empty otherwise) |
title | "TOM FORD Soleil Neige Eau de Parfum" |
brand | {name: "TOM FORD", code: null} (name is null when the listing carries no brand; code is not populated) |
url | "https://www.douglas.de/de/p/5010207032?variant=1269078" |
price | {current: 76.99, original: 115.0, currency: "EUR", discountPercent: 33.1} (formattedCurrent/formattedOriginal are not populated) |
unitPrice | {amount: 1539.8, currency: "EUR", unit: "per 1 l"} |
isOnSpecial / wasPrice | true / 115.0 (full-price products return false / null) |
savingsAmount / savingsPercent | 38.01 / 33.1 |
availability | {code: "AVAILABLE", inStock: true} |
images | [{url, alt}, ...] (alt is not populated) |
rating | 4.8 |
ratingBreakdown | [{rating: 5, count: 77}, ...] (when reviews are fetched) |
reviews | [{id, author, date, rating, title, body}, ...] (when reviews are fetched) |
ingredients | "ALCOHOL, PARFUM / FRAGRANCE, AQUA / WATER / EAU, ..." (when detail is fetched) |
howToUse | how-to-use instructions (when detail is fetched) |
specifications | {Duftrichtung: "frisch, blumig", Kopfnote: "Jasmin", ...} (when detail is fetched) |
scrapedAt | "2026-09-29T10:15:00+00:00" |
Every record also carries brandLine, productType, productFamily, promoLabel, isMarketplace and characteristics. A handful of fields the schema reserves for a richer product page are always empty in the current listing and enrichment routes: variants, breadcrumbs, description, variantLabel, reviewCount, ratingStars and reviewSummary are always [], "" or null, never populated. All nested detail fields are nullable or empty rather than missing, so a non-discounted product, a brandless marketplace listing or a listing-only run (no ingredients, reviews or spec table fetched) is an explicit negative in the output, never an absent key.
How to Use
- Pick a mode:
search(keyword, category and/or brand) orurl(paste Douglas links). - Fill in the fields for that mode. The price and discount filters below them apply in both modes.
- Turn on product detail and/or review enrichment if you need ingredients, spec tables or per-review text.
- Set Max items and Max pages to control run size and cost, then click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.
Keyword search:
{"mode": "search","queries": ["vitamin c serum"],"gender": "FEMALE","maxItems": 30}
Browse a brand's discounted products under a price cap:
{"mode": "search","category": "01","brand": "Dior","priceMax": 80,"specialsOnly": true}
Search with detail and review enrichment on:
{"mode": "search","queries": ["eau de parfum"],"fetchDetails": true,"fetchReviews": true,"maxReviewsPerProduct": 50,"maxItems": 20}
Paste a category URL, filtered by price band:
{"mode": "url","urls": ["https://www.douglas.de/de/c/parfum/01"],"priceMin": 40,"priceMax": 100,"maxPages": 3}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/douglas-de").call(run_input={"mode": "search", "queries": ["parfum"], "maxItems": 20})for product in client.dataset(run["defaultDatasetId"]).iterate_items():print(product["title"], product["price"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/douglas-de').call({ mode: 'search', queries: ['parfum'], maxItems: 20 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Filters apply in both modes, with one exception
priceMin, priceMax and specialsOnly narrow the results in search mode and in URL mode alike, including the products found behind a pasted category, brand or search URL. The one exception: a single pasted product URL is always returned, whatever its price or discount, because you asked for that exact product.
Unresolved URLs and caps
A pasted URL that douglas.de's own listing backend does not recognize as a category or brand (a content page, a store-finder page, the homepage) is named in the run log and skipped, never replaced with a different department's products. Max items stops the run once that many products have been collected (default 100); Max pages caps how many result pages are walked per query, category, brand or URL (one page holds 48 products, default 0 meaning unlimited). With Max pages at its default, every page is walked until Max items is reached.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search (keyword, category, brand) or url (paste Douglas links). |
queries | array | no default (prefill: ["parfum"]) | Keywords to search, e.g. "vitamin c serum", "parfum". Each query runs separately. |
category | string | no default (prefill: "01") | A Douglas category code (e.g. 01 Parfum) or a full category URL. Search mode only. |
brand | string | no default | A brand display name (e.g. Dior) or a full brand URL. Search mode only. Without a keyword or category, this covers the Parfum department only; add a category to search a brand elsewhere. |
gender | string | any | Restrict to women's, men's or unisex products. Search mode only, no effect in URL mode. |
sortBy | string | relevance | Best match, price ascending, price descending, newest first or top rated. Search mode only; newest and rating currently return the same order as best match, only price ordering is applied. |
promoFlags | array | no default (prefill: none) | Promotion facet codes such as travel size, new or limited edition. Currently has no effect on results; kept for compatibility. |
urls | array | no default (prefill: ["https://www.douglas.de/de/p/5010207032"]) | Douglas product, category, brand or search URLs. URL mode only. |
priceMin | number | no default | Minimum price in EUR. Applies in both modes; a pasted product URL is always returned regardless. |
priceMax | number | no default | Maximum price in EUR. Applies in both modes; a pasted product URL is always returned regardless. |
specialsOnly | boolean | false | Keep only products currently reduced (crossed-out original price). Applies in both modes. |
fetchDetails | boolean | false | Open each product page for ingredients (INCI), how-to-use text and the spec table. Off = listing fields only. |
fetchReviews | boolean | false | Pull the rating histogram, EAN and per-review text for each product. |
maxReviewsPerProduct | integer | 20 | Cap on reviews returned per product (1-200). Ignored unless fetchReviews is on. |
maxPages | integer | 0 | Max result pages to walk per query/category/brand/URL (0 = unlimited). One page holds 48 products. |
maxItems | integer | 100 | Hard cap on the total number of products returned across all targets. |
proxyConfiguration | object | Apify Proxy, residential, Germany | Connection settings, used for a pasted product URL and for detail/review enrichment; a Germany exit is required for those, and changing the country can make them return nothing. Search, category, brand and search-URL runs don't use this setting. |
mcpConnectors | array | no default | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | no default | Notion connector only: page under which records are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"id": "5010207032","sku": "1269078","ean": "4064666325144","title": "TOM FORD Soleil Neige Eau de Parfum","variantLabel": "","url": "https://www.douglas.de/de/p/5010207032?variant=1269078","brand": { "name": "TOM FORD", "code": null },"brandLine": "Soleil Neige","productFamily": "Eau de Parfum","productType": "PERFUME","isMarketplace": false,"breadcrumbs": [],"price": { "current": 76.99, "original": 115.0, "currency": "EUR", "formattedCurrent": null, "formattedOriginal": null, "discountPercent": 33.1 },"unitPrice": { "amount": 1539.8, "currency": "EUR", "unit": "per 300 ml" },"isOnSpecial": true,"wasPrice": 115.0,"savingsAmount": 38.01,"savingsPercent": 33.1,"promoLabel": "reduziert","availability": { "code": "AVAILABLE", "inStock": true },"variants": [],"images": [{ "url": "https://images.douglas.de/is/image/rc/5010207032-01", "alt": null }],"description": "","characteristics": ["Eau de Parfum"],"rating": 4.8,"ratingStars": null,"reviewCount": null,"ratingBreakdown": [{ "rating": 5, "count": 77 },{ "rating": 4, "count": 6 },{ "rating": 3, "count": 2 },{ "rating": 2, "count": 1 },{ "rating": 1, "count": 0 }],"reviews": [{ "id": "1001", "author": "Sample User", "date": "2026-05-01", "rating": 5, "title": "Wonderful scent", "body": "Long lasting and elegant.", "isRecommended": true, "variant": "50 ml", "verified": true }],"ingredients": "ALCOHOL, PARFUM / FRAGRANCE, AQUA / WATER / EAU, LIMONENE, LINALOOL","howToUse": "Auf die Haut auftragen, nicht verreiben.","specifications": { "Duftrichtung": "frisch, blumig", "Kopfnote": "Jasmin", "Art-Nr.": "5010207032" },"reviewSummary": null,"scrapedAt": "2026-09-29T10:15:00+00:00"}
Plan Requirement
The default proxy setting (Apify Proxy, residential, Germany) works out of the box. Search, category, brand and search-URL runs don't use it, but a pasted product URL and detail/review enrichment do: those are only reachable through a German connection, and the actor automatically retries with a different connection when one is refused. Changing the country away from Germany can make those parts of a run return nothing.
FAQ
How much does it cost?
You pay per product returned, plus a one-time actor-start charge, with detail and review enrichment billed only on the products that actually returned that data. The Pricing tab shows the current rates. Use Max items and Max pages to cap the cost of any run.
Is it legal to scrape Douglas?
This actor collects only publicly available product data. You are responsible for how you use it: follow Douglas's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product prices and specifications are generally facts, but brand names, images and review text may be subject to third-party rights.
Can I get only the products I care about on a schedule?
Yes. Schedule the actor from the Schedules tab with a fixed keyword, category or brand input, and use priceMin/priceMax/specialsOnly to keep each run scoped to what you track.
Why does turning on detail or review enrichment add nothing?
Product detail and reviews are fetched from a separate, harder-to-reach route than the listing data, and that route is currently blocked more often than not; ingredients, how-to-use text, spec tables, the rating breakdown and per-review text can come back empty on most or all products in a given run. The listing fields (price, availability, images, rating summary) are unaffected either way, and the enrichment surcharge is only charged on products where it actually added data, so a run where enrichment adds nothing costs the same as one with it turned off.
What does a pasted product URL return?
A thinner record than a search or category result. A pasted product page is fetched through the same route used for detail/review enrichment, so it needs the default German proxy setting and can fail if that route is blocked. When it succeeds without detail or reviews turned on, the record has only id, sku, title, url and scrapedAt; it has no price, availability, images or rating. Turn on detail and/or review enrichment on the same run to fill in more, best effort. To get full listing fields (price, availability, images, rating) for a specific product, search or browse for it instead of pasting its URL.
Why did my run fail instead of returning an empty dataset?
If the store refuses every connection, or none of the pasted URLs matched a real Douglas category, the run stops with a clear message instead of billing a quiet, empty success. Running again usually succeeds. If only some URLs matched, you still get products for the ones that did, and the others are named in the run log.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more e-commerce data?
Pair this actor with these related scrapers from the same team:
| 🛒 ROSSMANN.de Scraper Scrape ROSSMANN (rossmann.de) drugstore products: current + original strike-through price... | 🛒 dm.de Scrape dm-drogerie markt (dm.de) products: current + strike-through Ausverkauf price with... |
| 🔌 MediaMarkt Germany Scraper Scrape MediaMarkt.de products by keyword or URL. Extract current and original prices... | 🥦 Kaufland.de Scraper Scrape Kaufland.de, Germany's hypermarket and online marketplace: keyword/category/brand... |
| 🛒 OBI.de Scraper Scrape OBI (obi.de) DIY/home-improvement products: current + strike-through original... | 🛒 druni.es Scrape Druni beauty, cosmetics and perfume products. Search by keyword, category, Ofertas... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.