# 24S Scraper - Luxury Fashion, Prices, Stock & Product Details (`abotapi/24s-com-scraper`) Actor

Scrape 24S luxury fashion by category, filters, or URL. Extract brand, name, price, discounts, size stock, colors, images, descriptions, composition, and country of origin. Filter by brand, color, size, price, and sale.

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

## Pricing

from $1.00 / 1,000 product scrapeds

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

## 24S Scraper: Luxury Fashion Catalog, Prices & Stock

24S Scraper turns the 24S luxury fashion catalog into structured product data. Get brand, name, price, discount and stock for every item, the full size list with per-size availability, color variants and the image gallery, plus (optionally) the complete description, composition, made-in country and product code. Search by category with brand, color, size, price and discount filters, or paste any 24S category or product link, then export the results to JSON, CSV or Excel, or pull them straight into your app through the API.

### Why This Scraper?

- **40+ fields per product**, including per-size stock and color variants that many catalog scrapers skip.
- **Two ways to collect:** build a category search with brand, color, size, price and discount filters, or paste category and product links directly.
- **Specials tracked at the source:** was-price, savings amount, discount percentage and a single toggle that checks every discount bucket at once, on every discounted result.
- **Optional full product-detail enrichment:** description, bullet points, composition, made-in country, product code and the complete image gallery, added with one extra request per product.
- **Built for schedules:** incremental mode returns only new, updated and reappeared products on recurring runs, and a resume mode continues one interrupted run without re-collecting or re-charging what it already gathered.
- **Works across 24S markets** (locales such as en-gb, en-us, en-au, fr-fr and more), with the backup residential exit matched to the chosen market's country.
- **A refused run fails loudly** instead of silently returning an empty dataset, so a block is never confused with a genuinely empty search.

### Use Cases

- **Price and markdown monitoring:** track was-price, discount percentage and savings amount across brands and categories to watch how 24S prices move over time.
- **Sale-cycle tracking:** turn on Specials only to catch every discount bucket at once and get alerted the moment new markdowns appear.
- **Assortment and merchandising research:** build brand- and category-level datasets of stock, sizes and color variants for competitive analysis.
- **Resale and sourcing tools:** check size-level stock and color availability for products before sourcing or relisting them.
- **Content, comparison and affiliate sites:** pull descriptions, images, composition and product codes to build product pages automatically.

### Data You Get

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

| Field | Example |
| --- | --- |
| `id` | `"BRDXXX0XBCK"` |
| `brand` | `"Sample Brand"` |
| `name` | `"Structured shoulder bag"` |
| `title` | `"Sample Brand Structured shoulder bag"` |
| `color` | `"Black"` |
| `price` | `890.0` |
| `discountPrice` | `623.0` |
| `currentPrice` | `623.0` |
| `discountPercentage` | `30` |
| `currency` | `"EUR"` |
| `onSale` | `true` |
| `isOnSpecial` | `true` |
| `wasPrice` | `890.0` |
| `savingsAmount` | `267.0` |
| `inStock` | `true` |
| `sizes` | `[{"label": "FR 38", "sku": "BRDXXX0XBCKO0AAA00", "inStock": true}]` |
| `otherColors` | `[{"label": "Beige", "shortSku": "BRDXXX0XBEI"}]` |
| `images` | `["https://www.24s.com/static/images/unsafe/fit-in/1024x1280/00000000000000000000000000000000"]` |
| `imagesCount` | `8` |
| `description` | `"Full product description appears here when Fetch product details is on."` |
| `composition` | `"Calf leather"` |
| `madeIn` | `"Italy"` |
| `productCode` | `"BRDXXX0XBCKO0AAA00"` |
| `url` | `"https://www.24s.com/en-gb/structured-shoulder-bag-sample-brand_BRDXXX0XBCK?color=black"` |
| `locale` | `"en-gb"` |

