dm.de at a glance
dm.de is a ready-to-run Apify actor from abotapi for collecting ecommerce data. Its documented output includes article no. (dan), ean/gtin, product, brand and price, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify.
- Runs on
- Apify cloud: console, API, schedules and integrations
- Data type
- Ecommerce, Automation, Developer Tools
- Region
- Europe
- Pricing
- $1.80 per 1,000 results (Free plan), from $1.00 on paid plans
- Output
- Documented below · JSON, CSV, Excel
- Inputs
- 27 options
- Run success
- 97.7% of completed public runs in the last 30 days
Scrape dm-drogerie markt (dm.de) products: current + strike-through Ausverkauf price with discount, per-unit pricing (per 100ml/kg/piece), brand incl. dm own-brands, EAN, ingredients, pack-size variants, and full reviews with rating breakdown. Search or paste links.
What dm.de can do
- Was-price and discount, structured, not scraped from a badge. When a product carries a reduced original price, both prices are captured along with the computed discount amount and percentage.
- Real per-unit pricing. Bodycare, food, and household products return their unit price (by volume, weight, or piece) separately from the pack price, exactly as the site itself breaks it down.
- Ausverkauf, first class. A specialsOnly toggle narrows any search or category listing to dm's own live clearance/sellout feed, the site's own queryable discount signal, not a guessed category.
- Full review history. Overall rating, review count, a full 1 to 5 star rating breakdown, and every individual review with author, date, rating, title, and body text.
- Rich detail on demand. Full breadcrumb category path, flattened product information (description, ingredients, usage notes, which varies per category and is never hardcoded), pack-size variants with their own price and EAN, brand image, and online/store availability, plus coverage of every brand dm carries, including its own private-label lines alongside national brands.
- Two ways in, one set of filters. Keyword or category search, or paste any product/listing link and continue pagination automatically. Brand, rating, price range, Ausverkauf, and sort narrow the results either way.
Choose what to collect
These inputs let you configure dm.de - Prices, Offers, Unit Price & Reviews. Open the actor on Apify to enter your values and review the current options.
| Input | What it controls |
|---|---|
modestring · required | 'search' finds products by keyword, by a real dm.de category (e.g. 'haare' or 'pflege-und-parfum/koerperpflege/bodylotion-und-hautcreme'), and/or the site's own currently-reduced Ausverkauf items, with real site filters. 'url' scrapes any product or category/listing page URL you paste, walking pagination forward automatically. |
searchTermstring | Free-text keyword (e.g. 'shampoo') or a real dm.de category path exactly as it appears in the site's own navigation or URLs (e.g. 'haare' or 'pflege-und-parfum/koerperpflege/bodylotion-und-hautcreme'). Leave empty and enable Ausverkauf only below to browse the whole clearance feed. |
searchQuerystring | Alias of Search keyword or category. When set, it is used instead of the field above. |
urlsarray | Paste dm.de product pages (.../p/d//), category pages (e.g. .../haare), the Ausverkauf page (.../ausverkauf) or search pages (.../search?query=shampoo). Pagination continues forward automatically from any ?currentPage= already in the URL. Omitting this field in URL mode (API or schedule) scrapes six built-in examples, one per main shape; leaving it untouched in the Console runs the nine prefilled examples (the six plus a paginated category, an article-number-only product link and a bare-host product link). Max products total is shared across them. |
categoryUrlstring | Alias of URLs to scrape for a single dm category, product or search page URL. When set (and no keyword is given) it switches the run to URL mode and is used instead of the list above. |
countrystring | dm market to scrape. Germany (de) has the full feature set. For the other markets keyword search, product URLs, Ausverkauf, price/brand/rating filters, sorting and details work; category paths and per-review rows (reviews fall back to the rating and count) are Germany-only. Prices come back in the market's currency; unitPrice is filled whenever the market's product tile prints a unit price. |
specialsOnlyboolean | dm.de's real, queryable promo taxonomy is its 'Ausverkauf' (clearance/sellout) feed -- verified live. There is no separate queryable 'Angebote'/'Aktion' product feed: the site's 'Aktionen' nav entry is an editorial content hub with no product API behind it, so it is intentionally not exposed here. Turning this on narrows to Ausverkauf items (optionally combined with the keyword/category above), each carrying the site's own strike-through original price and discount. |
Show 20 more inputs
| Input | What it controls |
|---|---|
brandsarray | Only return products from these brands, e.g. 'Balea', 'dmBio', 'alverde NATURKOSMETIK', 'Nivea'. Match the exact brand name as shown on the site (includes dm's own private-label brands). Leave empty for all brands. |
minRatinginteger | Only return products rated at or above this many stars, 1-5. |
minPricenumber | Only return products priced at or above this amount, in euros. |
maxPricenumber | Only return products priced at or below this amount, in euros. |
sortBystring | dm.de's own sort order, verified live to reorder the full server-side result set (so it stays correct across pagination, not just within one fetched page). |
fetchDetailsboolean | A pasted product link always fetches full detail regardless of this toggle, and is charged the enrichment surcharge either way, it has no listing card to fall back on, so without the detail fetch the record would be almost empty. Everywhere else, this toggle adds the full breadcrumb category path, category codes, description, ingredients (Inhaltsstoffe), all other product characteristics (flattened, varies per category), pack-size variants with their own price/EAN, brand image, and online/store availability from the product detail API. Current price, was-price/discount, unit price and rating are already included without this toggle. This toggle and 'Fetch reviews' share one enrichment surcharge, charged at most once per product. |
fetchReviewsboolean | Fetch each product's full review history: overall rating, review count, a full 1-5 rating breakdown, and per-review author/date/rating/title/body. Products with no reviews simply return an empty list. This toggle and 'Fetch full product detail' share one enrichment surcharge, charged at most once per product no matter how many reviews are fetched. |
maxReviewsPerProductinteger | Cap on reviews fetched per product when 'Fetch reviews' is on. 0 = all available reviews, up to 1000. |
maxPagesinteger | Stop after this many result pages per search/category/URL entry. 0 (default) = unlimited -- the run stops at Max products total instead. |
maxItemsinteger | Hard cap on total products returned across every search/category/URL entry. 0 = unlimited (still bounded by Max pages per search); values above 1,000,000 are rejected. |
maxResultsinteger | Alias of Max products total for users coming from other dm scrapers. When set, it is used instead of Max products total. 0 = unlimited. |
resumeFromRunIdstring | Paste a previous run id (or its dataset id) to continue that run: products already collected there are skipped, so this run only returns new products (a delta). Leave empty for a normal run. For recurring daily/weekly monitoring of the SAME search instead, use Incremental changes below. |
incrementalModeboolean | Turn this on for daily or recurring monitoring. The first run returns all matching products as NEW. Later runs return only NEW, UPDATED and REAPPEARED products by default. A product is UPDATED when any field other than reviews, rating, reviewCount and scrapedAt changes (price, original price, discount, special flag, availability, variants, text and so on); those four are still returned on every record but never trigger UPDATED, and you can exclude more with "Ignore fields when detecting changes". Turn on "Emit unchanged products" or "Emit expired products" only when you also want those products returned (and billed). State is kept separately per search/category/URL and per Fetch full product detail/Fetch reviews setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above. |
stateKeystring | Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Leave empty to let the actor derive a key automatically from the search/category/URL and Fetch full product detail/Fetch reviews settings -- different searches then never mix state with each other. |
emitUnchangedboolean | Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED. This returns -- and bills -- extra rows you already have, so leave it off unless you specifically want the full snapshot every run. |
emitExpiredboolean | Off by default. Turn on to also return products that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search/URL set -- not when Max products/Max pages capped it, or when Resume from a previous run was used. This returns -- and bills -- extra synthetic rows, so leave it off unless you need expiry tracking. |
ignoreFieldsForChangesarray | Field names that must NOT make a product UPDATED, for example priceExclVat. Matches the field at any depth; use a dotted path such as variants.price to target one nested place. Ignored fields are still returned in the output, they are only left out of change detection and changedFields. Reviews, rating, reviewCount and scrapedAt are always ignored. |
mcpConnectorsarray | Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify -> Settings -> Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON; the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com). |
notionParentPageUrlstring | URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors. |
maxNotifyListingsinteger | Cap on items written to each connector per run. Does not affect the dataset. |
Fields in the output
The documented dataset includes the fields below. Availability can depend on the source page and selected mode.
productIdArticle No. (dan) (text)eanEAN/GTIN (text)nameProduct (text)brandBrand (text)pricePrice (number)currencyCurrency (text)originalPriceOriginal price (number)discountPercentDiscount % (number)promoLabelPromo label (text)unitPriceUnit price (number)unitPriceBasisUnit price basis (text)isOnSpecialOn Ausverkauf (boolean)Show 20 more fields
ratingRating (number)reviewCountReviews (number)onlineAvailableOnline available (boolean)urlURL (link)imageImage (image)changeTypeChange type (incremental mode) (text)changedFieldsChanged fields (incremental mode) (array)firstSeenAtFirst seen at (incremental mode) (date)lastSeenAtLast seen at (incremental mode) (date)categoryCategory (text)imageUrlImage URL (image)scrapedAtScraped at (date)reviewsReviews (rating, count, breakdown, per-review list) (object)brandImageBrand image (image)categoryPathCategory path (array)descriptionDescription (text)ingredientsIngredients (text)productDetailsCharacteristics / sections (object)variantsPack variants (with EAN) (array)onlineAvailabilityStatusAvailability (text)Example output
An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.
{
"productId": "2938471",
"sku": "2938471",
"ean": "4009876543219",
"name": "Feuchtigkeitscreme Ringelblume 50 ml",
"brand": "GartenPflege",
"category": "Gesichtspflege",
"url": "https://www.dm.de/p/d/2938471/feuchtigkeitscreme-ringelblume",
"price": 5.29,
"currency": "EUR",
"originalPrice": 6.99,
"discountAmount": 1.7,
"discountPercent": 24.3,
"isOnSpecial": true,
"promoLabel": "Ausverkauf",
"unitPrice": 10.58,
"unitPriceBasis": "100 ml",
"packSize": "50 ml",
"rating": 4.2,
"reviewCount": 63,
"onlineAvailable": true,
"onlineAvailabilityStatus": "Lieferbar",
"storeAvailabilityStatus": "Im Markt vorrätig",
"isPharmacy": false,
"priceExclVat": 4.94,
"image": "https://www.dm.de/pics/p2938471.jpg",
"images": [
"https://www.dm.de/pics/p2938471.jpg"
],
"reviews": {
"averageRating": 4.2,
"totalReviewCount": 63,
"ratingDistribution": [
{
"rating": 5,
"count": 36
},
{
"rating": 4,
"count": 14
},
{
"rating": 3,
"count": 6
},
{
"rating": 2,
"count": 3
},
{
"rating": 1,
"count": 4
}
],
"items": [
{
"rating": 5,
"title": "Fictional title text",
"body": "Fictional review body text.",
"author": "Fictional Reviewer",
"date": "2026-03-05T10:15:00.000Z",
"isRecommended": true,
"verifiedPurchaser": true
}
]
}
}Ways to use this data
- Price and discount tracking: monitor Ausverkauf and clearance prices, plus per-unit pricing, across brands to catch genuine markdowns.
- Retail intelligence: benchmark dm's own private-label and national-brand pricing over time for competitor research.
- Review and reputation analysis: study rating breakdowns and review text for personal-care and household products.
- Catalog and assortment research: build category-level snapshots of the range, including pack sizes and ingredient lists.
- Shopping tools and feeds: feed a price-comparison site, browser extension, or shopping assistant with structured product and pricing data.
Before you run
Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.
Questions about this actor
What data does dm.de return?
The documented output for dm.de includes article no. (dan), ean/gtin, product, brand, price, currency, original price and discount %. Availability of each field depends on the source page and the selected mode.
How much does dm.de cost?
It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.
Can I get only new or changed products on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated products, and unchanged ones are not billed unless you turn on emitUnchanged.
What's the difference between Resume and Incremental mode?
Resume continues one specific interrupted run using a pasted run or dataset id. Incremental mode is for running the same search again and again, for example daily, without ever pasting an id: the actor remembers the previous run of that search by itself.
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.
