druni.es - Prices, Ofertas Flash, Variants & Reviews avatar

druni.es - Prices, Ofertas Flash, Variants & Reviews

Pricing

from $1.00 / 1,000 product results

Go to Apify Store
druni.es - Prices, Ofertas Flash, Variants & Reviews

druni.es - Prices, Ofertas Flash, Variants & Reviews

Scrape Druni beauty, cosmetics and perfume products. Search by keyword, category, Ofertas Flash deals or paste product and listing URLs. Extract prices, original prices, discounts, images, product details, and format or colour variants with individual prices and availability.

Pricing

from $1.00 / 1,000 product results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

17 hours ago

Last modified

Share

Druni Product Scraper

Pull product data from Druni (druni.es), a Spanish beauty and perfumery retailer. Search by keyword, a real Druni catalog category, or the site's own Ofertas Flash deals feed, or paste product and listing links directly. Every record includes the current price, the strike-through original price with computed discount when a product is marked down, and format/color variants with their own price and availability when you ask for full detail.

Why This Scraper?

  • Was-price and discount, structured, not scraped from a badge. When a product is marked down, both prices are captured plus the computed discount amount and percentage.
  • Ofertas Flash, first class. A specialsOnly toggle narrows any search or category listing to Druni's own live discount feed -- the site's real, queryable markdown signal, not a guessed category.
  • Format and color variants. Perfumes, creams and similar products return every size (e.g. 20ML/30ML/50ML/100ML) or shade as its own variant, each with its own price and availability, plus a computed unit price per 100 ml/g where the pack size is unambiguous.
  • Reviews straight from the product page. Overall rating, review count, and the product's own most recent reviews (author, date, rating, body) -- not a third-party review vendor.
  • Two ways in. Keyword or category search with real site filters (brand, price range, Ofertas Flash, sort), or paste any product/listing link and continue pagination automatically.
  • Resume & recurring updates. Turn on Incremental mode to get only NEW, UPDATED, and REAPPEARED products on a scheduled re-run of the same search -- see "Resume & recurring updates" below.
  • Optional export to your apps. Send results into Notion, Linear, Airtable, or any Apify MCP connector alongside the dataset.

Data You Get

FieldExample value
productId / sku123456
nameSample Eau de Parfum
brandSAMPLE BRAND
category / categoryPathFragancias Femeninas, ["Druni", "Perfumes", "Perfumes Mujer", "Fragancias Femeninas"]
urlhttps://www.druni.es/sample-eau-de-parfum-sample-brand
price / currency39.95, EUR
originalPrice / discountAmount / discountPercent59.95, 20.00, 33.4
isOnSpecialtrue
onlineAvailabletrue
image / images["https://www.druni.es/sample/image.jpg"]
descriptionfull product description text
variants[{"sku": "1234568", "name": "Sample Eau de Parfum 50ML", "size": "50ML", "price": 39.95, "currency": "EUR", "onlineAvailable": true, "unitPrice": 79.9, "unitPriceBasis": "100 ml"}]
rating / reviewCount4.2, 18
reviews.averageRating / reviews.totalReviewCount4.2, 18
reviews.items[][{"rating": 5, "body": "Sample review text.", "author": "Cliente", "date": "2026-06-05"}]

Sample shape: values above are illustrative placeholders, not from a live product.

Incremental mode only. When incrementalMode is on, every returned record also carries:

FieldDescription
changeTypeNEW | UPDATED | UNCHANGED | REAPPEARED | EXPIRED
changedFieldsTop-level fields that changed since last seen; non-empty only for UPDATED
firstSeenAtWhen this product was first observed by this monitoring campaign
lastSeenAtWhen this product was last observed

Change detection is based on price, discount/Ofertas Flash status, unit price, availability, and rating/review count -- these are all real signals a monitoring run should surface as UPDATED. One thing is deliberately excluded from change detection and will never by itself cause a product to come back as UPDATED: the reviews.items list. The product page only ever surfaces druni.es's most-recent 10 reviews, so a brand-new review silently pushes an older one out of that window even though nothing about the older review changed -- diffing the list itself would flag that churn as a product change it is not. reviews.averageRating / reviews.totalReviewCount and the top-level rating / reviewCount fields ARE included in change detection (measured live: review counts across a sample of real products ranged 2-267, not high enough traffic to tick every run the way a mega-catalogue would, so a rating/count move is treated as real signal, not noise).

