# Depop Listings Scraper (`devilscrapes/depop-listings-scraper`) Actor

Sweep a Depop search query across price-band filter shards and export deduplicated listing rows — title, brand, condition, price breakdown, images, canonical URL. Depop has no pagination; coverage is bounded by the shard grid you configure, not the query's full catalogue. Vintage resale fashion.

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

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Depop Listings Scraper

**💰 $4.20 / 1 000 listings**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Sweep a Depop search query across price-band filter shards and export deduplicated listing rows — title, brand, condition, price breakdown, images, canonical URL. Depop has no pagination; coverage is bounded by the shard grid you configure, not the query's full catalogue.

</div>

***

### 🎯 What this scrapes

Depop is a fashion-resale marketplace with no working "load more" API — its search page SSRs exactly one static batch of listings per request and ignores page/offset entirely. This Actor gets around that by sweeping the same query across a grid of price-band shards (and, optionally, category/condition/brand/size shards), fetching each shard once, deduplicating by listing ID, and writing one clean row per unique listing: title, brand, category, condition, size, price breakdown, images, and the canonical product URL. Coverage is bounded by the shard grid you configure — more shards means more coverage, not an unlimited crawl.

### 🔥 What we handle for you

- 🛡️ **We rotate browser fingerprints** — `curl-cffi` impersonation (Chrome / Firefox / Safari) so Depop sees a real browser, not Python.
- 🔁 **We retry with exponential backoff** on `408 / 429 / 5xx` and honour `Retry-After` — up to 5 attempts per shard.
- 🌐 **We rotate proxy sessions** through Apify Proxy on every block — fresh session ID, fresh exit IP; switch to RESIDENTIAL from the input form if you need it.
- 🧱 **We never silently drop a shard** — a bad shard is logged and skipped; if the grid would exceed your cap we truncate and say so in the run's status message.
- 🧊 **We keep the dataset clean** — deduplicated by listing ID, Pydantic-validated rows, ISO-8601 timestamps.
- 💰 **You pay only for unique listings that land.** A listing seen in two shards is billed once, not twice.

### 💡 Use cases

- Resale market research — pull current asking prices for a brand or item across a price grid to benchmark resale value.
- Sourcing leads — monitor a keyword across price bands to spot underpriced listings worth a closer look.
- Trend tracking — sweep the same query on a schedule and diff runs to see what's newly listed or sold through.
- Catalogue sampling — build a representative sample of a niche (brand, category, style) for downstream analysis.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Fill in the input form — most fields have sensible defaults.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `query` | `string` | **yes** | 'vintage carhartt jacket' | Search term to sweep across the shard grid, matched against Depop's search/?q= endpoint. 1-100 characters. |
| `priceShards` | `array` | no | \[\[None, None], \[0, 25], \[25, 50], \[50, 100], \[100, 200], \[200, None]] | Price-band grid as \[min, max] pairs (either bound may be null for open-ended). This is the proven shard axis — each… |
| `extraShardAxes` | `object` | no | {} | Optional candidate shard axes — category / condition / brand / size, each an array of up to 10 values. Off by default.… |
| `maxShardsPerRun` | `integer` | no | 12 | Ceiling on the total number of shard requests this run will issue. Price shards are prioritized; any overflow is… |
| `maxListingsPerShard` | `integer` | no | 20 | Cap on listings parsed per shard. Depop's search page SSRs about 20 listings per static batch, so values above 20 have… |
| `proxyConfiguration` | `object` | no | {'useApifyProxy': True} | Apify Proxy routing. Datacenter (the default) matches the recon setup that confirmed reach on www.depop.com — switch to… |

#### Example input

