# SSENSE Scraper - Products, Sale & Retail Prices (`abotapi/ssense-product-scraper`) Actor

Scrape SSENSE by keyword, category, designer or URL. Every row carries the selling price and the regular price, the discount percent, stock state and images. Sale axes, designer pages and recurring change tracking are first-class.

- **URL**: https://apify.com/abotapi/ssense-product-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.70 / 1,000 product records

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

## SSENSE Scraper: Products, Sale & Retail Prices

SSENSE Scraper turns the SSENSE luxury storefront into a clean product feed. Search by keyword, browse the men's or women's catalogue with category, designer and sale facets, or paste store URLs to walk them directly. Every row carries the current selling price and the regular price together, with the discount percent computed, and adds the product description when you switch it on. Export to JSON, CSV or Excel, or pull the results straight into your app through the API.

### Why This Scraper?

- **The full price pair on every row.** Selling price and regular price come from the listing page itself, with the discount percent computed, so retail versus sale is on every record without a second request.
- **Four ways to scope a run.** Search by keyword, browse a section, category or designer, watch the sale axis, or paste store URLs directly.
- **The sale axis is first class.** Sale only, or a pasted sale URL, rides the store's own sale pages, including their category and designer combinations.
- **Product details on demand.** Turn on Fetch product details for the description, the product type keyword, the full image gallery, per-size name, SKU and stock state, composition and country of origin; the price pair, stock state and the main image (`imageUrl`) are on every row either way.
- **Built for recurring monitoring.** Incremental mode classifies every product as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against the last run, and a refused run fails loudly instead of returning an empty dataset.
- **Resume without paying twice.** Continue one interrupted run by its run or dataset id, and the actor skips everything it already collected there.
- **Client-side price and sort controls.** Narrow by price range or discounted rows only, then order the rows this run collected by price or discount.

### Use Cases

- **Price and discount monitoring:** track the sale section or specific designers on a schedule, and get only the price moves and new markdowns.
- **Resale and reseller pricing research:** compare SSENSE retail and sale prices against resale platforms for the same designers and styles.
- **Assortment and catalogue analysis:** map which designers, categories and genders make up the storefront, with stock state per product.
- **Fashion trend and content research:** pull product names, designers and images to track what a luxury retailer stocks each season.
- **Deal and drop alerting:** watch a designer or category for restocks and new markdowns with Incremental mode.

### Data You Get

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

