# THE OUTNET Scraper — Discounted Designer Fashion Prices & Stock (`studio-amba/theoutnet-scraper`) Actor

Scrape theoutnet.com (YNAP's designer outlet) by search, category or brand: current price, original price, discount percentage, brand, sizes, stock, images and descriptions. 17 markets, no login, no proxy needed.

- **URL**: https://apify.com/studio-amba/theoutnet-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## THE OUTNET Scraper

Search or browse THE OUTNET (YNAP's designer fashion outlet) and get back
structured product data: current price, original price, discount percentage,
brand, size/colour, stock, images and descriptions.

### Why use this actor

THE OUTNET is an outlet — nearly everything is marked down from a full-price
list. The number that actually matters for price-monitoring, deal-alert or
resale-pricing use cases is the discount, not just the price, so this actor
always tries to give you both the current and the original price in the same
currency, and computes the percentage for you.

If you already run our [NET-A-PORTER Scraper](https://apify.com/studio-amba/net-a-porter-scraper)
or [Mytheresa Scraper](https://apify.com/studio-amba/mytheresa-scraper), this
is the outlet-side complement: same corporate family angle (YNAP), same
"designer fashion, structured output" shape, but built for a completely
different backend.

### How to scrape THE OUTNET data

1. Put one or more terms in **Search Queries** — a category (`dress`, `bag`,
   `sneakers`) or a designer name (`zimmermann`, `valentino garavani`) both
   work.
2. Pick a **Market**. `outnet_be` is Belgium in EUR; there are 17 markets and
   each has its own currency.
3. Set **Max Items** and run it.

No login, no cookies, and no proxy needed — THE OUTNET's search and product
data live behind two fully public, unauthenticated JSON APIs, and a plain
request from a normal browser user agent gets a 200 on the first try, every
time (recon: `docs/site-recon/theoutnet-com.md`).

#### Category and brand mode

Set **Category Values** to browse a category listing directly instead of
searching, e.g. `["Dresses"]`, `["Bags"]`, `["Sneakers"]`. These are
case-sensitive and must match THE OUTNET's own category label exactly.
**Category Values** takes priority over **Search Queries** when both are set.

Set **Brands** to filter either mode down to one or more designers, e.g.
`["Zimmermann"]`. This works layered on top of a search or a category browse,
so `categorySlugs: ["Dresses"], brands: ["Zimmermann"]` returns only
Zimmermann dresses.

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `searchQueries` | Array | No | One or more search terms. Default `["dress"]` |
| `searchQuery` | String | No | Single-term alternative to `searchQueries` |
| `categorySlugs` | Array | No | Browse a category facet directly, e.g. `["Dresses"]`. Case-sensitive. Takes priority over Search Queries |
| `brands` | Array | No | Filter by designer name, e.g. `["Zimmermann"]`. Layers on top of either mode |
| `market` | String | No | Market to read, default `outnet_be`. See the market list below |
| `maxItems` | Integer | No | Stop after this many products across all queries or categories. Default 50 |
| `pageSize` | Integer | No | Products per request, default 60. 200 is the site's verified ceiling |
| `fetchProductDetails` | Boolean | No | Fetch brand, exact size/colour, stock and the full image set per product. Default `true` |
| `proxyConfiguration` | Object | No | Default Apify proxy, on by default. Recon found no anti-bot, so this exists as a plain escape hatch, not a requirement |

#### Markets

`outnet_be` (Belgium, EUR), `outnet_nl`, `outnet_ie`, `outnet_at` (EUR),
`outnet_ch` (CHF), `outnet_es`, `outnet_fr`, `outnet_de` (EUR),
`outnet_gb` (GBP), `outnet_us` (USD), `outnet_ca` (CAD), `outnet_au` (AUD),
`outnet_hk` (HKD), `outnet_kr` (KRW), `outnet_ae` (AED), `outnet_se` (SEK),
`outnet_dk` (DKK).

### Output

| Field | Type | Example |
|-------|------|---------|
| `name` | String | `"VALENTINO GARAVANI Corded Lace-Appliquéd Cotton-Blend Cady Mini Dress"` |
| `brand` | String | `"Valentino Garavani"` |
| `price` | Number | `432.26` |
| `currency` | String | `"EUR"` |
| `originalPrice` | Number | `2878.82`, present whenever the item is reduced |
| `discount` | String | `"-85%"` |
| `ean` | String | Barcode, when THE OUTNET's index publishes one |
| `sku` | String | Retailer SKU for this exact listing |
| `productId` | String | THE OUTNET's internal (Shopify) product ID |
| `inStock` | Boolean or null | `true`/`false` with Fetch Product Detail on, `null` when off |
| `sizes` | Array | Almost always one entry — see "One listing, one size" below |
| `colour` | String | `"Black"` |
| `category` | String | `"Dresses"` |
| `productType` | String | The retailer's own product-type label |
| `tags` | Array | `["Just-In"]` |
| `imageUrl` | String | Main image |
| `imageUrls` | Array | All available images |
| `description` | String | THE OUTNET's editorial copy |
| `url` | String | Product page on the selected market |
| `market` | String | `"outnet_be"` |
| `searchQuery` | String or null | The term that returned this product, null in category mode |
| `categorySlug` | String or null | The category that returned this product, null in search mode |
| `brandFilter` | String or null | The brand filter applied, when set |
| `scrapedAt` | String | ISO 8601 timestamp |

#### One listing, one size

Unlike NET-A-PORTER or Mytheresa, THE OUTNET does not group every size of a
garment under one product with a size ladder. A dress in size 36 and the same
dress in size 38 are two separate listings with their own URL and their own
Shopify product ID — outlet/liquidation inventory tracked unit by unit. So
`sizes` normally holds exactly one entry: the size, colour, availability and
SKU of that specific listing. This is a real fact about their catalogue, not a
gap in the scrape.

#### Prices are read in the market's own currency

THE OUTNET runs on Shopify Markets, and currency is selected by the market you
pick, not converted client-side afterwards. `price` always comes from a
per-market request when **Fetch Product Detail** is on. `originalPrice` can be
trickier: this shop's Shopify Markets setup does not always publish a
converted "compare at" price for every market (confirmed missing for `en-be`
on a product where `en-us` had one, for the exact same item) — when that
happens, the actor computes the discount percentage from the search index
(where the current and original price are always in the same base currency as
each other) and applies that percentage to the market-accurate current price,
so `price` and `originalPrice` are never a mix of two different currencies.

### Example output

```json
{
    "name": "VALENTINO GARAVANI Corded Lace-Appliquéd Cotton-Blend Cady Mini Dress",
    "brand": "Valentino Garavani",
    "price": 432.26,
    "currency": "EUR",
    "originalPrice": 2878.82,
    "discount": "-85%",
    "sku": "PB0VAHV53600NA-36",
    "productId": "9240092442850",
    "inStock": true,
    "sizes": [
        {
            "size": "36",
            "color": "Black",
            "available": true,
            "sku": "PB0VAHV53600NA-36"
        }
    ],
    "colour": "Black",
    "category": "Dresses",
    "productType": "Dresses",
    "tags": ["Just-In"],
    "imageUrl": "https://cdn.shopify.com/s/files/1/0791/3544/1122/files/60afeafa-4ceb-49fa-8ec0-af5fa5409359.jpg",
    "description": "Embrace the refined elegance of Valentino Garavani with this expertly crafted mini dress...",
    "url": "https://theoutnet.com/en-be/products/valentino-garavani-corded-lace-appliqued-cotton-blend-cady-mini-dress",
    "market": "outnet_be",
    "searchQuery": "dress",
    "categorySlug": null,
    "brandFilter": null,
    "scrapedAt": "2026-09-11T09:16:04.878Z"
}
```

### Speed and cost

There is no browser warm-up and no anti-bot dance: every request is a plain
JSON fetch. A measured local run: 50 products from one search query,
including the per-product detail fetch, in under 10 seconds direct, and about
2 minutes through the default Apify proxy pool (worth it for the IP
diversity, since a plain HTTP request is cheap either way).

Turning **Fetch Product Detail** off removes one request per product and
roughly halves the time and request count, at the cost of `brand`, `sizes`,
`inStock`, `colour`, `productType`, `tags` and the full `imageUrls` set (you
still get `name`, `price`, `category`, `imageUrl`, `description` and a
best-effort `originalPrice`/`discount` from the search index alone).

There is no Bright Data or other paid unblocker cost per result — every
request is a plain fetch, so cost per item is just the platform's own compute
and dataset pricing. As with any Apify actor, the usage cost of a run only
settles once the run finishes with SUCCEEDED; a run you stop early or that
fails still bills for the compute it used up to that point.

### Limitations

- **One listing is one size/colour**, not a ladder — see above. If you need
  every size of one style, search or browse by that style's name and collect
  the resulting listings.
- **`brand` is empty with Fetch Product Detail off.** THE OUTNET's search
  index does not carry a brand field on its own; it only comes from the
  per-product detail fetch.
- **Category and brand values are case-sensitive** and must match THE
  OUTNET's own labels exactly (`"Dresses"`, not `"dresses"`). An unmatched
  value returns 0 hits rather than an error.
- **`originalPrice` is sometimes estimated from a percentage**, not read
  directly, on markets where this shop's Shopify Markets setup does not
  publish a converted "compare at" price. See "Prices are read in the
  market's own currency" above.
- Data is scraped from the public website and may change without notice.
  Respect the website's terms of service and use responsibly.

### Related scrapers

- [NET-A-PORTER Scraper](https://apify.com/studio-amba/net-a-porter-scraper) —
  YNAP's full-price sibling. A different backend entirely (IBM WebSphere
  Commerce behind Akamai, versus this actor's Shopify + Constructor.io), but
  the same corporate group.
- [Mytheresa Scraper](https://apify.com/studio-amba/mytheresa-scraper) — the
  other big European full-price luxury retailer.
- [Vinted Scraper](https://apify.com/studio-amba/vinted-scraper) — Europe's
  largest secondhand fashion marketplace, for comparing outlet against resale.
- [Vestiaire Collective Scraper](https://apify.com/studio-amba/vestiairecollective-scraper) —
  authenticated luxury resale.
- [Zalando Scraper](https://apify.com/studio-amba/zalando-scraper) — general
  European fashion at a lower price point.

### Need this data on a schedule, or a custom version?

We run this scraper as a managed service for businesses: scheduled runs,
deduplication, delta detection, and delivery to your inbox, Google Sheets, or
API — maintenance included. We can also build a custom version with your
exact fields and filters, or combine multiple luxury sources into one feed.

# Actor input Schema

## `searchQueries` (type: `array`):

One or more search terms, e.g. a category ('dress', 'bag', 'sneakers') or a designer name ('zimmermann', 'valentino garavani').

## `searchQuery` (type: `string`):

Convenience alternative to Search Queries when you only want one term. When both this and Search Queries are empty, the actor falls back to 'dress' so an empty run still returns data.

## `categorySlugs` (type: `array`):

Browse THE OUTNET's category facet directly instead of searching. Values are CASE-SENSITIVE and must match the site's own category label exactly, e.g. 'Dresses', 'Bags', 'Sneakers', 'Coats', 'Knitwear'. When this is set, Search Queries are ignored.

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

Optional designer-name filter layered on top of either Search Queries or Category Values, e.g. 'Valentino Garavani', 'Zimmermann'. Case-sensitive, must match the brand exactly as THE OUTNET lists it.

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

Which THE OUTNET storefront to read. Prices and currency are per market.

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

Stop after this many products across all queries.

## `pageSize` (type: `integer`):

Products per request. 200 is the site's verified ceiling; higher values are clamped.

## `fetchProductDetails` (type: `boolean`):

Fetch each product's own page data to get brand, exact size/colour, stock and the full image set, and to read price/currency from the authoritative per-market source rather than the search index. Costs one extra request per product. Turn off for a faster, thinner listing-only scrape.

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

Recon (2026-09-11) found no anti-bot at all on the endpoints this actor uses -- a direct connection gets a 200 on the first try, every time. The default Apify proxy is enabled anyway as standard practice; there is no need for RESIDENTIAL here.

## Actor input object example

```json
{
  "searchQueries": [
    "dress",
    "zimmermann"
  ],
  "searchQuery": "dress",
  "market": "outnet_be",
  "maxItems": 10,
  "pageSize": 60,
  "fetchProductDetails": true,
  "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 = {
    "searchQueries": [
        "dress",
        "zimmermann"
    ],
    "market": "outnet_be",
    "maxItems": 10,
    "pageSize": 60,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/theoutnet-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 = {
    "searchQueries": [
        "dress",
        "zimmermann",
    ],
    "market": "outnet_be",
    "maxItems": 10,
    "pageSize": 60,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/theoutnet-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 '{
  "searchQueries": [
    "dress",
    "zimmermann"
  ],
  "market": "outnet_be",
  "maxItems": 10,
  "pageSize": 60,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call studio-amba/theoutnet-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/theoutnet-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/AUHeahjdn2NTBGB4M/builds/2Kgwf4qbjinbghWKp/openapi.json