Catalog results also carry `shortSku`, `stockLevel`, `exclusive`, `productSlug`, `discountPercent`, `promoEventName` and `discountStartDate`/`discountEndDate` (when a discount is active). With **Fetch product details** on, results add `bulletPoints`, `year`, `gender`, `productFamily`, `categories` and `detailFetched`. Every row also carries convenience fields: `imageUrl` (first image), `imageUrls` (all images), `originalPrice` (list price), `discount` (percent), `sku` (24S long SKU, with Fetch product details), `category`, `categoryPath`, `categorySlug` (from the page you scraped, or the product's own category tree with Fetch product details), `country` (ISO-2 market) and `scrapedAt`. They are added after change detection, so turning them on never marks tracked products as updated. 24S does not publish a seller field and has no free-text search page, so neither is offered; the former men's universe redirects away and is not available. The optional `country` input (for example `de`; `uk` is read as `gb`; unknown codes are ignored with a warning) is a shortcut for Market / locale (`de` uses the German storefront de-de, every other code the English storefront for that country, such as en-fr or en-it), and Categories also accepts pasted category page URLs.

Incremental mode adds `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt` to every record; see How to Use below.

### How to Use

1. Pick a **mode**: `search` (build category pages with filters) or `url` (paste category or product page links).
2. For search mode, set **Market/locale**, one or more **categories**, and any brand, color, size, price or discount filters. For url mode, paste the pages you want.
3. Turn on **Fetch product details** if you want the full description, composition, made-in country and image gallery.
4. Set **Max products** to control run size and cost, then click **Start**.

**Search a category, basic:**

```json
{
  "mode": "search",
  "locale": "en-gb",
  "categories": ["women/shoes"],
  "maxItems": 50
}
```

**Search with filters:**

```json
{
  "mode": "search",
  "locale": "en-gb",
  "categories": ["women/shoes", "women/bags"],
  "brands": ["SAMPLE BRAND"],
  "colors": ["Black"],
  "minPrice": 300,
  "maxPrice": 1500,
  "sortBy": "price_asc",
  "fetchDetails": true,
  "maxItems": 100
}
```

**Only current specials:**

```json
{
  "mode": "search",
  "locale": "en-gb",
  "categories": ["women/shoes"],
  "specialsOnly": true,
  "maxItems": 60
}
```

**Paste URLs (categories and products mixed):**

```json
{
  "mode": "url",
  "urls": [
    "https://www.24s.com/en-gb/women/shoes",
    "https://www.24s.com/en-gb/women/bags",
    "https://www.24s.com/en-gb/structured-shoulder-bag-sample-brand_BRDXXX0XBCK"
  ],
  "maxItems": 200
}
```

The `urls` field is pre-filled with 19 example links, one per distinct link shape, so a url-mode run with the field left untouched scrapes those examples (capped by Max products) instead of returning nothing; replace them with your own links. Accepted shapes: category pages (`/en-gb/women/shoes`, nested subcategories, brand and color pages), category pages with `?page=N`, `?sort=` and filter parameters, other markets (`/en-us/...`, `/fr-fr/femme/chaussures`), product pages (with an optional `?color=`), locale-less links, and trailing-slash links. Locale-less links such as `/women/shoes` use the Market/locale input. The market in a pasted link follows the same rules as the Market/locale input for the page request itself: `en-uk` is read as `en-gb`, a non-English form of another live market (such as `it-it`) is fetched from that market's English storefront (`en-it`), and a link for a market that is not a live storefront is skipped with a warning and not billed. A `?page=N` link starts at page N and `?sort=` is honoured. Bare department pages (such as `/en-gb/women`) and old `/men/` links are skipped with a warning and not billed; trailing slashes are normalised.

A pasted product link returns that product's detail fields only (brand, description, bullet points, composition, made-in, product code and image gallery); price, stock, sizes and color variants come from category pages, so paste the category link when you need them. Search filters are ignored in url mode; use the filters already in the pasted link.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/24s-com-scraper").call(run_input={"mode": "search", "locale": "en-gb", "categories": ["women/shoes"]})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["brand"], product["name"], product["currentPrice"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/24s-com-scraper').call({ mode: 'search', locale: 'en-gb', categories: ['women/shoes'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### Specials, was-price and discount

24S has no separate sale, private-sale or outlet section; its only specials signal is the discount-percentage bucket filter used by `discounts` above, and a single bucket is not cumulative (asking for the 20% bucket turns up only items in that bucket, not everything discounted 30% or more). Turning on **Specials only** checks every bucket (20/30/40/50) at once, unless you already picked specific buckets yourself. Every result also carries `isOnSpecial`, `wasPrice` and `savingsAmount`, and, when a discount is active, the promotion name and its start and end dates, all read from the same catalog data with no extra request.

#### Max products and Max pages

**Max products** (`maxItems`) is the real cap on a run: it stops once that many products have been collected across every category and URL, and `0` means unlimited. **Max pages** (`maxPages`) is an optional safety cap on how many listing pages are walked per category or URL (72 products per page); leave it empty to let Max products decide instead.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and this run skips every product it already collected there, so you do not pay twice for the same catalog pull.
- **Incremental mode** (`incrementalMode`) is for recurring runs over the same search. Each product is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED`, or `EXPIRED` (only once a run has fully scanned the tracked search, and only with `emitExpired`). `stateKey` names or shares the tracked state; leave it empty and the actor derives one automatically from the locale, categories or URLs and filters, so unrelated searches never mix state. With incremental mode off, output is exactly as before.

### 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 have not authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where product 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` (category and filters) or `url` (paste links). |
| `locale` | string | `en-gb` | 24S market as lang-country: de-de, fr-fr or en-<market> for a live market (en-gb, en-us, en-au, en-jp, en-sg and more); anything else is ignored with a warning and en-gb is used. The backup residential exit is matched to this market's country. |
| `categories` | array | `["women/shoes"]` | Category paths to scrape (search mode), e.g. `women/shoes`, `women/bags`, `women/ready-to-wear`. |
| `brands` | array | (none) | Filter by exact brand name as shown on 24S. Leave empty for all brands. |
| `colors` | array | (none) | Filter by color name. Leave empty for all colors. |
| `sizes` | array | (none) | Filter by size in 24S "FR NN" notation. Leave empty for all sizes. |
| `minPrice` | integer | (none) | Minimum price in the locale's currency (whole units). |
| `maxPrice` | integer | (none) | Maximum price in the locale's currency (whole units). |
| `discounts` | array | (none) | Minimum discount buckets to include: `20`, `30`, `40`, `50`. |
| `specialsOnly` | boolean | `false` | Show only items currently on sale; checks every discount bucket at once. Ignored if you already picked specific buckets. |
| `sortBy` | string | `relevance` | `relevance`, `price_asc`, `price_desc`, or `newest`. |
| `urls` | array | 19 example links (one per URL shape) | 24S category or product page URLs to scrape (url mode). Category links paginate; product links return detail fields only. Filter fields are ignored in this mode. |
| `fetchDetails` | boolean | `false` | Add the full product-detail fields to every result: description, bullet points, composition, made-in and the complete image gallery. |
| `maxItems` | integer | `20` | Maximum products to scrape across all categories and URLs. `0` for unlimited. |
| `maxPages` | integer | (none) | Optional safety cap on pages walked per category or URL (72 products per page). Empty means no page limit; the run stops at Max products. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run or dataset without re-collecting or re-charging its products. |
| `incrementalMode` | boolean | `false` | Recurring monitoring of the same search: later runs return only new, updated and reappeared products. |
| `stateKey` | string | (none) | Optional name for an incremental-mode monitoring campaign; derived automatically from locale, categories or URLs, and filters when empty. |
| `emitUnchanged` | boolean | `false` | Incremental mode only: also return (and bill for) products unchanged since the last run. |
| `emitExpired` | boolean | `false` | Incremental mode only: also return (and bill for) products no longer found, once a run fully scans the tracked search. |
| `proxy` | object | Apify default pool, auto-escalating | Connection settings; the default Apify pool is tried first, and if the site refuses it twice in a row the run switches to a residential exit matched to your market. |
| `ignoreFieldsForChanges` | array | (none) | Incremental mode only: field names (for example `price`) whose changes do not count; a product differing only in them is treated as unchanged and not billed. Matches at any nesting depth. |
| `country` | string | (none) | Optional ISO-2 market shortcut (for example `de`, `gb` or `uk`) for Market / locale; unknown codes are ignored with a warning. |
| `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 product 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 listing.

```json
{
  "id": "BRDXXX0XBCK",
  "shortSku": "BRDXXX0XBCK",
  "brand": "Sample Brand",
  "name": "Structured shoulder bag",
  "title": "Sample Brand Structured shoulder bag",
  "color": "Black",
  "price": 890.0,
  "discountPrice": 623.0,
  "currentPrice": 623.0,
  "discountPercentage": 30,
  "currency": "EUR",
  "onSale": true,
  "isOnSpecial": true,
  "wasPrice": 890.0,
  "savingsAmount": 267.0,
  "discountPercent": 30,
  "promoEventName": "sample_sales",
  "discountStartDate": "2026-01-15T09:00:00+00:00",
  "discountEndDate": "2026-02-15T00:00:00+00:00",
  "inStock": true,
  "stockLevel": 1,
  "sizes": [
    { "label": "FR 38", "sku": "BRDXXX0XBCKO0AAA00", "inStock": true },
    { "label": "FR 39", "sku": "BRDXXX0XBCKO1AAA00", "inStock": false }
  ],
  "otherColors": [
    { "label": "Beige", "shortSku": "BRDXXX0XBEI", "image": "https://www.24s.com/static/images/unsafe/fit-in/1024x1280/00000000000000000000000000000000" }
  ],
  "images": [
    "https://www.24s.com/static/images/unsafe/fit-in/1024x1280/00000000000000000000000000000000"
  ],
  "imagesCount": 8,
  "description": "Full product description appears here when Fetch product details is on.",
  "bulletPoints": ["Adjustable strap", "Logo detail", "Suede lining"],
  "composition": "Calf leather",
  "madeIn": "Italy",
  "productCode": "BRDXXX0XBCKO0AAA00",
  "year": "2024",
  "productSlug": "structured-shoulder-bag-sample-brand",
  "url": "https://www.24s.com/en-gb/structured-shoulder-bag-sample-brand_BRDXXX0XBCK?color=black",
  "locale": "en-gb",
  "detailFetched": true
}
```

### Plan Requirement

The actor first uses the default Apify proxy pool, which needs a plan with Apify Proxy access (free plans do not include it). 24S sits behind an edge service that refuses some connections (for example plain hosting IPs) with an access-denied page. If the default pool is refused twice in a row, the actor logs that the connection was refused by the site edge and switches to a residential exit matched to your market's country, which needs an Apify plan with residential proxy access; on a plan without it the actor says the backup route is unavailable and continues on the default route. If the site keeps refusing the connection, the run stops with a clear message instead of returning an empty dataset. Residential was verified for the GB market only. You can also pick a proxy group yourself in the Connection section. The **Pricing** tab shows the current rates for this actor.

### FAQ

#### How much does it cost?

You pay per product returned (the dataset-item event), a smaller fee per product enriched when **Fetch product details** is on (the detail-enrichment event), and a small fee per run start (the run-start event). Skipped and unreadable pages are not billed; unchanged and expired products are billed only when you turn on **Emit unchanged** or **Emit expired** in incremental mode. The **Pricing** tab shows the current rates. Use **Max products** to cap the cost of any run.

#### Is it legal to scrape 24S?

This actor collects only publicly available catalog data. You are responsible for how you use it: follow 24S's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product names, prices and stock are generally facts, but brand names, photos and descriptions 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 run then returns only new, updated and reappeared products, and unchanged ones are not billed unless you turn on **Emit unchanged**.

#### What is the difference between Resume and Incremental mode?

**Resume** continues one specific interrupted run: paste that run's ID and this run skips everything it already collected. **Incremental mode** is for running the same search again and again on a schedule and getting only what changed each time. Using both together seeds the first incremental baseline from the resumed run so those products are not reported as new the next day; this works only before the search has any saved incremental state, otherwise the run stops and asks you to remove Resume or pick a new State key.

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

If 24S refuses or redirects every request for a category or pasted URL, the run stops with a clear message so "no products in this category" is never confused with "the page could not be read". Run it again in a few minutes. If only some categories or URLs could be read, you still get what was found, along with a note about what is missing.

#### 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 fashion data?

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

<table>
<tr><td>👗 <a href="https://apify.com/abotapi/mango-com-scraper"><b>Mango Scraper</b></a><br>Scrape Mango (shop.mango.com) fashion products: current price plus strike-through Rebajas...</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/elcorteingles-es-scraper"><b>El Corte Inglés Scraper</b></a><br>Scrape El Corte Inglés elcorteingles.es products across fashion, electronics, home...</td><td>👗 <a href="https://apify.com/abotapi/fashionnova-com-scraper"><b>Fashion Nova Scraper</b></a><br>Scrape Fashion Nova products by keyword, collection or URL. Extract product names...</td></tr>
<tr><td>🏷️ <a href="https://apify.com/abotapi/thredup-scraper"><b>ThredUp Scraper</b></a><br>Scrape ThredUp resale listings by keyword, department, brand, size, condition, price or...</td><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></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/24s-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`):

How to find products to scrape. 'search' builds catalog pages from categories + filters; 'url' scrapes category or product page links you paste.

## `locale` (type: `string`):

24S market in the form lang-country: de-de, fr-fr, or en-<market> for gb, us, au, fr, it, es, nl, be, ch, de, jp, se, dk, hk, pt, at, sg, ie, ca, kr, cn, ae, no, fi, pl (for example en-gb, en-us, en-au). Any other value is ignored with a warning and en-gb is used. The backup residential exit is matched to this market's country. Category names must be in the locale's language (en-\* uses women, shoes, bags, ready-to-wear).

## `country` (type: `string`):

Optional ISO-2 market code: gb (or uk), us, au, fr, it, es, nl, be, ch, de, jp, se, dk, hk, pt, at, sg, ie, ca, kr, cn, ae, no, fi, pl. Shortcut for the Market / locale field: gb -> en-gb, de -> de-de; every other code uses the English storefront en-xx, because those markets redirect or have no storefront under their own language. Any other code is ignored with a warning. Only applies while Market / locale is left at en-gb; an explicit locale always wins.

## `categories` (type: `array`):

Category paths to scrape (search mode). Format universe/category\[/subcategory], e.g. 'women/shoes', 'women/bags', 'women/ready-to-wear', 'women/shoes/boots-ankle-boots/ankle-boots'. Use a category path, not a bare universe such as 'women': the universe landing page is editorial and lists no products. 24S no longer runs a separate menswear universe, so 'men/...' paths redirect away and return nothing. Defaults to 'women/shoes' so a run started with no input still returns real results. You may also paste full category page URLs (https://www.24s.com/en-gb/women/shoes); the market is taken from the URL.

## `brands` (type: `array`):

Filter by brand. Use the exact brand name as shown on 24S, e.g. 'CHLOE', 'LOEWE', 'BOTTEGA VENETA', 'LOUIS VUITTON', 'CELINE'. Leave empty for all brands.

## `colors` (type: `array`):

Filter by color, e.g. 'Black', 'Beige', 'Brown', 'Blue'. Leave empty for all colors.

## `sizes` (type: `array`):

Filter by size in 24S 'FR NN' notation, e.g. 'FR 38' (shoes) or 'FR 36' (clothing). Leave empty for all sizes.

## `minPrice` (type: `integer`):

Minimum price in the locale's currency (whole units). Leave empty for no minimum.

## `maxPrice` (type: `integer`):

Maximum price in the locale's currency (whole units). Leave empty for no maximum.

## `discounts` (type: `array`):

Show only discounted items at or above these discount buckets. Valid values: 20, 30, 40, 50. Leave empty to include full-price items.

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

Show only items currently on sale. 24S has no separate sale/outlet category or collection (verified: does not exist as a page); this checks every discount bucket at once. Ignored if you already picked specific buckets above.

## `sortBy` (type: `string`):

Result ordering (search mode).

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

24S category or product page URLs to scrape (url mode). Category URLs paginate forward; product URLs are fetched as single detail records. Filter fields are ignored in this mode (use the filters already in the pasted URL). Accepted shapes: category, nested subcategory, colour or brand page, ?page=N (starts at that page), ?sort=/brands= query, product page (slug_SKU), any locale, trailing slash, locale-less legacy path (uses the Market/locale input). Bare department pages and old /men/ links are skipped with a warning, never charged. Paste a category page such as https://www.24s.com/en-gb/women/shoes rather than a bare department landing page such as https://www.24s.com/en-gb/women, which is editorial and carries no product listing. 24S no longer runs a separate menswear universe, so old /men/ links redirect away and return nothing.

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

Add the full product-detail fields to every result: long description, bullet points, composition, made-in, product code and the complete image gallery. Adds one request per product.

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

Maximum number of products to scrape across all categories/URLs. Set 0 for unlimited.

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

Optional safety cap on pages walked per category/URL (72 products per page). Leave empty for no page limit; the run stops at Max products.

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

The default Apify proxy pool is used first; if the site refuses it twice in a row, the run switches to a residential exit matched to the market's country (needs residential access). You can also pick a proxy group explicitly.

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

Paste a previous run ID or dataset ID to continue a large crawl of products without returning or charging for products already collected there. Use this after an interrupted run, or when continuing a product catalogue pull in another run. For recurring daily monitoring of the same search, 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. Turn on "Emit unchanged" or "Emit expired" only when you also want those products returned (and billed). State is kept separately for each locale/category/URL and filter/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 locale/category/URL and filter 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 — 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 in incremental mode, for example "price" or "availability". A product whose only differences are in these fields is treated as UNCHANGED, so it is not returned or billed as UPDATED. Names match at any nesting depth. The fields still appear in the output of rows that are returned.

## `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",
  "locale": "en-gb",
  "categories": [
    "women/shoes"
  ],
  "specialsOnly": false,
  "sortBy": "relevance",
  "urls": [
    "https://www.24s.com/en-gb/women/shoes",
    "https://www.24s.com/en-gb/women/shoes/ballet-pumps",
    "https://www.24s.com/en-gb/women/shoes/boots-ankle-boots/chelsea",
    "https://www.24s.com/en-gb/women/bags/handbags/totes-shoppers",
    "https://www.24s.com/en-gb/women/shoes/black",
    "https://www.24s.com/en-gb/women/bags/bestsellers",
    "https://www.24s.com/en-gb/women/brands/celine",
    "https://www.24s.com/en-gb/women/shoes?page=2",
    "https://www.24s.com/en-gb/women/shoes?brands=CELINE&orderBy=price_asc",
    "https://www.24s.com/en-gb/women/shoes?discounts=30&minPrice=10000",
    "https://www.24s.com/en-gb/women/shoes?brands=CELINE&brands=LOEWE&colors=Black&shoeSizes=FR%2038",
    "https://www.24s.com/en-gb/women/shoes?brands=LOEWE&page=2",
    "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1?color=beige",
    "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1",
    "https://www.24s.com/en-us/women/shoes",
    "https://www.24s.com/fr-fr/femme/chaussures",
    "https://www.24s.com/women/bags",
    "https://www.24s.com/en-gb/women",
    "https://www.24s.com/en-gb/men/shoes"
  ],
  "fetchDetails": false,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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",
    "categories": [
        "women/shoes"
    ],
    "urls": [
        "https://www.24s.com/en-gb/women/shoes",
        "https://www.24s.com/en-gb/women/shoes/ballet-pumps",
        "https://www.24s.com/en-gb/women/shoes/boots-ankle-boots/chelsea",
        "https://www.24s.com/en-gb/women/bags/handbags/totes-shoppers",
        "https://www.24s.com/en-gb/women/shoes/black",
        "https://www.24s.com/en-gb/women/bags/bestsellers",
        "https://www.24s.com/en-gb/women/brands/celine",
        "https://www.24s.com/en-gb/women/shoes?page=2",
        "https://www.24s.com/en-gb/women/shoes?brands=CELINE&orderBy=price_asc",
        "https://www.24s.com/en-gb/women/shoes?discounts=30&minPrice=10000",
        "https://www.24s.com/en-gb/women/shoes?brands=CELINE&brands=LOEWE&colors=Black&shoeSizes=FR%2038",
        "https://www.24s.com/en-gb/women/shoes?brands=LOEWE&page=2",
        "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1?color=beige",
        "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1",
        "https://www.24s.com/en-us/women/shoes",
        "https://www.24s.com/fr-fr/femme/chaussures",
        "https://www.24s.com/women/bags",
        "https://www.24s.com/en-gb/women",
        "https://www.24s.com/en-gb/men/shoes"
    ],
    "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/24s-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",
    "categories": ["women/shoes"],
    "urls": [
        "https://www.24s.com/en-gb/women/shoes",
        "https://www.24s.com/en-gb/women/shoes/ballet-pumps",
        "https://www.24s.com/en-gb/women/shoes/boots-ankle-boots/chelsea",
        "https://www.24s.com/en-gb/women/bags/handbags/totes-shoppers",
        "https://www.24s.com/en-gb/women/shoes/black",
        "https://www.24s.com/en-gb/women/bags/bestsellers",
        "https://www.24s.com/en-gb/women/brands/celine",
        "https://www.24s.com/en-gb/women/shoes?page=2",
        "https://www.24s.com/en-gb/women/shoes?brands=CELINE&orderBy=price_asc",
        "https://www.24s.com/en-gb/women/shoes?discounts=30&minPrice=10000",
        "https://www.24s.com/en-gb/women/shoes?brands=CELINE&brands=LOEWE&colors=Black&shoeSizes=FR%2038",
        "https://www.24s.com/en-gb/women/shoes?brands=LOEWE&page=2",
        "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1?color=beige",
        "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1",
        "https://www.24s.com/en-us/women/shoes",
        "https://www.24s.com/fr-fr/femme/chaussures",
        "https://www.24s.com/women/bags",
        "https://www.24s.com/en-gb/women",
        "https://www.24s.com/en-gb/men/shoes",
    ],
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/24s-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",
  "categories": [
    "women/shoes"
  ],
  "urls": [
    "https://www.24s.com/en-gb/women/shoes",
    "https://www.24s.com/en-gb/women/shoes/ballet-pumps",
    "https://www.24s.com/en-gb/women/shoes/boots-ankle-boots/chelsea",
    "https://www.24s.com/en-gb/women/bags/handbags/totes-shoppers",
    "https://www.24s.com/en-gb/women/shoes/black",
    "https://www.24s.com/en-gb/women/bags/bestsellers",
    "https://www.24s.com/en-gb/women/brands/celine",
    "https://www.24s.com/en-gb/women/shoes?page=2",
    "https://www.24s.com/en-gb/women/shoes?brands=CELINE&orderBy=price_asc",
    "https://www.24s.com/en-gb/women/shoes?discounts=30&minPrice=10000",
    "https://www.24s.com/en-gb/women/shoes?brands=CELINE&brands=LOEWE&colors=Black&shoeSizes=FR%2038",
    "https://www.24s.com/en-gb/women/shoes?brands=LOEWE&page=2",
    "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1?color=beige",
    "https://www.24s.com/en-gb/adam-loafers-in-suede-calfskin-celine_CELJJQWUBE1",
    "https://www.24s.com/en-us/women/shoes",
    "https://www.24s.com/fr-fr/femme/chaussures",
    "https://www.24s.com/women/bags",
    "https://www.24s.com/en-gb/women",
    "https://www.24s.com/en-gb/men/shoes"
  ],
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/24s-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/24s-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/l5dZQog97tkuswtWw/builds/9CDtyCKsyHWlHxajw/openapi.json