| Field | Example |
| --- | --- |
| `recordId` / `productId` | `"10000001"` (the store's own product id, stable across runs) |
| `rowType` | `"product"` |
| `title` | `"Sample Name Wool Coat"` |
| `brand` / `brandId` | `"Sample Designer"` / `"909"` |
| `sku` | `"000000S00000"` |
| `gender` | `"men"` (also `"women"`) |
| `category` | `"coats"` (the product type keyword, with Fetch product details on) |
| `categoryIds` | `["3", "178"]` (the store's own category ids) |
| `price` / `regularPrice` | `890` / `1290` |
| `onSale` / `discountPercent` | `true` / `31.0` |
| `currency` | `"USD"` |
| `inStock` | `true` |
| `imageUrl` / `url` | product image and product page |
| `description` | product description (with Fetch product details on) |
| `images` | full product gallery, store order (with Fetch product details on) |
| `sizes` | per size `name`, `sku`, `inStock` (with Fetch product details on) |
| `composition` / `countryOfOrigin` | material text and the made-in country (with Fetch product details on) |
| `detailCarriedForward` | `true` when a failed product page fetch reused the previous run's description and category |
| `scrapedAt` | `"2026-01-01T00:00:00Z"` |
| `changeType` | `"NEW"` (also `"UPDATED"`, `"UNCHANGED"`, `"REAPPEARED"`, `"EXPIRED"`, incremental mode only) |
| `changedFields` | `["price"]` (incremental mode, on an `UPDATED` row) |
| `firstSeenAt` / `lastSeenAt` | incremental mode change tracking timestamps |

#### Output views and run summary

The dataset has three views: **Overview** (price pair, stock, link), **Detail** (description, gallery, sizes, composition, origin) and **Changes** (change type, changed fields, first and last seen). Each run also saves an `OUTPUT` record in the key-value store with the total records, per-scope counts and whether the run was blocked or failed.

### How to Use

1. Pick a **mode**: `search` (by keyword, or by browsing a section, category, designer or the sale axis) or `url` (paste store links).
2. Fill in the fields for that mode, and narrow with the price, discount and sort filters if you want.
3. Set **Max items** (and, optionally, **Max pages per source**) to control run size and cost, then click **Start**.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search by keyword:**

```json
{
  "mode": "search",
  "searchTerms": ["sneakers"],
  "maxItems": 20
}
```

**Browse the women's sale section, discounted rows only:**

```json
{
  "mode": "search",
  "gender": "women",
  "saleOnly": true,
  "onSaleOnly": true,
  "maxItems": 50
}
```

**Browse specific designers:**

```json
{
  "mode": "search",
  "designerSlugs": ["balenciaga", "rick-owens"],
  "maxItems": 30
}
```

**Paste a store URL:**

```json
{
  "mode": "url",
  "urls": ["https://www.ssense.com/en-us/men/sneakers"],
  "fetchDetails": true
}
```

#### URL shapes

| Shape | Example |
| --- | --- |
| Category | `https://www.ssense.com/en-us/men/sneakers` |
| Section (men) | `https://www.ssense.com/en-us/men` |
| Section (women) | `https://www.ssense.com/en-us/women` |
| Women category | `https://www.ssense.com/en-us/women/bags` |
| Designer | `https://www.ssense.com/en-us/men/designers/balenciaga` |
| Sale section | `https://www.ssense.com/en-us/men/sale` |
| Sale and category | `https://www.ssense.com/en-us/men/sale/sneakers` |
| Start from a page | `https://www.ssense.com/en-us/men/sneakers?page=2` |
| Search inside a section | `https://www.ssense.com/en-us/men/sneakers?q=nike` |
| Product | `https://www.ssense.com/en-us/men/product/salvatore-ferragamo/white-gancini-sneakers/19403311` |
| Bare product id | `19403311` |

URL mode behaviour change: a URL mode run with the `urls` field left untouched now scrapes one example of each shape above instead of nothing. Only the `en-us` storefront is supported: a locale-less path or another locale is scraped from `en-us` with a warning in the log, and a `/search?q=` path is not a store page and is skipped with a warning.

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/ssense-product-scraper").call(run_input={"mode": "search", "searchTerms": ["sneakers"], "maxItems": 20})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["title"], product["price"], product["regularPrice"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/ssense-product-scraper').call({ mode: 'search', searchTerms: ['sneakers'], 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 `maxItems` and `maxPages` shape a run

`maxItems` is the single cap on a run: it stops after that many records, counted across every search term, designer and URL. The budget is shared out evenly between those sources, so a source that runs out of results early can leave the run below `maxItems`. `maxPages` is an optional extra safety bound on how many result pages the run may walk per source; leave it at `0` for no page limit, and the run then stops at `maxItems`, not here.

#### Notes on scope

- A search term is never combined with a designer facet in one request; the store refuses that combination, so a designer scope walks the designer's full page instead.
- A designer slug the store does not know would silently redirect to the full catalogue. The actor detects that redirect, refuses the page, and fails the run loudly rather than returning a wider scope than you asked for.
- In URL mode, a pasted URL decides its own scope: the price, discount and sort filters still narrow what the run keeps, while the category, designers and sale only inputs are search mode only. Add `?page=3` to a browse URL to start from that page.
- Prices are quoted in the currency of the market you pick under Country (default US, US dollars) or of a pasted `en-xx` URL; the connection country does not change the currency. Every row states its own currency. The minimum and maximum price filters compare against that number as is, so choose the Country whose currency you filter in.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset id and the actor skips everything already collected there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same scope, for example a daily sale watch. Each record is classified `NEW`, `UPDATED` (with `changedFields`, and a price move counts as a change), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole scope, and only with `emitExpired`). `stateKey` names or shares the stored state; leave it empty and the actor derives one from the search terms, URLs and filters, so two different searches never mix state. With incremental mode off, output is exactly as before.
- For recurring runs with **Emit expired**, paste browse URLs without `?page=`, keep one State key per search, and keep Country fixed for each State key: a run that starts mid catalogue can mark products that moved to earlier pages as expired, and a currency switch (a different Country) reads as a price change. A pasted URL that starts at `?page=2` or later is a partial scan, so it never produces expired records.

### 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 record, 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 record 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 search or browse) or `url` (paste store URLs). |
| `searchTerms` | array | `["sneakers"]` | Search mode: one or more terms to search the store for. Leave empty to browse a section, category or designer instead. |
| `urls` | array | one example of each shape (below) | URL mode: store product, browse, category, designer or sale URLs to paste. |
| `gender` | string | `men` | Storefront section. Applies in both modes. |
| `category` | string | (none) | Search mode only: only browse this category slug. |
| `designerSlugs` | array | (none) | Search mode only: only browse these designer slugs. |
| `saleOnly` | boolean | `false` | Search mode only: browse the sale section only. |
| `minPriceUsd` | integer | (none) | Keep only rows priced at or above this value, compared in the row's own currency, set by Country (US dollars on the default US market). Applies in both modes. |
| `maxPriceUsd` | integer | (none) | Keep only rows priced at or below this value, compared in the row's own currency, set by Country (US dollars on the default US market). Applies in both modes. |
| `onSaleOnly` | boolean | `false` | Keep only rows with a discount. Applies in both modes. |
| `sortResultsBy` | string | `site_order` | Order this run's rows by `site_order`, `price_asc`, `price_desc`, or `discount_desc`. |
| `siteSort` | string | `site_default` | Ask the store itself to order pages: `site_default` (latest arrivals), `price_asc`, `price_desc`, `discount_desc`, `discount_asc`. Decides which rows fit under Max items. |
| `countryCode` | string | `US` | One of 43 English-storefront markets (for example `GB`, `JP`, `AU`); sets the currency and prices of every row. Default US is unchanged. |
| `fetchDetails` | boolean | `false` | Fetch each product's page for the description, the product type keyword, the full image gallery, per-size SKU and stock state, composition and country of origin. Charged once per record; the price pair, stock state and the main image (`imageUrl`) are on every row either way. |
| `maxItems` | integer | `20` | Stop after this many records across all sources (`0` = unlimited). |
| `maxPages` | integer | `0` | Safety bound on result pages walked per source (`0` = no limit; `maxItems` still applies). |
| `resumeFromRunId` | string | (none) | Continue one interrupted run by its run or dataset id. |
| `incrementalMode` | boolean | `false` | Return only new and changed records on scheduled runs over the same scope. |
| `stateKey` | string | (none) | Name or share an incremental-mode state; derived automatically from the scope when empty. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) unchanged records. |
| `emitExpired` | boolean | `false` | Also return (and bill) expired records, once a run has fully scanned the tracked scope. |
| `ignoreFieldsForChanges` | array | `[]` | Extra field names (for example `imageUrl` or `title`) that should not make a product count as `UPDATED` in incremental mode. The detail only fields `images`, `sizes`, `composition` and `countryOfOrigin` are always left out of change detection (output only, they cannot be opted back in, and a dotted path inside `sizes` has no effect), so a restock shows through the product level `inStock` only. Ignored fields are still returned. Price, sale and stock fields are watched by default. |
| `proxy` | object | Apify Proxy | Connection settings. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which record pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on records written to each connector per run. |

