# Mango Scraper - Prices, Rebajas, Variants & Composition (`abotapi/mango-com-scraper`) Actor

Scrape Mango (shop.mango.com) fashion products: current price plus strike-through Rebajas (sale) discount, full colour/size variant matrix, section and category, and (with full detail) composition, care, materials, origin, fit and per-size availability. Search by keyword or Rebajas, or paste links.

- **URL**: https://apify.com/abotapi/mango-com-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Categories:** E-commerce, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 27 total users, 7 monthly users, 90.6% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Mango Scraper: Prices, Rebajas Discounts, Variant Matrix & Composition

Mango Scraper turns shop.mango.com into structured product data. Search by keyword, browse Mango's own Rebajas (sale) feed, or paste product and listing links directly, and the actor continues pagination automatically. Every record carries the current price, the strike-through original price with a discount amount and Mango's own discount percentage when a product is marked down, and the full colour/size variant matrix. Turn on full detail for composition, care instructions, materials, country of origin, fit measurements and per-size availability. Export the results as JSON, CSV or Excel, or read them straight through the API.

### Why This Scraper?

- **Was-price and discount, straight from Mango's own pricing service.** When a product is marked down, both the current and original prices are captured, plus the discount percentage and Mango's own promotion label.
- **Rebajas, first class.** A `specialsOnly` toggle browses Mango's own, real, queryable Rebajas (sale) catalog for the chosen section, with genuine server-side pagination, not a guessed category filter. Mango Outlet is a separate site and out of scope here.
- **Full colour/size matrix.** Every colourway and size Mango sells for a product, each colour with its own price, discount and image gallery. Turn on full detail and each size also carries real-time availability (in stock, last units, or delayed).
- **Composition, care, materials, origin and fit.** With full detail on, every product also returns its fabric composition, wash-care instructions, a material breakdown by percentage, country of origin, and garment fit measurements.
- **Two ways in.** Keyword search or Rebajas browse, or paste any product or category link and the actor continues pagination forward automatically from wherever the link points.
- **Built for recurring monitoring.** Incremental mode returns only new and changed products on repeated runs against the same search, and a rejected scan fails loudly instead of quietly returning an empty dataset.
- **Optional export to your apps.** Send results into Notion, Linear, Airtable, or any Apify MCP connector alongside the dataset.

### Use Cases

- **Price monitoring and repricing:** track current price, was-price and discount percentage across a catalog or a competitor's Rebajas feed.
- **Sale and markdown tracking:** watch Mango's own Rebajas feed for new markdowns, or monitor a specific search for pieces that go on sale.
- **Merchandising and content teams:** pull product names, categories, colours and imagery to power a storefront, lookbook, or newsletter.
- **Size and stock monitoring:** use full detail mode to track per-size availability (in stock, last units, delayed) for a product line.
- **Catalog and assortment research:** build a dataset of category, composition, materials and origin across a section for market or sustainability research.

### Data You Get

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

| Field | Example |
| --- | --- |
| `productId` | `"37021368"` |
| `name` | `"Sample Linen Trousers"` |
| `brand` | `"Mango"` (single-brand shop; always this value) |
| `section` | `"Women"` (also `"Men"`) |
| `category` / `families` | `"Trousers"` / `[{"id": "26", "label": "Trousers", "labelEn": "Trousers"}]` |
| `collection` / `model` | `"OI2026"` / `"SACO"` |
| `url` | `"https://shop.mango.com/es/es/p/mujer/pantalones/sample-linen-trousers/37021368"` |
| `price` / `currency` | `19.99` / `"EUR"` |
| `originalPrice` / `discountAmount` / `discountPercent` | `29.99` / `10.00` / `33.3` (only when on sale) |
| `isOnSpecial` / `promoLabel` | `true` / `"PROMOCION HASTA REBAJAS"` |
| `defaultColorId` / `image` | `"99"` / a `media.mango.com` image URL |
| `colors[]` | one entry per colourway: `id`, `label`, `rgb`, its own `price`/`originalPrice`/`discountPercent`, `images[]`, `sizes[]` |
| `colors[].sizes[]` | `id`, `label`, `plusSize`; plus `available`, `isDelayed`, `lastUnits` when full detail is on |
| `compositions` | `["Composition: 55% linen, 45% viscose"]` |
| `care` | `["Machine wash max 30°C, short spin"]` |
| `materials` | `[{"name": "LINEN", "percent": 55}, {"name": "VISCOSE FSC", "percent": 45}]` |
| `originCountry` / `dyeingAndPrinting` / `measures` | `"China"` / when Mango lists it / `["Inseam 76 cm", "Side length 104 cm"]` |
| `lastUnits` / `isSellable` / `isUniqueSize` | `false` / `true` / `false` (product-level, with full detail) |
| `reviews` / `rating` / `ratingCount` | `{"averageRating": null, "totalReviewCount": 0, "items": []}` / `null` / `0` |
| `site` / `isSale` / `scrapedAt` | `"mango"` / `true` (same as `isOnSpecial`) / UTC timestamp |
| `color` / `sizes[]` / `galleryImages[]` | headline colour label / size labels / image URLs of the headline colour |
| `details` | `{"productId", "colorId", "discountPercent", "gender", "subcategory"}` |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | Incremental mode only, e.g. `"UPDATED"` / `["price"]` / timestamps |