How to Use

1. Keyword search, first page, with reviews (default):

{
"mode": "search",
"searchTerm": "perfume mujer",
"maxItems": 20
}

2. Category browse, filtered to a brand and sorted by price, only Ofertas Flash items:

{
"mode": "search",
"category": "Fragancias Femeninas",
"brands": ["DOLCE & GABBANA"],
"specialsOnly": true,
"sortBy": "PRICE_ASC",
"maxItems": 50,
"maxPages": 5
}

3. Full product detail (variants + description) and reviews for a pasted product link:

{
"mode": "url",
"urls": ["https://www.druni.es/sample-eau-de-parfum-sample-brand"],
"fetchDetails": true,
"fetchReviews": true
}

4. Paste the Ofertas Flash listing and keep paginating forward:

{
"mode": "url",
"urls": ["https://www.druni.es/ofertas-flash"],
"maxItems": 100,
"maxPages": 10
}

5. Continue a previous run, collecting only new products:

{
"mode": "search",
"category": "Fragancias Femeninas",
"resumeFromRunId": "<a previous run id or dataset id>"
}

Input Parameters

ParameterTypeDescription
modestringsearch or url.
searchTermstringKeyword (search mode only).
categorystringA real Druni catalog category, e.g. Fragancias Femeninas (search mode only).
specialsOnlybooleanKeep only products currently in Druni's Ofertas Flash feed (search mode only).
brandsarrayExact brand names to keep (search mode only).
minPrice / maxPricenumberEUR price band to keep (search mode only).
sortBystringRELEVANCE, PRICE_ASC, or PRICE_DESC (search mode only).
urlsarrayProduct, category, or Ofertas Flash listing URLs to scrape (url mode only).
fetchDetailsbooleanFetch full product detail (breadcrumb category path, description, image gallery, format/color variants).
fetchReviewsbooleanFetch the product's own reviews.
maxReviewsPerProductintegerCap on reviews per product; the product page itself only ever surfaces up to 10.
maxPagesintegerCap on result pages per search/category/URL entry; 0 or empty = unlimited (walks every page).
maxItemsintegerCap on total products returned (pushed to the dataset), not pages scanned; 0 = unlimited. See the cap note under "Resume & recurring updates" below -- a capped incremental run still backfills to the cap with unseen products.
resumeFromRunIdstringPrevious run id or dataset id to resume from -- skips every product already collected and returns only the delta, without re-billing it. For recurring daily monitoring of the same search, use Incremental mode instead.
incrementalModebooleanDaily/recurring monitoring of this same search. First run returns everything as NEW; later runs return only NEW/UPDATED/REAPPEARED by default. See "Resume & recurring updates" below.
stateKeystringIncremental mode only. Name this monitoring campaign, or deliberately share state across differently-configured runs. Leave empty to derive one automatically.
emitUnchangedbooleanIncremental mode only. Also return products unchanged since the last run, marked UNCHANGED. Adds and bills extra rows you already have.
emitExpiredbooleanIncremental mode only. Also return products from a previous run no longer found, marked EXPIRED, once a run has fully scanned the search (not capped, not a resume). Adds and bills extra synthetic rows.
proxyobjectApify proxy configuration. Works on every plan by default.
mcpConnectorsarrayOptional MCP connectors to export results into (Notion, Linear, Airtable, Apify).
notionParentPageUrlstringNotion connector only: page under which item pages are created.
maxNotifyListingsintegerCap on items exported to each connector per run. Does not affect the dataset.

Output Example

