# SSENSE Product Scraper – Designer Prices, Sizes & Stock (`rl1987/ssense-api-scraper`) Actor

Scrape SSENSE designer fashion products by keyword or by any of ~190 categories, for men or women. One row per product: brand, name, category, regular and sale price, discount %, SKU, full-res images and URL. Add details for description, composition, country of origin and per-size stock.

- **URL**: https://apify.com/rl1987/ssense-api-scraper.md
- **Developed by:** [R.L.](https://apify.com/rl1987) (community)
- **Categories:** E-commerce
- **Features:** Limited permissions
- **Stats:** 8 total users, 5 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.54 / 1,000 product listing rows

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 Product Scraper — Designer Fashion Prices, Sizes & Stock

**Scrape SSENSE.com products, brands, prices, discounts and per-size stock at scale.** This Apify Actor extracts structured luxury fashion data from [SSENSE](https://www.ssense.com) — the Montreal retailer for designer clothing, shoes, bags and accessories — by searching a keyword or browsing any category, for men or women.

No browser automation, no HTML parsing, no CAPTCHAs. The scraper talks directly to SSENSE's own GraphQL product API and returns clean JSON you can export to Excel, CSV, JSON, or feed straight into your database, price-monitoring tool, or dashboard.

***

### What does this SSENSE scraper do?

You give it a search keyword, a category, or neither (which browses the whole department). It
returns **one row per product**: SSENSE product ID, product name, brand, category, regular price,
sale price, discount percentage, sale flag, product code, full-resolution image URLs and the
product page URL. Turn on **Include product details** and each row also carries the product
description, material composition, country of origin and the per-size stock breakdown.

- **Fast** — queries the SSENSE GraphQL API directly instead of rendering pages. 54 products per request.
- **Accurate** — structured fields straight from the source the site itself reads.
- **Reliable pagination** — cross-page deduplication and end-of-results detection, so you get the full listing without duplicates.
- **43 markets, 7 currencies** — pick the storefront country and the language separately: USD, CAD, GBP, EUR, AUD, JPY or HKD, in English, French, Japanese, Chinese or Korean. Prices, availability and product URLs all follow the market you choose.
- **Proxy ready** — routes through Apify Proxy by default.
- **Pay-per-event pricing** — you're charged per product row extracted, nothing wasted.

***

### What can you do with SSENSE data?

- **Competitor & price monitoring** — track designer prices, markdown depth and new arrivals across brands.
- **Discount tracking** — sort by discount and read `discountPercentage` / `isSale` directly.
- **Stock and size-run analysis** — with details on, every row carries how many units are left per size.
- **Product & catalog research** — build a dataset by category (sneakers, bags, dresses, jewelry, and ~190 more).
- **Resale sourcing** — find products, images and price points for reselling or market research.
- **Machine learning & trend data** — collect fashion product images and metadata for training or trend forecasting.

***

### Which brands and categories can I scrape?

**Brands** — you don't pick a brand from a list; you search for it with the **Search keyword**
field, or browse a category and filter on `brandName`. A single broad women's browse returned
**140 distinct brands** in its first 2,000 rows, including Gucci, Bottega Veneta, Burberry,
Rick Owens, Acne Studios, Dries Van Noten, LEMAIRE, Jean Paul Gaultier, Vivienne Westwood,
Simone Rocha, KHAITE, VETEMENTS, OUR LEGACY, Canada Goose, Diesel and Nike.

**Categories** — the **Category** dropdown holds SSENSE's own tree as `PARENT > Child > Grandchild`
paths, about 190 of them under four roots:

| Root | Examples of what's under it |
| --- | --- |
| `CLOTHING` | Dresses (long / mid / short), Jeans, Jackets & Coats (blazers, bombers, down, leather, trench), Sweaters (cardigans, hoodies, turtlenecks), Pants (cargo, leather, sweatpants, trousers), Shirts, Skirts, Suits & Blazers, Swimwear, Tops (blouses, polos, T-shirts, tanks), Lingerie, Activewear, Underwear & Loungewear |
| `SHOES` | Sneakers (high top / low top / wedge), Boots (ankle, Chelsea, combat, over-the-knee, wingtip), Heels, Flats, Sandals, Loafers, Lace Ups & Oxfords, Monkstraps, Espadrilles |
| `BAGS` | Backpacks, Tote Bags, Shoulder Bags, Clutches & Pouches, Messenger Bags & Satchels, Duffle & Top Handle Bags, Briefcases, Travel Bags |
| `ACCESSORIES` | Eyewear (glasses / sunglasses), Jewelry and Fine Jewelry (rings, earrings, necklaces, bracelets), Watches, Hats (beanies, caps, fedoras), Belts, Scarves, Socks, Wallets & Card Holders, Ties, Gloves, Tech (iPhone/iPad/laptop cases, headphones), Souvenirs |

> **Category ids are gender-specific.** The actor resolves your chosen path inside the selected
> gender's own tree at runtime — men's Sneakers and women's Sneakers are different ids. The Category
> dropdown lists both genders' paths, so some entries are not valid for the gender you picked
> (`SHOES > Espadrilles` is men's only; women's is `SHOES > Flats > Espadrilles`). If the path does
> not exist for the selected gender, the run stops immediately with a status message naming the
> closest valid paths — it never falls back to browsing the whole department, so a typo can't bill
> you for a full-catalogue crawl.

***

### What do the fields mean?

- **`salePrice` is `0`, not `null`, when a product is not discounted** — and `formatSale` reads `"$0"`. Use `isSale` or `discountPercentage` to tell a real markdown from a full-price item, not `salePrice`.
- **`regularPrice` / `salePrice`** are plain numbers in `currency` (USD or CAD, from your **Country** setting). `formatRegular` / `formatSale` are SSENSE's own display strings for the same values.
- **`productCode`** is SSENSE's internal SKU, e.g. `262011M236006`. It is also the filename stem of the product's images, and it is the right key to join runs on alongside `id`.
- **`sizes`** is a single semicolon-separated string, one entry per size, each either a unit count or `out-of-stock`: `US 6 = IT 39: out-of-stock; US 6.5 = IT 39.5: 5 left; US 7 = IT 40: 8 left`. Split on `; ` to parse it.
- **`countryOfOrigin`** is a lowercase ISO 3166-1 alpha-2 code, e.g. `vn`, `it`, `cn` — not a country name.
- **`composition`** is SSENSE's free-text material breakdown, e.g. `Upper: synthetic, leather. Sole: rubber.`
- **`images`** are full-resolution Cloudinary URLs (1128px wide), already expanded — not thumbnails.
- **Detail-only fields.** `description`, `composition`, `countryOfOrigin` and `sizes` exist only on SSENSE's product-detail query, so they are empty unless **Include product details** is on.
- **`sizes` carries no per-size SKU.** The string is the size label and its stock, nothing else. SSENSE does hold a SKU per size; it is not mapped into the dataset today. `productCode` is the product-level code and is on every row.

***

### Two things about this input that are easy to get wrong

**A *Specific products* run always reads the product page.** `includeDetails` is a
search/category switch. Give `productUrls` and there is no listing record to start
from — a product id can only be read from the detail query — so that path fetches
the product page whatever `includeDetails` says, and bills the listing row plus
whichever of **Include per-size stock** and **Include description and composition**
are on. Both are on by default, so a bare `{"productUrls": ["17322111"]}` bills
three events per product, not one. Switch both off and it bills one.

**`PRICE_LOW_TO_HIGH` sorts by what the product costs today, not by `regularPrice`.**
Measured on `SHOES > Sneakers` / women, 2026-11-01: the first ten rows came back with
`regularPrice` 95, 105, 100, 110, 110, 100, 105, 120, 120, 90 — which reads unsorted —
and their *discounted* prices ascend 29, 32, 33, 33, 34, 37, 38, 42, 44, 44. Sort on
`salePrice` where `isSale` is true, and on `regularPrice` where it is not.

***

### How do I scrape SSENSE? (3 steps)

1. **Set your input** — a **Search keyword**, a **Category**, or neither to browse the whole department. Choose **Gender**, **Country** and **Sort order**.
2. **Pick options** — **Include product details** for description/composition/sizes, and a `maxItems` cap.
3. **Run & export** — click **Start**, then download the dataset as JSON/CSV/Excel or fetch it via the API.

***

### What input does it take?

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `q` | string | – | Search keyword, e.g. `sneakers`, `trench coat`, or a brand name. Leave blank to browse. |
| `gender` | select | `women` | `women` or `men`. |
| `category` | select | – | Browse one of ~190 SSENSE category paths, e.g. `SHOES > Sneakers > Low Top Sneakers`. Leave blank to search or to browse the whole department. |
| `sort` | select | `LATEST_ARRIVALS` | `LATEST_ARRIVALS`, `PRICE_LOW_TO_HIGH`, `PRICE_HIGH_TO_LOW`, `DISCOUNT_HIGH_TO_LOW`, `DISCOUNT_LOW_TO_HIGH`. |
| `countryCode` | select | `US` | 43 storefronts — drives pricing, availability and the product URL. EUR: AT BE CH CY CZ DE DK EE ES FI FR GR HU IE IT LT LU LV MT NL NO PL PT SE SI SK. USD: AE BH CN KR MO MY NZ QA RU SG TW US. GBP: GB. CAD: CA. AUD: AU. JPY: JP. HKD: HK. |
| `languageCode` | select | `en` | `en`, `fr`, `ja`, `zh` or `ko` — language of product names, categories and descriptions. Works with any country. |
| `includeDetails` | boolean | `false` | Fetch each product's detail page for description, composition, country of origin and per-size stock. One extra request per product. **Search/category runs only** — see *Specific products* below. |
| `includeDescription` | boolean | `true` | Fetch `description`, `composition` and `countryOfOrigin`. Billed as its own event. |
| `includeSizes` | boolean | `true` | Fetch the per-size stock breakdown into `sizes`. Billed as its own event. |
| `productUrls` | array | – | Product ids or product-page URLs to scrape directly instead of searching. |
| `maxItems` | integer | `100` | Maximum products to return. `0` = every match, which can be tens of thousands of rows for a broad browse. |
| `proxyConfiguration` | object | Apify Proxy | Route requests through a proxy. |

#### Example input

Search men's sneakers, deepest discounts first, with full detail:

```json
{
  "q": "sneakers",
  "gender": "men",
  "sort": "DISCOUNT_HIGH_TO_LOW",
  "includeDetails": true,
  "maxItems": 200,
  "countryCode": "US",
  "languageCode": "en"
}
```

Or browse a whole category instead of searching:

```json
{
  "gender": "women",
  "category": "CLOTHING > Dresses > Long Dresses",
  "sort": "PRICE_LOW_TO_HIGH",
  "maxItems": 0
}
```

***

### What does a row look like?

Each product is one dataset row. With **Include product details** on:

```json
{
  "id": 19372441,
  "name": "Silver & Black Shox BB4 Sneakers",
  "brandName": "Nike",
  "categoryName": "High Top Sneakers",
  "gender": "men",
  "regularPrice": 185,
  "salePrice": 0,
  "currency": "USD",
  "formatRegular": "$185",
  "formatSale": "$0",
  "discountPercentage": 0,
  "isSale": false,
  "productCode": "262011M236006",
  "images": [
    "https://res.cloudinary.com/ssenseweb/image/upload/c_scale,f_auto,q_auto,w_1128/262011M236006_1.jpg",
    "https://res.cloudinary.com/ssenseweb/image/upload/c_scale,f_auto,q_auto,w_1128/262011M236006_2.jpg"
  ],
  "description": "High-top buffed faux-leather and leather sneakers.\n\n· Lace-up closure\n· Logo patch at padded tongue\n· Nike Shox units at midsole\n· Treaded rubber sole",
  "composition": "Upper: synthetic, leather. Sole: rubber.",
  "countryOfOrigin": "vn",
  "sizes": "US 6 = IT 39: out-of-stock; US 6.5 = IT 39.5: 5 left; US 7 = IT 40: 8 left; US 7.5 = IT 40.5: 6 left",
  "url": "https://www.ssense.com/en-us/men/product/nike/silver-black-shox-bb4-sneakers/19372441"
}
```

### Which fields are in the dataset?

| Field | Type | Description |
|-------|------|-------------|
| `id` | number | SSENSE product ID |
| `name` | text | Product name |
| `brandName` | text | Designer brand |
| `categoryName` | text | Leaf category name |
| `gender` | text | `men` or `women` |
| `regularPrice` | number | Regular price in `currency` |
| `salePrice` | number | Sale price; `0` when not discounted |
| `currency` | text | `USD` or `CAD` |
| `formatRegular` | text | Regular price as SSENSE displays it |
| `formatSale` | text | Sale price as SSENSE displays it |
| `discountPercentage` | number | Discount percent; `0` when not discounted |
| `isSale` | boolean | Whether the product is on sale |
| `productCode` | text | SSENSE SKU / image filename stem |
| `url` | link | Direct link to the product page |
| `images` | array | Full-resolution product image URLs |
| `description` | text | Product description *(details only)* |
| `composition` | text | Material composition *(details only)* |
| `countryOfOrigin` | text | ISO 3166-1 alpha-2 code *(details only)* |
| `sizes` | text | Per-size stock breakdown *(details only)* |

Export in JSON, CSV, Excel, XML, or RSS from the Apify dataset, or pull it via the [Apify API](https://docs.apify.com/api/v2).

***

### How much does it cost?

The current price of every event is on the **Pricing** tab of this Actor's page in Apify Store. That tab is generated from the Actor's own pricing record, so it is always current, and your plan's rung is applied automatically. A figure repeated here would be a second copy that drifts out of date.

You can cap what any single run may spend with **Max total charge**.

### How do I run it from my own code?

Schedule runs, get webhooks on finish, and pipe data into your stack. Works with the [Apify API](https://docs.apify.com/api/v2), [JavaScript SDK](https://docs.apify.com/sdk/js), [Python SDK](https://docs.apify.com/sdk/python), and [Apify integrations](https://apify.com/integrations) (Make, Zapier, Slack, Google Sheets, and more).

```bash
curl -X POST "https://api.apify.com/v2/acts/ssense-api-scraper/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"q":"sneakers","gender":"men","maxItems":200,"includeDetails":true}'
```

Or with the Apify CLI: `apify call ssense-api-scraper -i input.json -o`.

***

### Is it legal to scrape SSENSE?

This Actor collects publicly available product data. You are responsible for how you use scraped data — respect SSENSE's terms, applicable laws, and copyright on images. This tool is intended for legitimate market research, price monitoring, and analytics. See Apify's [ethical web scraping](https://blog.apify.com/is-web-scraping-legal/) guide.

***

### FAQ

**Do I need an SSENSE login or API key?**

No. The actor calls SSENSE's own GraphQL API with the mobile app's credentials — you only need an Apify account.

**Can I scrape a whole category, or the whole department?**

Yes. Set `maxItems: 0` and the actor paginates until the API says there are no more pages — 54 products per request, and in practice well past the 2,000-row mark for a broad women's browse. Set `maxItems` to a real number if you want a bounded bill.

**How do I get every product for one brand?**

Put the brand name in the **Search keyword** field. Brands are not a separate input, so for an exact set, browse the relevant category and filter your output on `brandName`.

**How do I find only discounted items?**

Sort by `DISCOUNT_HIGH_TO_LOW` and keep rows where `isSale` is `true`, or where `discountPercentage` is above your threshold. Do not test `salePrice` — it is `0`, not `null`, on full-price items.

**Which countries and currencies are supported?**

Two: `US` (prices in USD) and `CA` (prices in CAD). Language is separate — `en` or `fr`. Prices and availability follow the country you pick.

**Do I get sizes and stock levels?**

Only with **Include product details** on. Then `sizes` gives one entry per size with the units remaining or `out-of-stock`, e.g. `US 8 = IT 41: 13 left`.

**What does "Include product details" cost me in time?**

One extra API request per product, so a 1,000-product run makes roughly 1,019 requests instead of 19. It is also billed as a second event per row. Leave it off when the listing fields are enough.

**Can I schedule it?**

Yes — use Apify's scheduler for recurring runs and a webhook to push each finished dataset onward. Join runs on `id` or `productCode` to diff prices over time.

***

### Support

Found a bug or need a new field? Open an issue on the Actor page. Contributions and feature requests welcome.

### Did you find this useful?

Rate this actor on Apify! Your feedback helps other users find it and helps us keep improving it.

# Actor input Schema

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

Pick one slice and the run fetches only that, for the products the search finds. "Search" returns listing rows with no product-page request at all. The slice modes narrow the request itself, not just the output, so asking for sizes does not download descriptions you are not keeping.

## `q` (type: `string`):

Search products by keyword (e.g., 'shirt', 'dress')

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

Browse a category (leave blank to search). Category ids are gender-specific and resolved from the selected gender at runtime.

## `sort` (type: `string`):

How to sort results

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

Product gender department

## `productUrls` (type: `array`):

Scrape these products directly instead of searching: a numeric product id, or the product page URL, which ends in that id. One per line. When set, the search inputs are not used - this is the way to monitor a product you already know, rather than whatever a search happens to surface. This path always reads the product page, so it bills the listing row plus whichever of the two slices below are on.

## `includeDetails` (type: `boolean`):

Fetch each product's detail page, which is what fills `description`, `composition`, `countryOfOrigin` and `sizes`. One extra request per product, and each slice you leave on bills its own event on top of the listing row. This switch governs a SEARCH or CATEGORY run only: a run that names products in "Specific products" always fetches the product page, because a product id can only be read from there — on that path use "Include per-size stock" and "Include description and composition" to choose what is fetched and billed.

## `includeSizes` (type: `boolean`):

Every size SSENSE lists for the product, with the units left or `out-of-stock`, as one semicolon-separated string in the `sizes` column — e.g. `IT 36: 2 left; IT 37: out-of-stock`. On by default. Billed as its own `sizes-row` event, so switch it off for a description-only run and you are not charged for it.

## `includeDescription` (type: `boolean`):

Description, composition and country of origin, billed as its own `detail-row` event. On by default. Switch it off for a sizes-only request, which is what a restock monitor wants.

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

Country for pricing and availability

## `languageCode` (type: `string`):

Language for product names/descriptions

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

Maximum number of products to fetch. 0 = unlimited (can be tens of thousands of rows for a broad gender/category browse).

## `detailConcurrency` (type: `integer`):

How many product-detail requests to have in flight at once. Leave empty and it is picked from the run's memory, which is what actually bounds it. Raising it past what the memory allows gets the run killed with no traceback.

## `proxyConfiguration` (type: `object`):

Route requests through a proxy (Apify Proxy by default).

## Actor input object example

```json
{
  "mode": "search",
  "q": "",
  "sort": "LATEST_ARRIVALS",
  "gender": "women",
  "productUrls": [],
  "includeDetails": false,
  "includeSizes": true,
  "includeDescription": true,
  "countryCode": "US",
  "languageCode": "en",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "q": "",
    "productUrls": [],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rl1987/ssense-api-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 = {
    "q": "",
    "productUrls": [],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("rl1987/ssense-api-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 '{
  "q": "",
  "productUrls": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call rl1987/ssense-api-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rl1987/ssense-api-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/4NdBkbXoPPdiLnyZE/builds/nTWdFhpxPIV2oTtpQ/openapi.json