```json
{
  "query": "vintage levis jacket",
  "priceShards": [
    [
      null,
      null
    ],
    [
      25,
      50
    ]
  ],
  "maxShardsPerRun": 2,
  "maxListingsPerShard": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

Every row is one dataset item.

| Field | Type | Notes |
|---|---|---|
| `id` | `string` | Depop listing ID — the dedupe key across shards. |
| `slug` | `string` | Depop listing slug. |
| `url` | `string` | Canonical listing URL: https://www.depop.com/products/{slug}/. |
| `title` | `string` | Listing title (Depop's description field — there is no separate title field). |
| `brand` | `string` | Brand name, when Depop has one on file for the listing. |
| `category` | `string` | Depop category name. |
| `condition` | `string` | Listed condition, e.g. Good, New. |
| `colour` | `string` | Listed colour attribute. |
| `gender` | `string` | Listed gender attribute. |
| `product_type` | `string` | Listed product-type attribute, e.g. Jacket. |
| `sizes` | `array` | Sizes attached to the listing. |
| `country` | `string` | Seller's listed country. |
| `like_count` | `integer` | Number of likes on the listing at scrape time. |
| `price_total` | `string` | Total price the buyer pays, as a decimal string. |
| `price_item` | `string` | Item price component, as a decimal string. |
| `price_buyer_fee` | `string` | Buyer fee component, as a decimal string. |
| `price_tax` | `string` | Tax component, as a decimal string. |
| `price_shipping` | `string` | Shipping component, as a decimal string. |
| `currency` | `string` | ISO currency code for the price breakdown. |
| `image_urls` | `array` | Listing image CDN URLs. |
| `matched_shard` | `object` | The shard parameters (e.g. price\_min/price\_max) that produced this row — for auditability, not billed separately. |
| `scraped_at` | `string` | ISO-8601 timestamp of when this row was scraped. |

#### Example output

```json
{
  "id": "48213771",
  "slug": "vintage-carhartt-jacket-brown-medium",
  "url": "https://www.depop.com/products/vintage-carhartt-jacket-brown-medium/",
  "title": "Vintage Carhartt jacket, brown, size M, light wear",
  "brand": "Carhartt",
  "category": "Menswear",
  "condition": "Good",
  "colour": "Brown",
  "gender": "Men",
  "product_type": "Jacket",
  "sizes": [
    "M"
  ],
  "country": "GB",
  "like_count": 14,
  "price_total": "42.50",
  "price_item": "35.00",
  "price_buyer_fee": "3.50",
  "price_tax": "0.00",
  "price_shipping": "4.00",
  "currency": "GBP",
  "image_urls": [
    "https://media-photos.depop.com/b1/abc123.jpg"
  ],
  "matched_shard": {
    "price_min": "25",
    "price_max": "50"
  },
  "scraped_at": "2026-09-18T12:00:00+00:00"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.2 | One-off warm-up charge per run |
| `listing-scraped` | $0.004 | PPE event |

Example: 1 000 listings at the rates above ≈ **$4.20**. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

### 🚧 Limitations

- No true pagination — total coverage is bounded by the shard grid (price bands plus any opt-in category/condition/brand/size axes), not by the query's full catalogue size.
- `extraShardAxes` values are customer-supplied candidates; the Actor validates non-triviality at runtime but does not auto-discover which values exist on Depop.
- Seller profiles, order history, messaging, and other authenticated Depop features are out of scope.

### ❓ FAQ

**Will this get every listing for my query?**

No — Depop has no working pagination, so coverage is bounded by the shard grid you configure. Each price band returns Depop's own static batch of listings (roughly 20), and more shards mean more coverage, not an unlimited crawl. Widen `priceShards` or turn on `extraShardAxes` to cover more of the catalogue.

**Why price shards and not just "page 2, page 3"?**

Depop's search endpoint ignores page/offset entirely — repeated identical requests return the same static batch. Filtering by price band is the mechanism that actually returns a different set of listings, so that's what this Actor sweeps.

**What happens if a shard is duplicate of another?**

Listings are deduplicated by ID across every shard in the run, so a listing that shows up under two price bands is stored and billed exactly once.

**Why is my run slow or produces fewer rows than I expected?**

Each shard is one request against Depop's live search page, so runtime scales with `maxShardsPerRun`. A 0-row shard usually means that price band genuinely has no matches for your query, not a failure — check the run's status message for what was searched.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Changelog

This Actor's version history is a separate document: https://apify.com/devilscrapes/depop-listings-scraper/changelog.md

# Actor input Schema

## `query` (type: `string`):

Search term to sweep across the shard grid, matched against Depop's search/?q= endpoint. 1-100 characters.

## `priceShards` (type: `array`):

Price-band grid as \[min, max] pairs (either bound may be null for open-ended). This is the proven shard axis — each band returns a disjoint batch of listings. Defaults to a 6-band grid spanning the full price range.

## `extraShardAxes` (type: `object`):

Optional candidate shard axes — category / condition / brand / size, each an array of up to 10 values. Off by default. Each value is validated at runtime against the baseline shard's listing-ID set and only kept as a real shard if it is not a near-duplicate (>=50% ID overlap is treated as a no-op).

## `maxShardsPerRun` (type: `integer`):

Ceiling on the total number of shard requests this run will issue. Price shards are prioritized; any overflow is truncated in input order and reported in the run's status message.

## `maxListingsPerShard` (type: `integer`):

Cap on listings parsed per shard. Depop's search page SSRs about 20 listings per static batch, so values above 20 have no effect.

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

Apify Proxy routing. Datacenter (the default) matches the recon setup that confirmed reach on www.depop.com — switch to RESIDENTIAL if you see repeated blocks.

## Actor input object example

```json
{
  "query": "vintage carhartt jacket",
  "priceShards": [
    [
      null,
      null
    ],
    [
      0,
      25
    ],
    [
      25,
      50
    ],
    [
      50,
      100
    ],
    [
      100,
      200
    ],
    [
      200,
      null
    ]
  ],
  "extraShardAxes": {},
  "maxShardsPerRun": 12,
  "maxListingsPerShard": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "query": "vintage carhartt jacket",
    "priceShards": [
        [
            null,
            null
        ],
        [
            0,
            25
        ],
        [
            25,
            50
        ],
        [
            50,
            100
        ],
        [
            100,
            200
        ],
        [
            200,
            null
        ]
    ],
    "extraShardAxes": {},
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/depop-listings-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 = {
    "query": "vintage carhartt jacket",
    "priceShards": [
        [
            None,
            None,
        ],
        [
            0,
            25,
        ],
        [
            25,
            50,
        ],
        [
            50,
            100,
        ],
        [
            100,
            200,
        ],
        [
            200,
            None,
        ],
    ],
    "extraShardAxes": {},
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/depop-listings-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 '{
  "query": "vintage carhartt jacket",
  "priceShards": [
    [
      null,
      null
    ],
    [
      0,
      25
    ],
    [
      25,
      50
    ],
    [
      50,
      100
    ],
    [
      100,
      200
    ],
    [
      200,
      null
    ]
  ],
  "extraShardAxes": {},
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/depop-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/depop-listings-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/ekg9RDBtCHxJ947F4/builds/gerCujfLRrQW44hue/openapi.json