### Output Example

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

```json
{
  "recordId": "10000001",
  "rowType": "product",
  "productId": "10000001",
  "url": "https://www.example.com/en-us/men/product/sample-designer/sample-name-wool-coat/10000001",
  "title": "Sample Name Wool Coat",
  "brand": "Sample Designer",
  "brandId": "909",
  "sku": "000000S00000",
  "gender": "men",
  "category": "coats",
  "categoryIds": ["3", "178"],
  "price": 890,
  "regularPrice": 1290,
  "onSale": true,
  "discountPercent": 31.0,
  "currency": "USD",
  "inStock": true,
  "imageUrl": "https://example.com/images/sample-coat.jpg",
  "description": "Sample flannel coat with a relaxed fit.",
  "scrapedAt": "2026-01-01T00:00:00Z"
}
```

With Incremental mode on, rows also carry `changeType`, `changedFields`, `firstSeenAt` and `lastSeenAt`; a failed product page repair adds `detailCarriedForward`.

### Plan Requirement

The default Apify Proxy setting works; no residential proxy is needed. Measured on the default pool, the store's pages loaded for the browse, category, designer, sale, search-in-section and product shapes. The store sits behind a browser check that refuses ordinary clients on every proxy group, so the actor presents itself as a regular browser, and it rotates connections automatically when one is refused. Residential access (pick it under Proxy & connection) gives more headroom for large or frequent runs, but a single residential exit can occasionally be challenged, so it is not required and not more reliable by default.