{
"productId": "123456",
"sku": "123456",
"name": "Sample Eau de Parfum",
"brand": "SAMPLE BRAND",
"category": "Fragancias Femeninas",
"url": "https://www.druni.es/sample-eau-de-parfum-sample-brand",
"price": 39.95,
"currency": "EUR",
"originalPrice": 59.95,
"discountAmount": 20.0,
"discountPercent": 33.4,
"isOnSpecial": true,
"onlineAvailable": true,
"image": "https://www.druni.es/sample/image.jpg",
"categoryPath": ["Druni", "Perfumes", "Perfumes Mujer", "Fragancias Femeninas"],
"description": "Sample product description as shown on the site.",
"variants": [
{ "sku": "123457", "name": "Sample Eau de Parfum 50ML", "size": "50ML", "price": 39.95, "currency": "EUR", "onlineAvailable": true, "unitPrice": 79.9, "unitPriceBasis": "100 ml" },
{ "sku": "123458", "name": "Sample Eau de Parfum 100ML", "size": "100ML", "price": 64.95, "currency": "EUR", "onlineAvailable": true, "unitPrice": 64.95, "unitPriceBasis": "100 ml" }
],
"rating": 4.2,
"reviewCount": 18,
"reviews": {
"averageRating": 4.2,
"totalReviewCount": 18,
"items": [
{ "rating": 5, "body": "Sample review text.", "author": "Cliente", "date": "2026-06-05" }
]
}
}

Sample shape: values above are illustrative placeholders, not from a live product.

A note on reviews and unit pricing

Reviews come directly from the product page itself, not a third-party review vendor -- the page only ever surfaces its most recent reviews (up to 10), while the overall rating and review count reflect the full history. Druni does not display a per-unit (per-100ml/g) price on the site itself; unitPrice/unitPriceBasis on each variant are computed by this scraper (price divided by that variant's own pack size) only when the size is a single unambiguous value, and are left empty otherwise rather than guessed.

Resume & recurring updates

There are two different things here -- pick the one that matches what you're doing:

NeedUse
A crawl stopped and should continueresumeFromRunId / automatic checkpoint recovery
Run the same search every day and receive only changesincrementalMode
Keep separate daily campaigns for similar searchesdistinct stateKey values
Run a normal full snapshotleave both off

Resume (resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips products already collected there, returning only the remaining new products. An automatic same-run checkpoint also protects against platform migrations/Resurrects without any input needed.

Incremental mode (incrementalMode) is for a schedule (for example, daily): the actor remembers the previous run of the same search by itself, so you never paste a run ID. The first run returns everything as NEW. Later runs return only NEW, UPDATED, and REAPPEARED products by default -- duplicates and unchanged products are suppressed (and not charged). Turn on emitUnchanged or emitExpired only when you also want those rows returned (and billed for). State is isolated per search/category/Ofertas Flash/URL and Fetch full product detail/Fetch reviews setup automatically; set stateKey to name or deliberately share a monitoring campaign.

Cap note. maxItems counts products returned, not products scanned. On an incremental run that suppresses most products as UNCHANGED, the walk keeps going past the suppressed ones to backfill the quota with unseen/changed products -- a capped quiet run does not, by itself, mean the bill drops to near zero, because it keeps looking for something to fill the cap with. Every row it does return is still genuinely new/changed, never a repeat. To see the full cost benefit of a quiet run (near-zero pushed rows when nothing changed), leave maxItems at 0 (unlimited) so the walk can reach the natural end of the search instead of stopping at a fixed count.

Scheduled-run example -- same search, run daily:

Day 1 (first run ever for this search):

{ "mode": "search", "searchTerm": "perfume mujer", "incrementalMode": true }

→ every product comes back with "changeType": "NEW".

Day 2 (the schedule fires again, identical input):

{ "mode": "search", "searchTerm": "perfume mujer", "incrementalMode": true }

→ products whose price/discount/Ofertas Flash status/unit price/availability/rating changed come back as "changeType": "UPDATED" with changedFields listing what changed, brand-new products come back as "changeType": "NEW", products that vanished and came back come back as "changeType": "REAPPEARED" -- and products that are still there, unchanged, are not returned at all (suppressed, not charged) unless emitUnchanged is on.

Send results into your apps (MCP connectors)

Optionally pipe results into the apps you already use through Model Context Protocol (MCP) connectors. Authorize a connector once under Apify, Settings, Integrations, then select it in the mcpConnectors field. Each connector receives a condensed, human-readable summary per product (name plus key fields), while the complete record always stays in the Apify dataset. For Notion, set notionParentPageUrl to the page the item pages should be created under, and use maxNotifyListings to cap how many items are exported per connector per run. Supported connectors: Notion, Linear, Airtable, and Apify. Leave the field empty to skip; it never changes the dataset output.

A note on plans

The default connection works on every Apify plan, including the free tier. A residential proxy connection is optional and only worth turning on for very large or sustained runs.