# Vinted Spain Scraper — Any Keyword or Category (`reventadata/vinted-scraper`) Actor

Searches vinted.es for any keyword or category and returns listings with price, buyer-protection fee, brand, model, condition, size, favourites and seller type as separate columns. No proxy required.

- **URL**: https://apify.com/reventadata/vinted-scraper.md
- **Developed by:** [reventadata](https://apify.com/reventadata) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 81.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

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?

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

> **Unofficial.** This Actor is not affiliated with, authorised by, endorsed by, or in any
> way officially connected to Vinted. "Vinted" is a trademark of its respective owner and is
> used here only to describe what this tool reads. It reads the same public pages a browser
> does.

Vinted Spain Scraper searches **any keyword or category** on
[vinted.es](https://www.vinted.es) - clothing, footwear, bags, phones, consoles, home - and
returns each listing with its price, brand, condition and size as **separate columns**
instead of one blob of text.

### What data can you extract from Vinted Spain (vinted.es)?

Vinted server-renders its whole results grid into every catalog page, so this Actor reads the
page directly rather than driving a browser or calling a logged-in API. It sends the price,
condition, brand, category and sort filters Vinted itself supports, then applies a keyword
and seller-type filter after fetching.

### Why scrape Vinted Spain (vinted.es)?

- **Every category, one Actor.** Vinted is mostly fashion, but phones, consoles and home
  goods sell there too, and nothing here is gated to clothing.
- **The site's own catalogue values as columns.** Vinted keeps brand, model, condition and
  size out of the listing title. This Actor recovers all four into their own fields, so you
  can sort by condition or group by brand without parsing seller prose.
- **The real total price.** `price` is what the seller asks, `serviceFee` is Vinted's buyer
  protection fee, and `totalPrice` is what a buyer actually pays before shipping.
- **No proxy needed.** Measured with no proxy at all: every page inside the site's 10-page
  ceiling came back complete, 96 items each. A run costs compute and nothing else.
- **Private sellers stay private.** Seller *type* is returned for every row; seller
  *identity* only for professional shops. See Privacy below.

### How to scrape Vinted Spain (vinted.es)

1. Put one or more search terms in `searchQueries` - or leave it empty and give `catalogIds`
   to browse a whole category.
2. Optionally narrow with `conditions`, a price range, `brandIds`, `sellerType` or `sortBy`.
3. Run it. Results land in the dataset.

#### Input

| Field | Type | Meaning |
|---|---|---|
| `searchQueries` | array | One search per term. Required unless `catalogIds` is given. |
| `conditions` | array | Any of `Nuevo con etiquetas`, `Nuevo sin etiquetas`, `Muy bueno`, `Bueno`, `Satisfactorio`. Empty means any condition. |
| `minPrice` / `maxPrice` | integer | Optional, in EUR, on the item price. Omitted from the request entirely when empty - never defaulted. |
| `sortBy` | string | `relevance` | `priceAsc` | `priceDesc` | `newest`. |
| `sellerType` | string | `any` | `private` | `professional`. Professional sellers are a small minority on Vinted. |
| `catalogIds` | array | Vinted category ids from the site's category filter (e.g. 2994 Electronics, 1904 Women). Combined with the keyword, not a replacement for it. |
| `brandIds` | array | Vinted brand ids from the site's brand filter (e.g. 105 Primark, 7 H\&M). Brand ids are catalogue-scoped, not global. |
| `requireKeywordMatch` | boolean | Drop items whose title, brand and model together miss any word of the query. Vinted's own search is fuzzy - an "iphone" search also returns iPhone cases. Default on. |
| `maxItems` | integer | Hard cap on rows pushed. Default 960. |
| `maxPages` | integer | Pages per term, clamped to the site's ceiling of 10. |

```json
{
    "searchQueries": ["iphone"],
    "conditions": ["Muy bueno", "Bueno"],
    "maxPrice": 200,
    "sortBy": "priceAsc",
    "maxItems": 200
}
```

#### Output

```json
{
    "id": "9740922758",
    "title": "Iphone X - bien lire description !",
    "url": "https://www.vinted.es/items/9740922758-iphone-x-bien-lire-description",
    "price": 90,
    "serviceFee": 5.2,
    "totalPrice": 95.2,
    "currency": "EUR",
    "brand": "Apple",
    "model": "iPhone X",
    "condition": "Muy bueno",
    "size": null,
    "photoUrl": "https://images1.vinted.net/t/01_006fc_XkPphxKLCj9THCGJgSLBtu4i/f800/a9d078ee.webp",
    "favouriteCount": 2,
    "isPromoted": true,
    "sellerType": "private",
    "matchedKeyword": "iphone"
}
```

Professional-seller rows carry three extra fields - `sellerId`, `sellerLogin` and
`sellerProfileUrl`. `sellerLogin` is null since 2026-08-25: Vinted removed the username
from the catalog payload, and the key is kept so existing consumers do not break.

### Notes and limits

- **960 listings per search, and that is Vinted's limit, not this Actor's.** Vinted serves
  anonymous visitors at most 10 pages of 96 items for any query - the same 960 whether you
  search one word or browse a whole category. Past that it returns a normal-looking page with
  no results rather than an error. To go deeper, split the search by price band, brand or
  category and run each as its own term.
- **Vinted's own result count is unreliable and is deliberately not reported.** The count the
  site embeds in its pages reads 960 for every query, including a query with no filters at
  all, so it is not a real total. Nothing here uses it, and no row count is promised in
  advance of a run.
- **Brand, model and size are null on plenty of rows.** `model` is parsed from the same
  accessibility text as brand and size, so it is equally unreliable. Unbranded listings and
  categories without sizes (electronics, most home goods) genuinely have neither. Null means Vinted has no
  value, not that parsing failed.
- **`condition` is in Spanish**, exactly as vinted.es publishes it: `Nuevo con etiquetas`,
  `Nuevo sin etiquetas`, `Muy bueno`, `Bueno`, `Satisfactorio`.
- **`size` is Vinted's own string, not a number** - `42` for footwear, `M / 38 / 10` for
  clothing, `4 años / 104 cm` for kidswear. Returned verbatim so it stays comparable to the
  site.
- **`isPromoted` is a label, not a rarity.** Vinted flags a large share of results as
  promoted, so it is returned for information rather than offered as a filter.
- **Sorting by price surfaces outliers at both ends.** Cheapest-first fills with 1 EUR
  accessories; most-expensive-first fills with obviously mispriced listings. Pair `sortBy`
  with a price range if you want a usable band.
- **One photo per row.** The catalog payload carries only the main photo; galleries live on
  the listing page, which this Actor does not fetch.
- **A run that returns zero rows fails rather than succeeding empty**, so a silent
  misconfiguration cannot look like "no stock today".

### Privacy

Vinted's public listings show a seller username. GDPR protects natural persons, so this
Actor treats the two seller kinds differently:

- **Private sellers:** `sellerType` is returned as `private`. `sellerId`, `sellerLogin` and
  `sellerProfileUrl` are **absent from the row entirely** - not empty, absent.
- **Professional (business) sellers:** those three fields are returned, because a shop is a
  business, not a natural person.

No real name, phone number, email address or location is collected for anyone. This Actor
does not fetch listing detail pages or seller profiles, so it never reaches data the results
grid does not already publish.

### How much does it cost to scrape Vinted Spain (vinted.es)?

Pricing is pay-per-event: **$0.001 per result** written to the dataset (**$1.00 per 1,000
results**), plus **$0.00005** charged once when the run starts. There is no subscription —
you pay only for what you get.

### FAQ

**Is a proxy required to scrape Vinted?** No. Measured over 25 sequential pages with no
proxy at all, every page inside the site's 10-page ceiling came back complete. This Actor
ships with no `proxyConfiguration` input at all.

**Is seller identity included in the output?** Only for professional sellers. Private-seller
rows never carry `sellerId`, `sellerLogin` or `sellerProfileUrl` — those fields are absent
from the row, not empty.

**How many listings can one search return?** Up to 960 — Vinted's own limit for anonymous
visitors (10 pages of 96 items), not a limit this Actor imposes.

### More second-hand marketplace scrapers

| Actor | What it scrapes |
|---|---|
| [Wallapop Scraper](https://apify.com/reventadata/wallapop-scraper) | Wallapop, Spain — any keyword, phone mode with battery-health parsing |
| [Wallapop + Vinted + Milanuncios Scraper — Spain](https://apify.com/reventadata/wallapop-vinted-milanuncios-scraper) | Wallapop, Vinted and Milanuncios in Spain — one keyword, one merged table |
| [Cash Converters Spain Scraper](https://apify.com/reventadata/cashconverters-scraper) | Cash Converters Spain — graded second-hand stock with price when new |
| [Milanuncios Scraper](https://apify.com/reventadata/milanuncios-scraper) | Milanuncios — 17 categories, condition, storage and battery-health filters |
| [Gumtree UK Scraper](https://apify.com/reventadata/gumtree-scraper) | Gumtree UK — any category, vehicle and phone details parsed from the ad's own text |
| [OLX Romania Scraper](https://apify.com/reventadata/olx-ro-scraper) | OLX Romania (olx.ro) — any keyword, no proxy required |
| [OLX Brazil Scraper](https://apify.com/reventadata/olx-scraper) | OLX Brazil (olx.com.br) — any category, structured attributes from the site's own detail chips |
| [Todocolección Scraper](https://apify.com/reventadata/todocoleccion-scraper) | Todocolección — collectibles, antiques and auctions, fixed-price and bidding modelled apart |
| [Back Market Spain Scraper](https://apify.com/reventadata/backmarket-scraper) | Back Market Spain — refurbished phones, laptops and tablets, priced against new |
| [eBay Spain Scraper](https://apify.com/reventadata/ebay-scraper) | eBay Spain (ebay.es) — active listings with seller type |

# Actor input Schema

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

One search per term. Works across any Vinted category — fashion, footwear, electronics, home. Required unless you supply Category IDs instead, in which case the whole category is browsed.

## `conditions` (type: `array`):

Keep only these conditions. Sent as Vinted's own status filter and verified against the condition text of the returned items. Leave empty for any condition.

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

Optional. Omitted from the request entirely when empty — never defaulted to 0.

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

Optional. Omitted from the request entirely when empty. This is the item price, not the price including Vinted's buyer protection fee.

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

Order only; changes nothing about which listings exist. Cheapest-first surfaces a lot of 1 EUR accessories and most-expensive-first surfaces obvious mispriced or joke listings, so read the extremes with care.

## `sellerType` (type: `string`):

Keep only private sellers or only professional (business) sellers. Applied after fetching, from Vinted's own business flag. Professional sellers are a small minority — 1 to 2 rows in 96 on the pages sampled.

## `catalogIds` (type: `array`):

Optional Vinted category ids, taken from the category filter on the site (for example 2994 for Electronics, 1904 for Women). These narrow a search rather than replacing it: a keyword and a category are combined, not alternatives. Supply these alone to browse a whole category with no keyword.

## `brandIds` (type: `array`):

Optional Vinted brand ids, taken from the brand filter checkboxes on the site (for example 105 for Primark, 7 for H\&M). Brand ids are catalogue-scoped rather than global, and Vinted's own brand lookup endpoint ignores its search parameter, so read the ids off the filter panel for the category you care about.

## `requireKeywordMatch` (type: `boolean`):

Drop items whose title, brand and model together are missing any word of the query. Vinted's own search is fuzzy — an 'iphone' search also returns iPhone cases and covers. Matching is accent- and case-insensitive.

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

Hard cap on rows pushed across all search terms.

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

Vinted serves at most 10 pages of 96 items (960 items) per query to anonymous visitors, for any query. Beyond that it returns a normal-looking page with no results rather than an error. Clamped to that ceiling.

## Actor input object example

```json
{
  "searchQueries": [
    "iphone"
  ],
  "conditions": [],
  "sortBy": "relevance",
  "sellerType": "any",
  "catalogIds": [],
  "brandIds": [],
  "requireKeywordMatch": true,
  "maxItems": 960,
  "maxPages": 10
}
```

# Actor output Schema

## `matches` (type: `string`):

Matching listings: price, brand, condition, size, favourites, seller type, and a link to the listing.

# 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": [
        "iphone"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("reventadata/vinted-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": ["iphone"] }

# Run the Actor and wait for it to finish
run = client.actor("reventadata/vinted-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": [
    "iphone"
  ]
}' |
apify call reventadata/vinted-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,reventadata/vinted-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/SHrl7eeA239xFpP8S/builds/fjI4fi6Fe6z2kt6nZ/openapi.json