What you may see in the log and run status:

- On a free plan the residential connection is refused. The log shows a boxed warning ("The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable.") and, once a backup connection serves data, "Served over the backup connection (the default connection was unavailable)."
- If every connection is refused for the account, the run fails with "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".
- If a free plan's backup connection cannot load the pages either, the run fails with "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 SSENSE pages."
- For any other run where no page loaded, the run fails with "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search."

A product page that takes longer than 25 seconds is given up on rather than stalling the run.

### FAQ

#### How much does it cost?

You pay a small start charge and per product record returned, plus the product details charge (description, gallery, sizes, composition, origin) only when Fetch product details is on, once per delivered record. The **Pricing** tab shows the current rates. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape SSENSE?

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

#### Can I track only new or changed products on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only new and updated records (a price move counts as an update), and unchanged ones are not billed unless you turn on Emit unchanged.

#### Why did URL mode return more or fewer rows than I expected?

A pasted product URL always returns exactly one record. A pasted browse, category, designer or sale URL is walked page by page like a search, and the price, discount and sort filters still narrow what the run keeps; the category, designers and sale only inputs do not apply, because the pasted URL already decides that scope.

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

If the store refuses every request, or a designer slug it does not know silently redirects to the full catalogue, the run stops with a clear message so "nothing matched" is never confused with "nothing could be read". Run it again in a few minutes, or check the Proxy configuration.

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

### 🔗 More scrapers you might like

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

<table>
<tr><td>🧩 <a href="https://apify.com/abotapi/grailed-marketplace-scraper"><b>Grailed Scraper</b></a><br>Scrape Grailed by keyword, category, designer, condition, size or URL. Extract prices and...</td><td>🛒 <a href="https://apify.com/abotapi/therealreal-scraper"><b>The RealReal Scraper</b></a><br>Scrape luxury consignment listings from therealreal.com. Browse by designer, category or...</td></tr>
<tr><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><td>👗 <a href="https://apify.com/abotapi/vogue-com-scraper"><b>Vogue Scraper</b></a><br>Scrape Vogue fashion, beauty and culture articles with full text, runway shows, look...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/miravia-es-scraper"><b>Miravia Spain Scraper</b></a><br>Scrape Miravia Spain by keyword, seller store or URL. Every row carries the selling price...</td><td>🧩 <a href="https://apify.com/abotapi/asos-com-scraper"><b>ASOS Scraper</b></a><br>Scrape ASOS by keyword, category or URL. Every row carries the selling price and the...</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/ssense-product-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 start the scrape. 'search' runs store searches. 'url' processes the store URLs you paste: a product URL is fetched as a single product, and a browse, category, designer or sale URL is paged like a search, its own path deciding the scope. The price and ordering filters below apply in BOTH modes; the scope filters (category, designers, sale only) apply in search mode only.

## `searchTerms` (type: `array`):

One or more things to search the store for, for example 'sneakers', 'wool coat', 'leather bag'. Each term is scraped independently. Search mode only: in URL mode the scope is read out of each pasted store URL instead. Leave this empty and the run browses the section, category or designer picked below, narrowed by the filters.

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

