By the end of this tutorial, you will have a Python script that pulls second-hand fashion listings from Vinted Spain (vinted.es) into structured JSON: title, item asking price, buyer protection service fee, total price in EUR, brand, item condition, size, photo URL, favourite count, and seller type.
Vinted is a popular European marketplace where people buy and sell second-hand clothes, shoes, bags and accessories. Searching the catalog manually and copying product listings into a spreadsheet is slow and repetitive, and each search result page shows up to 96 items.
In this guide, we use Python and the Apify Actor Vinted Spain Scraper (reventadata/vinted-scraper). Our benchmark run (configured with searchQueries: ["nike"], conditions: ["Muy bueno", "Bueno"], minPrice: 10, maxPrice: 40, sortBy: "relevance", requireKeywordMatch: true, and maxItems: 200) finished in 19.2 seconds and returned 200 items.
⏱️ Time estimate: About 30 minutes.
Prerequisites
To follow this tutorial, you will need:
- Python 3.11+ installed locally on your system.
- The Apify API client for Python (
pip install apify-client). - An Apify account and its API token.
Copy your API token from API & Integrations in the Apify Console settings, and then install the official Apify client library in your terminal:
pip install apify-client
What you'll achieve
You will run the Actor from Python and receive clean, structured JSON records for matching listings on Vinted Spain, up to the maxItems and maxPages caps. The scraper extracts item records directly from the server-rendered catalog pages, so individual listing pages do not need to be opened separately.
Note on pricing structures: Vinted displays both the seller's asking price and a buyer protection fee. The dataset separates these into
price(the listing item price),serviceFee(the buyer protection fee), andtotalPrice(item price plus service fee in EUR).
Example use case: Suppose you want to monitor second-hand Nike sportswear priced between 10 EUR and 40 EUR in very good or good condition. Setting searchQueries: ["nike"] with conditions: ["Muy bueno", "Bueno"], minPrice: 10, and maxPrice: 40 returns matching listings, up to your maxItems cap.
Step 1: Access Vinted Spain Scraper
Open the Vinted Spain Scraper page on Apify Store. The store listing details available input parameters, output schemas, and sample records. You can click Try for free to inspect the Actor in the Apify Console web interface. In this guide, we invoke the scraper directly using Python code.
Step 2: Configure search parameters
The primary configuration property is searchQueries, an array of search keywords. Each query searches the vinted.es catalog across fashion, footwear, electronics and home. You can also specify optional conditions, minPrice, maxPrice, and sortBy. Here is the Python script with the same input we used for our benchmark run:
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"searchQueries": ["nike"],
"conditions": [
"Muy bueno",
"Bueno",
],
"minPrice": 10,
"maxPrice": 40,
"sortBy": "relevance",
"requireKeywordMatch": True,
"maxItems": 200,
}
run = client.actor("reventadata/vinted-scraper").call(run_input=run_input)
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item["title"], item["price"], item["totalPrice"], item["currency"], item["url"])
This code uses the exact settings behind the metrics in this article. Setting maxItems: 200 stopped collection once 200 rows were saved, while requireKeywordMatch: True ensures every retained listing matches the search term.
Step 3: Configure optional settings and filters
The Actor provides multiple configuration options and filtering switches:
| Parameter | Type | Default | What it does |
|---|---|---|---|
searchQueries |
array | none | List of search keywords on vinted.es. Required unless you provide catalogIds. |
conditions |
array | [] |
Condition filters: "Nuevo con etiquetas", "Nuevo sin etiquetas", "Muy bueno", "Bueno", "Satisfactorio". |
minPrice |
integer | none | Minimum asking price in EUR, evaluated on the item price before service fee. |
maxPrice |
integer | none | Maximum asking price in EUR, evaluated on the item price before service fee. |
sortBy |
string | relevance |
Sort order: relevance, priceAsc, priceDesc, or newest. |
sellerType |
string | any |
Filter sellers: any, private, or professional. |
catalogIds |
array | none | Vinted category IDs (such as 2994 for Electronics or 1904 for Women) to narrow searches or browse categories. |
brandIds |
array | none | Vinted brand IDs (such as 105 for Primark or 7 for H&M) scoped to the relevant category. |
requireKeywordMatch |
boolean | true |
Drops items whose title, brand, and model together do not contain every word of the search query. |
maxItems |
integer | 960 |
Hard cap on total rows saved across all search queries (minimum 1, prefill 10). |
maxPages |
integer | 10 |
Maximum catalog result pages per query (1 to 10; Vinted limits anonymous access to 10 pages). |
Three operational details help you configure these filters effectively:
-
Private sellers carry no seller identifiers. The Actor evaluates seller type from Vinted's business flag. For private sellers,
sellerId,sellerLogin, andsellerProfileUrlare omitted from the row to protect personal privacy, whilesellerTypeis retained. For professional accounts,sellerIdandsellerProfileUrlare included. -
Vinted enforces a 10-page anonymous catalog ceiling. Vinted serves at most 10 pages of 96 items (960 items) per query to anonymous visitors. The input schema allows at most 10 pages, and the Actor clamps
maxPagesto this maximum because subsequent pages return empty item arrays on the site. -
Price filters evaluate item asking prices.
minPriceandmaxPriceapply to the seller's asking price before Vinted's buyer protection fee is added.
Step 4: Run the Actor
Replace <YOUR_APIFY_TOKEN> with your actual token from the Apify Console, save the script, and execute it. Calling .call() starts the Actor in the Apify cloud and waits for completion. The scraper fetches catalog pages sequentially without requiring external proxies, parses the embedded listing records, applies the keyword and seller-type filters (condition and price were already sent to Vinted in the search request), and stores matching items in the default dataset.
Allow the script to execute until completion. Our benchmark run finished in 19.2 seconds and returned 200 items. Each line printed by the script shows the item title, asking price in EUR, total price with service fee, currency, and listing URL.
Step 5: View and download results
The script loops through items in the dataset using .iterate_items(). In Apify Console, you can inspect dataset records and export the data in JSON, CSV, XML, Excel, HTML table, RSS, or JSONL formats.
Here is the first item record from our benchmark run (id: "10500531689"), verbatim:
{
"id": "10500531689",
"title": "T shirt Nike",
"url": "https://www.vinted.es/items/10500531689-t-shirt-nike",
"price": 10,
"serviceFee": 1.2,
"totalPrice": 11.2,
"currency": "EUR",
"brand": "Nike",
"model": null,
"condition": "Muy bueno",
"size": "XS",
"photoUrl": "https://images1.vinted.net/t/05_0215e_JV2wBP59Ao9gQftFrYkxAL2K/310x430/212da0d0.webp?s=859bad0c545f8fa148f97e7eb0afcff61240411b",
"favouriteCount": 51,
"isPromoted": false,
"sellerType": "private",
"matchedKeyword": "nike"
}
Understanding your results
Key attributes returned in the dataset:
-
price: asking price in EUR before buyer fees. -
serviceFee: Vinted's buyer protection fee. -
totalPrice: item price plus service fee in EUR. -
condition: Vinted's condition grade (Muy buenoorBueno). -
brandandsize: parsed brand and size label. -
sellerType:privateorprofessional.
Our benchmark run extracted 200 items, yielding clear empirical metrics:
- All 200 items had numeric prices from 10 EUR to 40 EUR (median 12.0 EUR), with service fees from 1.2 EUR to 2.7 EUR (median 1.3 EUR) and total prices from 11.2 EUR to 42.7 EUR (median 13.3 EUR).
- 173 items were
Muy bueno(86.5%) and 27 wereBueno(13.5%), matching the filter (173 + 27 = 200). - Brands were 198
Nikeand 2Nike Airitems (198 + 2 = 200). - 196 listings were from private sellers (98.0%) and 4 from businesses (2.0%).
- 139 listings were organic results and 61 were promoted placements (139 + 61 = 200).
- Favourites ranged from 0 to 83 (median 15.0; 4 had 0 favourites).
- 199 items had size values across 41 distinct sizes, and 1 had a null size.
Pro tips and advanced usage
-
Respect catalog pagination ceilings. Vinted limits anonymous visitors to 10 pages of 96 items (960 items per query). To collect deeper catalogs, partition broad searches by price brackets using
minPriceandmaxPrice, or combine keywords with specificcatalogIds. -
Handle privacy boundaries in downstream pipelines. The Actor omits personal seller identification fields (
sellerId,sellerLogin,sellerProfileUrl) for private sellers to protect personal privacy, while retainingsellerType. For professional sellers,sellerIdandsellerProfileUrlare populated. -
Automate alerts with webhooks. You can configure Apify webhooks to trigger downstream HTTP endpoints when a scrape finishes. The payload's
resourceobject contains the run details (docs.apify.com/platform/integrations/webhooks/actions), includingdefaultDatasetId. -
Filter out accessories with keyword matching. Vinted's search also returns related items (an "iphone" search returns iPhone cases, per the input schema). Keeping
requireKeywordMatch: truekeeps only items where every search word appears in the title, brand, or model. - For current pricing and details, see the Store page.
Troubleshooting common issues
-
The run fails with "No rows pushed: all X parsed listings were rejected...". The Actor raises a runtime error when items were found on Vinted but rejected by your filters. Check whether your price range (
minPrice/maxPrice), condition selections, orsellerTypesettings are too restrictive. - The run fails with "No rows pushed: the site returned no listings at all...". The Actor raises this error when Vinted returned zero listings for your search term or category.
-
The run fails with "
searchQueriesis required unless you supplycatalogIds...". The Actor raises this error ifsearchQueriesis empty and no category IDs are provided. -
Input refused before the run starts. The platform validates schema enums before starting. Supplying unrecognized values for
sortBy,sellerType, orconditionsis refused before the run starts.
For technical support or feature requests, visit the Actor's Store page.
Next steps
Save your search configuration as a task in Apify Console and configure an Apify schedule to run daily or hourly. You can track second-hand fashion price trends, monitor newly posted bargains, or stream catalog rows directly into a database or spreadsheet. Check the Apify Python client documentation and the Store page to get started.
What items or brands are you planning to track on Vinted? Drop a comment below!
Top comments (0)