Mango's product pages carry no customer reviews, so `reviews` is always returned as this empty structure rather than omitted or guessed, and its own search and listing routes expose no server-side sort parameter, so none is offered here either.

#### Output views

The dataset has four views (also linked from the run's Output tab):

- **overview**: one row per product with price, discount, section, category, link, image and the extra fields above.
- **colors**: `productId`, `name` and the full `colors[]` colour/size matrix.
- **detail**: composition, care, materials, origin and fit measures (filled when full detail is on).
- **changes**: `changeType`, `changedFields`, `firstSeenAt`, `lastSeenAt` and `price` for incremental runs.

### How to Use

1. Pick a **mode**: `search` (keyword and/or Rebajas browse) or `url` (paste product or listing links).
2. Fill in the fields for that mode: `market`, `section` and `searchTerm` and/or `specialsOnly` for search, or `urls` for url mode. `minPrice`/`maxPrice` apply in either mode.
3. Turn on **Fetch full product detail** if you need composition, care, materials, origin, fit measurements and per-size availability.
   **Supported link shapes (url mode):** a product page (`/{market}/p/...`, matched by its product id), a category listing (`/{market}/c/...`) and a keyword search page (`/{market}/search/...?q=`); the promotion/sale listing link (`/c/.../promocion/...`, which replaced the old Rebajas link) is a category listing and works the same; home and section hub pages (`/h/`) are not supported. Any other link is skipped with a warning. **URL mode defaults:** `urls` is pre-filled with six sample links (an ES category, the ES promotion/sale listing, an ES search page, a GB search page, an ES product and a GB product). If you pick `url` mode and leave it untouched, the run scrapes those six links instead of nothing, so check the list before you start. Category and search pages return the products rendered on that one page (about 100 for a category, more for a search); only Rebajas listings paginate with `?page=`. A pasted product link is matched by its product id, never by text search.
4. Set **Max products total** and **Max pages per search** to control run size and cost, then click **Start**.

**Keyword search, default market and section (Women, Spain):**

```json
{
  "mode": "search",
  "searchTerm": "vestido",
  "maxItems": 20
}
```

**Browse the UK men's Rebajas feed:**

```json
{
  "mode": "search",
  "market": "gb/en",
  "section": "MEN",
  "specialsOnly": true,
  "maxItems": 50,
  "maxPages": 5
}
```

**Full product detail (composition, care, per-size availability) for a pasted product link:**

```json
{
  "mode": "url",
  "urls": ["https://shop.mango.com/es/es/p/mujer/sample-linen-trousers/37021368"],
  "fetchDetails": true
}
```

**Daily monitoring of a search, only what changed:**

```json
{
  "mode": "search",
  "specialsOnly": true,
  "section": "WOMEN",
  "incrementalMode": true
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/mango-com-scraper").call(run_input={"mode": "search", "searchTerm": "vestido", "maxItems": 20})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["name"], product["price"], product["currency"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/mango-com-scraper').call({ mode: 'search', searchTerm: 'vestido', 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.

#### Resume and recurring updates

Two different things: Resume continues ONE specific interrupted run. Incremental mode is for running this same search again and again and getting only the changes.

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset id and the actor skips every product it already collected there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same mode/section/search/URL/detail scope. Each product is classified `NEW`, `UPDATED` (with `changedFields`), or suppressed as `UNCHANGED` (not billed unless `emitUnchanged` is on). Turning on `emitExpired` additionally marks a product `EXPIRED` once a run has fully scanned the tracked scope and no longer finds it; a `maxItems`/`maxPages` cap, Resume, or a rejected page all skip this step and keep the previous state as is. `REAPPEARED` is not a default outcome: it only appears for a product that was previously marked `EXPIRED` and is then found again on a later run, so it requires `emitExpired` to have been on for an earlier, complete scan. **What is compared:** every output field except the volatile ones -- price, original price, discount, promo, currency, name, category, colours, sizes and (with `fetchDetails`) per-size availability and composition drive `UPDATED`; the headline `image`, `colors[].images`, `galleryImages` and `scrapedAt` (links, order and timestamps churn between scrapes) and the derived convenience fields `site`, `isSale`, `color`, `sizes`, `details`, `rating` and `ratingCount` (they duplicate fields that are already compared, or are placeholders) are never compared, and `ignoreFieldsForChanges` lets you exclude more (top-level names or dotted paths such as `colors.sizes.available`; `productId` can't be ignored). Ignored fields stay in the output. Changing the list never causes a one-time wave of `UPDATED` rows, because saved copies are re-checked with the current list. `stateKey` names or shares the stored state; leave it empty and the actor derives one automatically from the search/URL/detail settings, so different searches never mix state.

### 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**.

1. Authorize a connector once under **Apify, Settings, Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. If the picker is empty, you haven't authorized a connector yet.
3. For **Notion**, also set `notionParentPageUrl` to the page where item pages 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 Rebajas) or `url` (paste product or listing links). |
| `market` | string | `es/es` | Mango's own market path prefix, e.g. `es/es`, `gb/en` (search mode only; a pasted URL carries its own market). Search mode's own nav path is verified for `es`, `en`, `fr`, `de`, `it` and `pt` language markets; other languages may fail loudly rather than silently return nothing. |
| `section` | string | `WOMEN` | `WOMEN` or `MEN` (search mode only). Other Mango sections can still be reached by pasting URLs in url mode. |
| `searchTerm` | string | none (prefill: `vestido`) | Keyword for search mode. Mango's own search results page never paginates, so a keyword search always returns a single page. |
| `specialsOnly` | boolean | `false` | Browse Mango's Rebajas (sale) catalog for the chosen section instead of a keyword search (search mode only); a keyword is ignored when this is on. |
| `urls` | array | six sample links: two product pages (`/p/`, ES and GB), two category listings (`/c/`, one the promotion/sale listing), two keyword search pages (`/search/...?q=`, ES and GB) | Product, category listing or keyword-search-page links to scrape (url mode only). Other link shapes are skipped with a warning. A Rebajas listing link works while Mango's sale is on; off-season it returns 404 and the run warns. Pagination continues forward automatically from any `?page=` already in the URL. |
| `minPrice` | number | none | Only return products priced at or above this amount, in both search mode and url mode. |
| `maxPrice` | number | none | Only return products priced at or below this amount, in both search mode and url mode. |
| `fetchDetails` | boolean | `false` | Adds composition, care, materials, origin, fit measures, and per-size availability. A pasted product URL in url mode always fetches this detail regardless of this toggle. |
| `maxPages` | integer | `0` (unlimited) | Stop after this many result pages per Rebajas/URL entry; keyword search is always a single page. |
| `maxItems` | integer | `20` | Hard cap on total products returned across every search/URL entry; `0` = unlimited. |
| `resumeFromRunId` | string | none | Continue one interrupted run; products it already collected are skipped, so this run returns only new products. |
| `ignoreFieldsForChanges` | string\[] | `[]` | Incremental mode only: fields that must not count as a change (top-level or dotted paths like `colors.sizes.available`); kept in output. Always ignored: `image`, `colors.images`, `galleryImages`, `scrapedAt` and the other derived fields listed under Data You Get. `productId` can't be ignored. |
| `incrementalMode` | boolean | `false` | Turn on for recurring monitoring of the same search/section/URL scope; classifies each product as NEW, UPDATED, UNCHANGED, EXPIRED or REAPPEARED. |
| `stateKey` | string | none (auto-derived) | Name a monitoring campaign to keep its state stable, or deliberately share state across differently-configured runs. |
| `emitUnchanged` | boolean | `false` | Also return, and bill, products that have not changed since the last run. |
| `emitExpired` | boolean | `false` | Also return, and bill, products no longer found, after a complete scan of the tracked scope. |
| `proxy` | object | Apify Proxy | Connection settings. The actor requests a residential connection matched to the requested market's country, regardless of the Apify Proxy group selected; supplying your own proxy URLs replaces it. Datacenter connections are not supported. |
| `mcpConnectors` | array | none | Optional MCP connectors to export a summary of results into (Notion, Linear, Airtable, Apify). |
| `notionParentPageUrl` | string | none | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items exported to each connector per run. Does not affect the dataset. |

### Output Example

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

```json
{
  "productId": "37021368",
  "name": "Sample Linen Trousers",
  "brand": "Mango",
  "section": "Women",
  "collection": "OI2026",
  "model": "SACO",
  "category": "Trousers",
  "families": [{ "id": "26", "label": "Trousers", "labelEn": "Trousers" }],
  "url": "https://shop.mango.com/es/es/p/mujer/pantalones/sample-linen-trousers/37021368",
  "price": 19.99,
  "currency": "EUR",
  "originalPrice": 29.99,
  "discountAmount": 10.0,
  "discountPercent": 33.3,
  "isOnSpecial": true,
  "promoLabel": "PROMOCION HASTA REBAJAS",
  "image": "https://media.mango.com/is/image/punto/37021368-99-002",
  "defaultColorId": "99",
  "colors": [
    {
      "id": "99",
      "label": "Black",
      "rgb": "36,36,36",
      "sizes": [
        { "id": "36", "label": "36", "plusSize": false, "available": true, "isDelayed": false, "lastUnits": false }
      ],
      "images": [{ "code": "002", "url": "https://media.mango.com/is/image/punto/37021368-99-002", "alt": "Sample Linen Trousers" }],
      "price": 19.99,
      "currency": "EUR",
      "originalPrice": 29.99,
      "discountAmount": 10.0,
      "discountPercent": 33.3,
      "isOnSpecial": true,
      "promoLabel": "PROMOCION HASTA REBAJAS"
    }
  ],
  "compositions": ["Composition: 55% linen, 45% viscose"],
  "care": ["Machine wash max 30°C, short spin", "Do not bleach"],
  "materials": [{ "name": "LINEN", "percent": 55 }, { "name": "VISCOSE FSC", "percent": 45 }],
  "originCountry": "China",
  "measures": ["Inseam 76 cm", "Side length 104 cm"],
  "lastUnits": false,
  "isSellable": true,
  "isUniqueSize": false,
  "reviews": { "averageRating": null, "totalReviewCount": 0, "items": [] }
}
```

### Plan Requirement

Mango's site shows a security checkpoint page (HTTP 429) to automated visitors. Datacenter connections do not work on it, and a residential connection alone is also refused: the actor has to complete a session step on every run before the pages load. It does this automatically; you do not configure it.

- **Paid Apify plan with residential proxy access (recommended):** the actor connects through a residential connection matched to your market's country, completes the session step and reads the pages. Residential traffic is billed by Apify at a higher rate than datacenter, so factor this into large or frequent runs.
- **Free plan (no residential proxies):** the actor logs `The selected connection is unavailable to this run. Apify free plans do not include residential proxies.` and continues on a backup connection, noting `Served over the backup connection (the default connection was unavailable).` Some pages may still be unavailable.
- **Your own proxy URLs:** supported through the `proxy` input; they replace the built-in connection (no backup connection is used).

If nothing could be read, the run fails with one of these messages instead of finishing as an empty success:

- `The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required` (check your own proxy credentials if you supplied URLs).
- `No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Mango pages.`
- `Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later.`

Pricing is pay per event, quoted from the live Pricing tab (FREE tier / GOLD tier): **Product result** $0.002 / $0.001 per product returned; **Full detail enrichment** $0.0008 / $0.0005 per returned product enriched with full detail (BRONZE, SILVER and PLATINUM/DIAMOND tiers are on the Pricing tab); **Actor Start** $0.08 / $0.05 per run.

### FAQ

#### How much does it cost?

You pay per product returned, plus a per-item surcharge when full detail is fetched: with **Fetch full product detail** on, and always for a pasted product URL, which fetches its detail page regardless of that setting. The surcharge is billed per record, at the moment each one is delivered to the dataset (one detail-enrichment unit each, so an interrupted run is only billed for what was delivered), and applies only to records that are actually returned and successfully enriched, never to a failed detail fetch or a suppressed UNCHANGED record. The **Pricing** tab shows the current rates. Use **Max products total** to cap the cost of any run; when that cap is reached the run stops and nothing more is billed. If the run reaches the maximum total charge you set for it, it stops at that point: rows the platform did not store (including EXPIRED rows in Incremental mode) are neither returned nor billed, and are kept for the next run.

#### Is it legal to scrape Mango?

This actor collects only publicly available product data. You are responsible for how you use it: follow Mango's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product names and prices are generally facts, but photos and brand names may be subject to third-party rights.

#### 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 later run against the same search/section/URL set returns only `NEW` and `UPDATED` products by default; unchanged ones are suppressed and not billed unless you turn on **Emit unchanged products**.

#### Does a returning product ever come back marked REAPPEARED?

Only if it was previously marked `EXPIRED`. That itself requires **Emit expired products** to have been on for an earlier run that scanned the tracked scope completely, with no Max products or Max pages cap, no Resume, and no rejected page. Without that history, a product that disappears and later comes back is classified `UPDATED` if anything about it changed, or suppressed `UNCHANGED` if it did not; its state record is never deleted, so it is never `NEW` again.

#### What's the difference between Resume and Incremental mode?

**Resume** (`resumeFromRunId`) continues ONE specific interrupted run: paste its run or dataset id and already-collected products are skipped. **Incremental mode** is for running the same search again and again, daily or weekly, and getting only what changed; it remembers its own state between runs, keyed by the search/section/URL/detail settings or by your own **State key**.

#### Why did my run fail instead of returning an empty dataset?

If the run returns nothing and at least one page or product request (a search page, a Rebajas catalog page, a pasted listing page, or a product detail fetch) was rejected by the site (for example, the Rebajas catalog can go offline outside its own sale season), the run stops with a clear error message instead of finishing successfully with 0 items, so "nothing matched" is never confused with "nothing could be read". A price filter that legitimately narrows a successfully loaded catalog to zero rows, with no rejected requests, still finishes as a normal, empty run.

#### 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 a summary of results into Notion, Linear or Airtable.

### 🔗 Want more fashion data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🛒 <a href="https://apify.com/abotapi/zara-com-scraper"><b>Zara Scraper</b></a><br>Scrape Zara (zara.com) products: current price plus strike-through Rebajas (sale)...</td><td>👗 <a href="https://apify.com/abotapi/24s-com-scraper"><b>24S Scraper</b></a><br>Scrape 24S luxury fashion by category, filters, or URL. Extract brand, name, price...</td></tr>
<tr><td>👗 <a href="https://apify.com/abotapi/otto-de-scraper"><b>OTTO.de Scraper</b></a><br>Scrape OTTO.de products by search or URL. Extract prices, discounts, variants...</td><td>👗 <a href="https://apify.com/abotapi/next-uk-product-scraper"><b>Next.co.uk Scraper</b></a><br>Scrape Next.co.uk: keyword search, category and product-listing walks, full product...</td></tr>
<tr><td>👗 <a href="https://apify.com/abotapi/yesstyle-com-scraper"><b>YesStyle Scraper</b></a><br>Scrape YesStyle products by keyword or URL. Extract prices, discounts, ratings, stock...</td><td>👗 <a href="https://apify.com/abotapi/goat-sneaker-scraper"><b>GOAT Scraper</b></a><br>Scrape GOAT (goat.com), the sneaker and streetwear resale marketplace. Search or paste...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/mango-com-scraper/issues/open). 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.

# Actor input Schema

## `mode` (type: `string`):

'search' finds products by keyword and/or Mango's own Rebajas (sale) feed for a chosen section. 'url' scrapes any product or category/Rebajas listing page URL you paste, walking pagination forward automatically.

## `market` (type: `string`):

Mango's own market path prefix, e.g. 'es/es' (Spain, Castellano) or 'gb/en' (UK, English). Applies to search mode; a pasted URL in url mode carries its own market instead.

## `section` (type: `string`):

Which Mango nav section to search/browse. Only Women and Men are wired to keyword search and the Rebajas feed below; other sections (Teen, Kids, Home) can still be scraped via pasted URLs in url mode.

## `searchTerm` (type: `string`):

Free-text keyword, e.g. 'vestido' or 'pantalon lino'. Mango's own search results page does not paginate (verified live), so a keyword search always returns a single page of results. Leave empty and use Rebajas only below to browse the sale feed without a keyword.

## `specialsOnly` (type: `boolean`):

Browse Mango's own, real, queryable Rebajas (sale) catalog for the chosen section, with genuine server-side pagination -- verified live (2000+ items across dozens of pages). Does not combine with a keyword (mango.com's search and its Rebajas catalog are two separate systems); a keyword is ignored when this is on. Mango has no separate 'Outlet' catalog on shop.mango.com itself (Mango Outlet is a distinct site, out of scope here), so Rebajas is the site's one real specials taxonomy.

## `urls` (type: `array`):

Paste one or more mango.com product pages (/p/), category listing pages (/c/, including the current promotion/sale listing, which replaced the old Rebajas link) or keyword search pages (/search/...?q=), in any market. Other link shapes are skipped with a warning. Pagination continues forward automatically from any ?page= already in the URL. Search-mode fields are ignored here. The fields in the Filters section still apply, including to a pasted product URL.

## `minPrice` (type: `number`):

Only return products priced at or above this amount, in the market's own currency. Applies in BOTH search mode and URL mode, including a pasted product URL.

## `maxPrice` (type: `number`):

Only return products priced at or below this amount, in the market's own currency. Applies in BOTH search mode and URL mode, including a pasted product URL.

## `fetchDetails` (type: `boolean`):

Adds composition, care instructions, material breakdown by percentage, country of origin, fit/garment measurements, and per-size availability (in stock / last units / delayed) from the product page. Current price, was-price/discount, and the colour/size matrix (without per-size availability) are already included without this toggle. A pasted product URL in url mode always fetches full detail regardless of this toggle.

## `maxPages` (type: `integer`):

Stop after this many result pages per Rebajas/URL entry. Only applies to Rebajas browsing and pasted category URLs (keyword search is always a single page). 0 (default) = unlimited -- walk every page until the site stops returning new products or Max products total is hit.

## `maxItems` (type: `integer`):

Hard cap on total products returned across every search/URL entry. 0 = unlimited (still bounded by Max pages per search).

## `proxy` (type: `object`):

This actor always connects over a residential proxy (country matched to your requested market), regardless of what is selected here. Residential is billed at a higher rate, so factor this into your usage.

## `resumeFromRunId` (type: `string`):

Paste a previous run id (or its dataset id) to continue a large crawl without returning or charging for products already collected there. Use this after an interrupted run, or when continuing a product pull in another run. For recurring monitoring of the same search/section/URLs, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns all matching products as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED products. A product counts as UPDATED when any output field other than the volatile ones changes -- price, original price, discount, promo, currency, name, category, colours, sizes and (with Fetch details) per-size availability and composition; reviews fields are placeholders and never drive changes. Never compared: the headline `image`, `colors.images`, `galleryImages` and `scrapedAt` (links, order and timestamps churn between scrapes), and the derived convenience fields `site`, `isSale`, `color`, `sizes`, `details`, `rating` and `ratingCount` (they duplicate fields that are already compared), plus anything you list in "Ignore fields when detecting changes" below. Turn on "Emit unchanged" or "Emit expired" only when you also want those products returned (and billed). State is kept separately for each mode/section/search/URL and detail-mode setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

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 mode/section/search/URL and detail settings -- different searches then never mix state with each other.

## `emitUnchanged` (type: `boolean`):

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.

## `emitExpired` (type: `boolean`):

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/URLs -- not when Max products capped it, or when Resume was used. This returns -- and bills -- extra synthetic rows, so leave it off unless you need expiry tracking.

## `ignoreFieldsForChanges` (type: `array`):

Optional. Field names that must NOT count as a change, so a product is not reported UPDATED just because they moved. They stay in the output rows. Use a top-level name (for example `name`) or a dotted path that walks through lists (for example `colors.sizes.available`, `colors.label`). Built in and always ignored: the headline `image`, `colors.images`, `galleryImages` and `scrapedAt` (links, order and timestamps churn without the product changing), plus the derived convenience fields `site`, `isSale`, `color`, `sizes`, `details`, `rating` and `ratingCount` (they duplicate fields that are already compared, or are placeholders). `productId` can never be ignored. Changing this list never causes a one-time wave of UPDATED rows: unchanged products are re-checked against the saved copy using the current list.

## `mcpConnectors` (type: `array`):

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).

## `notionParentPageUrl` (type: `string`):

URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "market": "es/es",
  "section": "WOMEN",
  "searchTerm": "vestido",
  "specialsOnly": false,
  "urls": [
    "https://shop.mango.com/es/es/c/mujer/vestidos-y-monos/e6bb8705",
    "https://shop.mango.com/es/es/search/mujer?q=vestido",
    "https://shop.mango.com/es/es/p/mujer/vestidos-y-monos/fiesta/vestido-asimetrico-fruncido/37037940",
    "https://shop.mango.com/es/es/c/mujer/promocion/7914393e",
    "https://shop.mango.com/gb/en/search/women?q=dress",
    "https://shop.mango.com/gb/en/p/women/coats/coats/handmade-oversized-wool-coat/37006333/32/00"
  ],
  "fetchDetails": false,
  "maxPages": 0,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `colors` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `changes` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "market": "es/es",
    "searchTerm": "vestido",
    "urls": [
        "https://shop.mango.com/es/es/c/mujer/vestidos-y-monos/e6bb8705",
        "https://shop.mango.com/es/es/search/mujer?q=vestido",
        "https://shop.mango.com/es/es/p/mujer/vestidos-y-monos/fiesta/vestido-asimetrico-fruncido/37037940",
        "https://shop.mango.com/es/es/c/mujer/promocion/7914393e",
        "https://shop.mango.com/gb/en/search/women?q=dress",
        "https://shop.mango.com/gb/en/p/women/coats/coats/handmade-oversized-wool-coat/37006333/32/00"
    ],
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/mango-com-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "market": "es/es",
    "searchTerm": "vestido",
    "urls": [
        "https://shop.mango.com/es/es/c/mujer/vestidos-y-monos/e6bb8705",
        "https://shop.mango.com/es/es/search/mujer?q=vestido",
        "https://shop.mango.com/es/es/p/mujer/vestidos-y-monos/fiesta/vestido-asimetrico-fruncido/37037940",
        "https://shop.mango.com/es/es/c/mujer/promocion/7914393e",
        "https://shop.mango.com/gb/en/search/women?q=dress",
        "https://shop.mango.com/gb/en/p/women/coats/coats/handmade-oversized-wool-coat/37006333/32/00",
    ],
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/mango-com-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "market": "es/es",
  "searchTerm": "vestido",
  "urls": [
    "https://shop.mango.com/es/es/c/mujer/vestidos-y-monos/e6bb8705",
    "https://shop.mango.com/es/es/search/mujer?q=vestido",
    "https://shop.mango.com/es/es/p/mujer/vestidos-y-monos/fiesta/vestido-asimetrico-fruncido/37037940",
    "https://shop.mango.com/es/es/c/mujer/promocion/7914393e",
    "https://shop.mango.com/gb/en/search/women?q=dress",
    "https://shop.mango.com/gb/en/p/women/coats/coats/handmade-oversized-wool-coat/37006333/32/00"
  ],
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/mango-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/mango-com-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/7L0Gb44hFULQ1l1wE/builds/3MguNHSf0TiGSyevz/openapi.json
