MediaMarkt.es Scraper - Prices, Offers & Reviews
Pricing
from $1.00 / 1,000 product results
MediaMarkt.es Scraper - Prices, Offers & Reviews
Scrape MediaMarkt Spain (mediamarkt.es) products: current price, strike-through original price + discount on offers, brand, EAN, category path, availability, image gallery, full spec sheet, other-seller offers, and reviews with ratings. Search keywords or paste links.
Pricing
from $1.00 / 1,000 product results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
5
Total users
1
Monthly active users
12 minutes ago
Last modified
Categories
Share
MediaMarkt.es Product Scraper: Prices, Offers & Reviews
MediaMarkt.es Product Scraper turns MediaMarkt Spain (mediamarkt.es) into structured product data. Get current price, the strike-through original price and discount when a product is genuinely on offer, brand, EAN, category path, availability, the full image gallery, a category-specific spec sheet, marketplace seller offers, and customer reviews with ratings. Search by keyword and category, or paste product, category, and search-listing links, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.
Why This Scraper?
- Was-price and discount, gated on the site's own signal, never guessed. When a product carries a struck-through original price, both prices are captured plus the discount amount and percentage. A full-price product simply carries
originalPrice: null, nothing fabricated. - Real customer reviews. Average rating, total review count, and each product's most recent reviews with rating, title, full text, date, and a verified-purchaser flag.
- Full spec sheet on demand. The flattened characteristics MediaMarkt itself shows per product (RAM/CPU/display for a laptop, panel type/resolution for a TV, and so on), never hardcoded to one category's fields.
- Marketplace-aware. Distinguishes MediaMarkt's own retail offers from third-party marketplace sellers, including seller name and rating when a listing is a marketplace offer.
- Real site filters and sort. Brand, price range, and MediaMarkt's own sort order (price, rating, topseller, newest, availability), matching the site's own controls, plus a minimum-rating filter.
- Two ways in. Keyword and/or category search, or paste any product, category, or listing link and pagination continues forward automatically.
- Optional export to your apps. Send results into Notion, Linear, Airtable, or any Apify MCP connector alongside the dataset.
Use Cases
- Price tracking and comparison: collect current price, strike-through original price and discount percentage across a catalog to power price-history charts and deal alerts.
- Marketplace and reseller research: compare MediaMarkt's own retail offers against third-party marketplace sellers, including seller name and rating, before sourcing or repricing.
- Product research and spec comparison: pull the full flattened spec sheet for laptops, TVs, and appliances to build comparison tables and buying guides.
- Review and reputation analysis: collect ratings, review counts, and individual reviews to track sentiment and flag quality issues per product or brand.
- Assortment and availability monitoring: track online availability, delivery, and pickup status across a category or brand to spot stockouts and restocks.
- Deal hunting: filter by brand, price range, and rating, sorted by the site's own price or topseller order, to surface the current best offers.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
productId / sku | "9000001" |
ean | "8400000000158" |
name | "Sample Laptop 15 pulgadas" |
brand | "Sample Brand" |
category / categoryPath | "Portatiles" / ["Informatica", "Portatiles"] |
url | "https://www.mediamarkt.es/es/product/_sample-laptop-9000001.html" |
price / currency | 549 / "EUR" |
originalPrice / discountAmount / discountPercent | 649 / 100 / 15 (all null off a genuine offer) |
isOnSpecial / strikePriceType | true / "XOP" |
onlineAvailable / availabilityStatus | true / "ONLINE" |
isMarketplace | false |
marketplaceSeller | {"sellerId": "S1", "sellerName": "Sample Seller", "sellerRating": 4.2} (marketplace offers only) |
image / images | "https://assets.mmsrg.com/isr/sample/ASSET_ONE" / full gallery array |
specs | {"Tamano de pantalla": "15.6 pulgadas", "Memoria RAM": "16 GB"} (flattened, varies per category, when Fetch full product detail is on) |
delivery | {"status": "AVAILABLE", "displayStatus": "En stock", "earliestDate": "2026-10-02", "latestDate": "2026-10-04"} (when Fetch full product detail is on) |
pickup | {"status": "AVAILABLE", "displayStatus": "Recogida hoy", "isPickable": true} (when Fetch full product detail is on) |
otherOffers | other sellers' offers for the same product, when present and Fetch full product detail is on |
rating / reviewCount | 4.2 / 30 |
reviews | {"averageRating": 4.2, "totalReviewCount": 30, "items": [{"rating": 5, "title": "Sample title", "text": "Sample review text.", "reviewerName": "Sample User", "date": "2026-08-01T10:00:00.000Z", "isVerifiedPurchaser": true}]} (items list is empty unless Fetch reviews is on) |
How to Use
- Pick a mode:
search(keyword and/or category id, with the site's own filters and sort) orurl(paste product, category, or search-listing links). - Fill in the fields for that mode, and switch on Fetch full product detail and/or Fetch reviews for the extra data you need.
- Set Max products total (and optionally Max pages per search) 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, first page (default):
{"mode": "search","searchTerm": "portatil","maxItems": 20}
Category browse, filtered to a brand and price range, sorted by price:
{"mode": "search","categoryId": "153","brands": ["ASUS"],"minPrice": 300,"maxPrice": 900,"sortBy": "PRICE_ASC","maxItems": 50,"maxPages": 5}
Full product detail and reviews for a pasted product link:
{"mode": "url","urls": ["https://www.mediamarkt.es/es/product/_sample-laptop-9000001.html"],"fetchDetails": true,"fetchReviews": true,"maxReviewsPerProduct": 20}
Paste a listing link and keep paginating forward:
{"mode": "url","urls": ["https://www.mediamarkt.es/es/search.html?query=cafetera"],"maxItems": 100,"maxPages": 10}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/mediamarkt-es-scraper").call(run_input={"mode": "search", "searchTerm": "portatil", "maxItems": 20})for product in client.dataset(run["defaultDatasetId"]).iterate_items():print(product["name"], product["price"], product["currency"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/mediamarkt-es-scraper').call({ mode: 'search', searchTerm: 'portatil', 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.
How Max products total splits across pasted links
URL mode with the Links field left untouched scrapes one example of each supported link shape: a category page, the same category's page 2, a category by bare id (c-<id>), a product page (full slug), the same product by bare id (_p-<id>), a search listing and that search's page 2. The product pair resolves to one product and the c-153 / portatiles-153 pair to one listing, so duplicates are skipped. Replace them with your own links.
In URL mode, when you paste more than one product, category, or search link, Max products total is divided evenly across those links before the run starts, and that split is not adjusted afterward. If one link only has a handful of matching products, its unused share is not handed to another link with plenty of supply, so the run can finish below Max products total even though enough products existed overall. For a precise total, paste one link per run, or set Max products total generously so no single link's fixed share becomes the bottleneck.
Pasted links that overlap can also come up short in the same run. When a category or search link reaches its share partway through a results page, the products on that page it did not take are still treated as already handled. A later pasted link that contains those same products, such as a second listing with overlapping results or a product link that appeared on that page, then skips them without collecting or billing them. Example: a category link followed by a link to a product on the category's first page, with Max products total set to 2, returns only 1 product. To avoid this, paste non-overlapping links, put individual product links before listing links, or run overlapping links in separate runs.
Incremental mode (scheduled runs)
Turn on Incremental mode and the actor remembers the products it saw, so a scheduled run returns only what changed. Every row then carries changeType (NEW, UPDATED, REAPPEARED or EXPIRED, plus UNCHANGED if you ask for it), changedFields (the names of the fields that differ), firstSeenAt and lastSeenAt. All row fields are compared except the scrape timestamp, the review list (a new review still shows up through rating and reviewCount) and the day-relative delivery fields deliveryStatus, deliveryDisplayStatus, delivery, fulfillmentEarliest and fulfillmentLatest, which move every day without the product changing; isAvailableForDelivery is still compared, so a real availability flip is reported. Use Ignore fields when detecting changes for fields you do not want to count, for example price.
- Unchanged products are not emitted and not billed (a row is only billed when it is delivered). The product page may still be read to compare it.
EXPIREDrows (products that disappeared from the results) are only reported after a run that walked the whole result list: set Max products total and Max pages per search to0. A run cut short by a cap, a resume id or an unavailable page never marks anything EXPIRED. Each EXPIRED row is a normal delivered result row and counts toward Max products total.- The remembered state belongs to your search, filters and detail/review options. A different search gets its own baseline; set State key to keep one baseline for a task you edit. Changing caps or proxy never starts a new baseline.
- With incremental mode off, output is exactly as before. Combining it with a resume id works but skips the EXPIRED report.
Resume and automatic recovery
resumeFromRunId continues a previous run: point it at that run's or dataset's id and products already saved there are skipped, so this run returns, and bills, only products missing from it. This works the same way whether the earlier products came from a search, a category, or a pasted product link.
A run that is interrupted by an Apify platform migration, or restarted with the Resurrect button after it failed or was aborted, also recovers on its own from an internal checkpoint, in the same run and dataset, with no duplicate products and no double billing. That checkpoint records every product the run had started on, not only the ones it saved. The continued run therefore never retries a product that was still being fetched at the moment of the interruption (with Fetch reviews on, the default, that can be a whole results page of up to 12 products), a pasted product page that failed to load, or a product left behind by the overlapping-links case above. Those products are never collected or billed in that run, and the run can finish with fewer products than Max products total even though more were available. This only affects the continuation of that same run: a brand-new run starts from scratch. If a run finishes short after a migration or Resurrect, start a new run with resumeFromRunId set to the earlier run's id. It checks the products actually saved in the dataset and collects, and bills, only the missing ones. Rerunning the identical input without resumeFromRunId also recovers them, but collects and bills everything again.
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 product, 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 and/or category id, with the site's own filters and sort) or url (paste product, category, or search-listing links; pagination continues forward automatically). |
searchTerm | string | portatil (prefill) | Free-text keyword. Leave empty if you set a Category id below. Search mode only. |
categoryId | string | (none) | Numeric id (153), a pasted category link, or a plain category name such as portatiles (a plain name is used as the keyword when the keyword is empty). Combine with a keyword to search within a category, or leave the keyword empty to browse the whole category. Search mode only; URL mode reads this from the pasted link. |
urls | array | one example of each supported link shape (category page, category page 2, category by bare id, product page, product by bare id, search listing, search page 2) | Product, category, or search-listing links to scrape. Pagination continues forward automatically from any page= already in the URL. Search-mode fields are ignored here; the Filters and sort fields below still apply, including to a pasted product link. |
brands | array | (none) | Only return products from these exact brand names, e.g. APPLE, LENOVO, ASUS, HP. Leave empty for all brands. Applies in both search mode and URL mode. |
minRating | integer | (none) | Only return products rated at or above this many stars, 1-5. Applies in both search mode and URL mode. |
condition | string | all | new or refurbished, decided from the product's own offer (its default offer is the refurbished one, as marketplace refurbished units are), falling back to the site's "reacondicionado" wording in the name or category path. Applied before rows are counted or billed. |
sellerType | string | all | mediamarkt or marketplace (third-party sellers). Applied before rows are counted or billed. |
searchQueries | array | (none) | Several keywords in one run; results are de-duplicated and maxItems caps the whole run. |
sortOrder | string | (none) | Alias of sortBy that also accepts lowercase tokens such as price_asc. |
| Extra output fields | seller, isAvailableForDelivery, refurbishedAvailable (a refurbished offer exists for the product), energyClass, fulfillmentEarliest, fulfillmentLatest, condition, deliveryStatus, pickupStatus are filled only where the page carries them, otherwise null. | ||
minPrice | number | (none) | Only return products priced at or above this amount, in euros. Applies in both search mode and URL mode. |
maxPrice | number | (none) | Only return products priced at or below this amount, in euros. Applies in both search mode and URL mode. |
sortBy | string | RELEVANCE | MediaMarkt's own sort order: RELEVANCE, PRICE_ASC, PRICE_DESC, RATING, TOPSELLER, NEWEST, or AVAILABILITY. Reorders the full server-side result set, so it stays correct across pagination. Applies in both search mode and URL mode. |
fetchDetails | boolean | false | Adds the full flattened spec sheet, delivery/pickup availability detail, energy efficiency label, promo badges, and marketplace/other-seller offers from the product page. Current price, was-price/discount, rating, and main image are already included without this toggle. |
fetchReviews | boolean | true | Fetch each product's review summary (average rating, total count) and its most recent reviews. Returns the site's first review page, capped by Max reviews per product; products with no reviews return an empty list. |
maxReviewsPerProduct | integer | 20 | Cap on reviews returned per product when Fetch reviews is on (values above 50 are treated as 50). 0 = all available on that page. The site's product page currently shows about 10 reviews, so that is the practical ceiling. |
maxPages | integer | 0 | Stop after this many result pages per search/category/URL entry. 0 = unlimited, walk every page until the site stops returning new products or Max products total is hit. |
maxItems | integer | 20 | Hard cap on total products returned across every search/category/URL entry. 0 = unlimited (still bounded by Max pages per search). |
incrementalMode | boolean | false | Remember products between runs and emit only changes (see Incremental mode above). |
stateKey | string | (auto) | Name for the remembered state; empty derives it from your search and filters. |
emitUnchanged | boolean | false | Also emit products that did not change (changeType UNCHANGED). |
emitExpired | boolean | true | After a complete run, emit EXPIRED rows for products no longer listed. |
ignoreFieldsForChanges | array | (empty) | Field names that must not count as a change. |
resumeFromRunId | string | (none) | A previous run id (or its dataset id) to continue: products already collected there are skipped, so this run only returns new products. Leave empty for a normal run. |
proxy | object | residential, Spain | Connection settings. A residential connection is required for a reliable run; the default already selects one in Spain. |
mcpConnectors | array | (none) | Optional: send a summary of each product to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which item pages 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.
{"productId": "9000001","sku": "9000001","ean": "8400000000158","name": "Sample Laptop 15 pulgadas","brand": "Sample Brand","category": "Portatiles","categoryPath": ["Informatica", "Portatiles"],"url": "https://www.mediamarkt.es/es/product/_sample-laptop-9000001.html","price": 549,"currency": "EUR","originalPrice": 649,"discountAmount": 100,"discountPercent": 15,"isOnSpecial": true,"strikePriceType": "XOP","onlineAvailable": true,"availabilityStatus": "ONLINE","isMarketplace": false,"image": "https://assets.mmsrg.com/isr/sample/ASSET_ONE","images": ["https://assets.mmsrg.com/isr/sample/ASSET_ONE"],"rating": 4.2,"reviewCount": 30,"reviews": {"averageRating": 4.2,"totalReviewCount": 30,"items": [{"rating": 5,"title": "Sample title","text": "Sample review text.","reviewerName": "Sample User","date": "2026-08-01T10:00:00.000Z","isVerifiedPurchaser": true}]}}
Plan Requirement
MediaMarkt.es answers plain and datacenter connections with an interactive challenge page, so a residential connection in Spain is required for a reliable run. The default proxy configuration already selects it, so make sure your plan includes residential proxy access.
If residential access is refused for your account (for example on a free plan), the run logs a one-time notice that the selected connection is unavailable, continues on a backup connection, and logs "Served over the backup connection (the default connection was unavailable)." once a page loads that way. Some pages may still be unavailable on the backup connection. If you enter your own proxy URLs, no backup connection is used.
FAQ
How much does it cost?
You pay per product returned, plus one extra charge per product when its full spec sheet, delivery/pickup detail, and/or reviews were actually fetched (never twice for the same product). That extra charge is one unit per started block of 10 delivered reviews, with a minimum of one unit for the product-page read: 0 to 10 reviews bill 1 unit, 11 to 20 bill 2, and 25 bill 3. Reviews count only as many as are delivered (Max reviews per product defaults to 20, and the site's page currently shows about 10), so most products bill one unit. The charge is recorded for each product as soon as it is saved to the dataset; a product whose page did not load is not charged for it. The Pricing tab shows the current rates. Use Max products total to cap the cost of any run.
Is it legal to scrape mediamarkt.es?
This actor collects only publicly available product data. You are responsible for how you use it: follow MediaMarkt's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product images and review text may be subject to third-party rights.
Can I get only new products on a schedule?
Yes. Turn on Incremental mode (see above) and schedule the actor: each run returns only new, updated, reappeared and (after a full walk) expired products, and unchanged products are not billed. resumeFromRunId is a different tool, for continuing one specific earlier run.
Do the brand, price, and rating filters work when I paste a link instead of searching?
Yes. Pasting a category or search-listing link rebuilds the same filtered, sorted request the site's own controls would send, and a pasted product link is checked against the same filters before it is returned.
Why did a run finish with fewer products than Max products total when I pasted several links?
Max products total is split evenly across the pasted links up front and is not redistributed afterward, so a link with little supply cannot free up its unused share for another link with plenty. Separately, if the links overlap, products a listing link saw but did not take once its share was used up are skipped by later links too. Paste one non-overlapping link per run, or set Max products total generously, if you need a precise count.
Why might some products be missing after a run is interrupted and automatically resumes?
An automatic recovery after a platform migration or a Resurrect keeps track of every product the run had started on, not only the ones it actually saved. A product still being fetched when the run was interrupted, or a pasted product page that failed to load, is not retried in that continued run and is never billed. If you suspect products are missing, start a new run with resumeFromRunId pointed at the earlier run: it checks the dataset itself and collects only what is genuinely missing. Rerunning the identical input without it also recovers them, but collects and bills everything again.
Why did my run fail instead of returning an empty dataset?
If the resumeFromRunId you supplied cannot be resolved to a run or dataset from your account, the run fails with a clear message before collecting anything, instead of silently collecting and billing everything again. A run where no page could be loaded at all ends as failed with a plain status message instead of an empty success: one message when the proxy connection is refused for the account (a paid plan is required), one when residential access is unavailable and the backup connection could not load the pages, and one when the requests failed for another reason (a connection problem, not an empty search; try again later). If the site refuses a sustained share of requests mid-run, the run stops collecting further pages but keeps and returns everything already gathered.
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 MediaMarkt data?
Pair this actor with these related scrapers from the same team:
| ๐ MediaMarkt Germany Scraper Scrape MediaMarkt.de products by keyword or URL. Extract current and original prices... | ๐ LeroyMerlin.es Scraper Scrape Leroy Merlin Spain (leroymerlin.es) DIY and home-improvement products: price... |
| ๐ Decathlon.es Scrape Decathlon Spain (decathlon.es) sporting goods: current price plus strike-through... | ๐ฅฆ Mercadona Scraper Scrape Mercadona products by delivery-area postal code. Search by keyword or category, or... |
| ๐ druni.es Scrape Druni beauty, cosmetics and perfume products. Search by keyword, category, Ofertas... | ๐ PcComponentes Scraper Scrape PcComponentes (pccomponentes.com) products: current price plus strike-through... |
๐ Browse all abotapi scrapers
๐ฌ Support
- ๐ 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 contact@abotapi.com.
- โญ Enjoying it? A quick review on the actor page helps other users find it.