Paste store product URLs (https://www.ssense.com/en-us/men/product/designer/name/123456), browse URLs (https://www.ssense.com/en-us/men), category URLs (https://www.ssense.com/en-us/men/sneakers), designer URLs (https://www.ssense.com/en-us/men/designers/designer-name) or sale URLs (https://www.ssense.com/en-us/men/sale). Add ?page=3 to any browse URL to start walking from that page instead of the first. A pasted URL decides its own scope: the price and ordering filters below still narrow what the run keeps, the section filter fills in only when the URL does not name a section of its own, and the scope filters (category, designers, sale only) are search mode only. A pasted product URL is the one exception: it returns that single product in full. Left untouched, URL mode scrapes one example of each supported page shape. A bare numeric product id (for example 19403311) is accepted as well. English storefronts of every supported market (en-gb, en-jp, ...) are kept; other locales and locale-less paths are scraped from the market chosen in Country with a warning.

## `gender` (type: `string`):

Which storefront section to browse. Applies in BOTH search mode and URL mode: search mode sends it with every request, and in URL mode it fills in only when a pasted URL does not name a section of its own.

## `category` (type: `string`):

Only browse this category, as the slug the store itself uses in the URL, for example 'sneakers', 'coats', 't-shirts', 'bags'. The store has around a hundred of these; the slug is the part of a category page URL right after the section. Leave empty for every category. Search mode ONLY: in URL mode the pasted URL decides its own scope.

## `designerSlugs` (type: `array`):

Only browse these designers, as the slug the store itself uses in the URL, for example 'balenciaga', 'rick-owens', 'the-north-face'. The slug is the part of a designer page URL after /designers/. Each designer is scraped as its own scope; a search term is never combined with a designer in one request, because the store refuses that combination. Search mode ONLY: in URL mode the pasted URL decides its own scope.

## `saleOnly` (type: `boolean`):

Browse the sale section only, which is the store's own sale axis (the same pages its sale menu links to). Search mode ONLY: in URL mode the pasted URL decides its own scope, so paste a sale URL to walk the sale section there.

## `minPriceUsd` (type: `integer`):

Only keep rows whose selling price is at least this number, compared to the row's price in the selected market's currency (US dollars on the default US market, pounds for GB, yen for JP). The store has no server side filter for this, so it is applied to the rows this run reads. Applies in BOTH search mode and URL mode.

## `maxPriceUsd` (type: `integer`):

Only keep rows whose selling price is at most this number, compared to the row's price in the selected market's currency (US dollars on the default US market, pounds for GB, yen for JP). The store has no server side filter for this, so it is applied to the rows this run reads. Applies in BOTH search mode and URL mode.

## `onSaleOnly` (type: `boolean`):

Only keep rows whose selling price is below the regular price, that is rows with a discount. The store has no server side parameter for this outside its sale section, so it is applied to the rows this run reads. For full sale coverage use Sale only above. Applies in BOTH search mode and URL mode.

## `sortResultsBy` (type: `string`):

Arranges the rows this run collected, after they are read. This is a local tidy up of one run's output, not a catalogue wide ordering. Applies in BOTH search mode and URL mode.

## `siteSort` (type: `string`):

Asks the store itself to order every page (a catalogue wide ordering, applied before rows are read, so it decides WHICH rows fit under Max items). Latest arrivals is the store default. Applies to browse and search pages in both modes; a pasted product URL is unaffected. Combine with Order the returned rows by only if you want a second local tidy up. Applies in BOTH search mode and URL mode.

## `countryCode` (type: `string`):

Which SSENSE market to read (English storefront). It sets the currency and prices of every row: for example GB returns GBP, JP returns JPY. The default US returns USD exactly as before. The price range filters below compare against the row's price in the market currency. A pasted URL that already names a supported English market keeps it. Applies in BOTH search mode and URL mode.

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

Fetch each item's product page for the description, the product type keyword, the full image gallery, per-size name, SKU and stock state, composition and country of origin. Slower, and charged once per record. Leave off for a fast crawl: identity, prices, discount, stock state and the main image (imageUrl) are included either way.

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

The single cap on this run: stop after collecting this many records across all search terms, designers and URLs. Set 0 for unlimited.

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

Safety bound on how many result pages to walk per search term, designer or URL. Leave empty (0) for no page limit: the run then stops at Max items, not here. Does not impose a separate cap below Max items.

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

Leave the default for the cheapest run. Change it only if a run reports that it could not read any results. Prices are quoted in the currency of the selected Country (market), not of the connection; every row states its own currency.

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

Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for records already collected there. Use this after an interrupted or capped run. For recurring monitoring of the same search, use Incremental mode below instead.

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

Turn this on for daily or weekly recurring monitoring of the same search, for example a sale watch. The first run returns everything matching as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Price moves ARE reported as UPDATED: on a store they are the signal, not noise. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately per search, URL and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `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 search terms, URLs and filters, so two different searches never mix state.

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

Off by default. Turn on to also return records 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 a full snapshot every run.

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

Off by default. Turn on to also return records 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 items capped it, not when Resume was used, and not when the run was refused. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

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

Extra output field names that should NOT make a product count as UPDATED, for example imageUrl or title. Price, sale and stock fields are watched by default because a price move is the signal. The detail only fields images, sizes, composition and countryOfOrigin are ALWAYS left out of change detection (they are output only, and cannot be opted back in); a restock still shows through the product level inStock. Use top level field names such as imageUrl or title: the only nested field, sizes, is excluded as a whole, so a dotted path inside it has no effect. Ignored fields are still returned in the output.

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

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a page per record; other connectors get a best-effort write or digest. Each connector receives a condensed summary per record, not the full record; the complete record always stays in the dataset. Leave empty to skip; this never changes the dataset output. 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 record pages are created. Required to enable the Notion export; ignored by other connectors.

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

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

## Actor input object example

```json
{
  "mode": "search",
  "searchTerms": [
    "sneakers"
  ],
  "urls": [
    "https://www.ssense.com/en-us/men/sneakers",
    "https://www.ssense.com/en-us/men",
    "https://www.ssense.com/en-us/women",
    "https://www.ssense.com/en-us/women/bags",
    "https://www.ssense.com/en-us/men/designers/balenciaga",
    "https://www.ssense.com/en-us/men/sale",
    "https://www.ssense.com/en-us/men/sale/sneakers",
    "https://www.ssense.com/en-us/men/sneakers?page=2",
    "https://www.ssense.com/en-us/men/sneakers?q=nike",
    "https://www.ssense.com/en-us/men/product/salvatore-ferragamo/white-gancini-sneakers/19403311"
  ],
  "gender": "men",
  "saleOnly": false,
  "onSaleOnly": false,
  "sortResultsBy": "site_order",
  "siteSort": "site_default",
  "countryCode": "US",
  "fetchDetails": true,
  "maxItems": 20,
  "maxPages": 0,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (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",
    "searchTerms": [
        "sneakers"
    ],
    "urls": [
        "https://www.ssense.com/en-us/men/sneakers",
        "https://www.ssense.com/en-us/men",
        "https://www.ssense.com/en-us/women",
        "https://www.ssense.com/en-us/women/bags",
        "https://www.ssense.com/en-us/men/designers/balenciaga",
        "https://www.ssense.com/en-us/men/sale",
        "https://www.ssense.com/en-us/men/sale/sneakers",
        "https://www.ssense.com/en-us/men/sneakers?page=2",
        "https://www.ssense.com/en-us/men/sneakers?q=nike",
        "https://www.ssense.com/en-us/men/product/salvatore-ferragamo/white-gancini-sneakers/19403311"
    ],
    "gender": "men",
    "fetchDetails": true,
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/ssense-product-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",
    "searchTerms": ["sneakers"],
    "urls": [
        "https://www.ssense.com/en-us/men/sneakers",
        "https://www.ssense.com/en-us/men",
        "https://www.ssense.com/en-us/women",
        "https://www.ssense.com/en-us/women/bags",
        "https://www.ssense.com/en-us/men/designers/balenciaga",
        "https://www.ssense.com/en-us/men/sale",
        "https://www.ssense.com/en-us/men/sale/sneakers",
        "https://www.ssense.com/en-us/men/sneakers?page=2",
        "https://www.ssense.com/en-us/men/sneakers?q=nike",
        "https://www.ssense.com/en-us/men/product/salvatore-ferragamo/white-gancini-sneakers/19403311",
    ],
    "gender": "men",
    "fetchDetails": True,
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/ssense-product-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",
  "searchTerms": [
    "sneakers"
  ],
  "urls": [
    "https://www.ssense.com/en-us/men/sneakers",
    "https://www.ssense.com/en-us/men",
    "https://www.ssense.com/en-us/women",
    "https://www.ssense.com/en-us/women/bags",
    "https://www.ssense.com/en-us/men/designers/balenciaga",
    "https://www.ssense.com/en-us/men/sale",
    "https://www.ssense.com/en-us/men/sale/sneakers",
    "https://www.ssense.com/en-us/men/sneakers?page=2",
    "https://www.ssense.com/en-us/men/sneakers?q=nike",
    "https://www.ssense.com/en-us/men/product/salvatore-ferragamo/white-gancini-sneakers/19403311"
  ],
  "gender": "men",
  "fetchDetails": true,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false
}' |
apify call abotapi/ssense-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/ssense-product-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/yM50oDq0nepN5fTnb/builds/RwopDqsPKSQ3LmXbu/openapi.json
