Vinted Scraper — Listings, Demand Signals & Sold Tracking
Pricing
from $1.20 / 1,000 result scrapeds
Vinted Scraper — Listings, Demand Signals & Sold Tracking
Scrape Vinted across every EU market: price, brand, size, condition, favourites, listing age, seller country and all photos. Works on vinted.be, .nl, .de, .it and .es, not just .fr. Watch mode re-checks known listings so you can see which ones sold. No login, no proxy.
Pricing
from $1.20 / 1,000 result scrapeds
Rating
0.0
(0)
Developer
Studio Amba
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Vinted Scraper
Scrape Vinted listings across every European market, and track a fixed set of listings over time to see which ones actually sell.
Why use this actor
Vinted is the biggest second-hand marketplace in Europe, and it is the price reference for anyone buying or reselling used clothing. This actor reads it through Vinted's own search API, so you get the same records the site shows, with the fields that matter for pricing: asking price, the all-in price a buyer pays, condition, size, how long the listing has been up, and how many people have favourited it.
Two things here that most Vinted scrapers do not do.
It works on every market, not just France. Vinted puts a Cloudflare
challenge in front of the HTML on vinted.be, .nl, .de, .it, .es and
.pl. Scrapers that start by loading the homepage fail on all six and only work
on .fr and .co.uk. This one does not load the homepage.
It can tell you what sold. Vinted deletes sold listings from the catalogue
outright, so there is no sold-price history anywhere to query. mode: "watch"
builds one forward: you hand it a set of listings, it re-checks them on a
schedule, and it reports which are still live and which have gone.
How to scrape Vinted data
- Pick a mode.
indexfor a fast catalogue read,fullif you also need descriptions and colours,watchto track listings over time. - Give it search terms, or paste a Vinted search URL you built in the browser.
- Pick a market. This sets the language and currency, not the inventory — see the note below.
- Run it. Export JSON, CSV or Excel, or pull the dataset over the API.
No login, no cookies to supply, no proxy. A free Apify account is enough to try it.
The three modes
index | full | watch | |
|---|---|---|---|
| What it reads | Vinted's search API | search API + one page per listing | search API + one liveness probe per tracked listing |
| Speed | 89 listings in 6.5s | ~2.5s per listing | ~30 listings/minute (rate-limited, see below) |
| Fields | everything in the table below except the five marked "full only" | all of them | listing fields plus the lifecycle fields |
| Best for | price monitoring, catalogue snapshots, market sizing | product records, colour/material filtering, reserved status | building a sold-price series |
index is the default and it is the one to reach for. full costs roughly
150x the bytes per listing (370 KB against ~4 KB) because Vinted's item-detail
API endpoint was removed and the listing page is the only route left to
descriptions.
Watch mode, and what it can honestly tell you
Vinted removes a listing the moment it sells. So a sold-price index cannot be backfilled, from this actor or any other. It has to accumulate.
Watch mode keeps its state in a named key-value store, so consecutive runs add up instead of each starting blind. Schedule it daily and each run:
- optionally runs your searches and adds anything new to the watchlist,
- probes every tracked listing to see whether it is still live,
- writes one record per tracked listing with
status,daysLive,lastKnownPriceand every price change it has seen.
The probe asks Vinted about the listing directly (/items/{id} answers a
redirect when the listing is live and a 404 when it is gone). It does not look
for the listing in search results, so the usual "is it gone or did the ranking
just shuffle?" problem does not arise. missesBeforeVanished exists to absorb
network flakes, not ranking noise, and 2 is plenty.
The soldSignal field is graded honestly:
| Value | Means |
|---|---|
none | Live, nothing happening |
reserved | Live, and the seller has marked it reserved — a sale is in progress |
vanished | Gone. This could be a sale or a delisting, and Vinted does not tell you which |
reserved-then-vanished | Reserved first, then gone. This reads as a completed sale at lastKnownPrice |
reserved is the signal worth paying for, and it needs checkReserved: true,
which fetches each live listing's page. That is the expensive option in this
actor. Leave it off for a large watchlist and take vanished for what it is.
Input
| Field | Type | Default | Description |
|---|---|---|---|
mode | String | index | index, full or watch |
searchQueries | Array | ["nike"] | Search terms. maxItems is split evenly between them |
searchQuery | String | — | Single-term convenience alternative |
market | String | be | Domain to read. See the market note below |
maxItems | Integer | 100 | Stop after this many records |
startUrls | Array | — | Vinted search URLs; their filters are reused verbatim |
order | String | relevance | relevance, newest_first, price_low_to_high, price_high_to_low |
priceFrom / priceTo | Integer | — | Price band. Also the way past the 960-result cap |
conditionIds | Array | — | 6 = new with tags, 1 = new without tags, 2 = very good, 3 = good, 4 = satisfactory, 7 = not fully functional |
brandIds / catalogIds | Array | — | Vinted's numeric brand and category ids |
fetchSellerCountry | Boolean | true | Look up each seller's country. Not in the search response, so it costs one API call per unique seller |
includeSellerProfile | Boolean | false | Adds seller city, rating and review count. Personal data — see below |
watchItemIds | Array | — | Watch mode. Listing ids or item URLs to track |
watchStoreName | String | vinted-watchlist | Watch mode. Which key-value store holds the watchlist |
seedWatchlistFromSearch | Boolean | true | Watch mode. Also run the searches each time and add what is new |
checkReserved | Boolean | false | Watch mode. Fetch each live listing's page to read reserved status |
missesBeforeVanished | Integer | 2 | Watch mode. Consecutive 404s before a listing is called vanished |
dropVanishedAfterRuns | Integer | 3 | Watch mode. How long a vanished listing stays in the output |
requestDelayMs | Integer | 150 | Politeness delay. 0 for maximum speed |
proxyConfiguration | Object | off | Leave off. A direct connection is what works here |
Output
| Field | Type | Example | Note |
|---|---|---|---|
listingId | String | "9484408775" | Stable, global across all Vinted domains |
status | String | "active" | active or vanished. Not the same thing as condition |
title | String | "Lanvin curb sneaker white blue" | |
brand | String | "Lanvin" | 92–100% coverage; a few listings have no brand set |
price | Number | 110 | Seller's asking price |
totalPrice | Number | 116.2 | Asking price plus buyer protection — what a buyer pays |
serviceFee | Number | 6.2 | Vinted's buyer-protection fee |
currency | String | "EUR" | |
size | String | "44" | 83–100%. Genuinely absent on unsized items |
condition | String | "Très bon état" | In the market's language. See below |
url | String | full listing URL | |
datePosted | String | "2026-07-25T08:51:00.000Z" | See the caveat below |
listingAgeDays | Number | 4.08 | High values mean the asking price is not clearing |
favourites | Integer | 25 | The demand signal. A real count |
views | Integer | 0 | Always 0. See limitations |
sellerId / sellerName | String | "remmydrost" | |
sellerCountry | String | "NL" | 98–100% when fetchSellerCountry is on, otherwise null |
sellerIsBusiness | Boolean | false | |
sellerCity / sellerRating / sellerReviewCount | Only when includeSellerProfile is on | ||
isPromoted | Boolean | true | Seller paid to boost this listing |
photos | Array | 6 URLs | All photos, full size |
photoCount | Integer | 6 | |
market / searchQuery / scrapedAt | Provenance | ||
description | String | full only | |
colour / material | String | "Blanc, Bleu" | full only. material is only set on ~10% of listings, by the seller |
catalogId / brandId | Integer | 1242 / 5257 | full only. Reusable as filters |
isReserved | Boolean | false | full only, or watch mode with checkReserved |
firstSeenAt / lastSeenAt / daysLive / checks / vanishedAt / lastKnownPrice / priceChanges / soldSignal | watch only |
Example output
{"listingId": "9484408775","status": "active","title": "Lanvin curb sneaker white blue","brand": "Lanvin","price": 110,"currency": "EUR","totalPrice": 116.2,"serviceFee": 6.2,"size": "44","condition": "Très bon état","url": "https://www.vinted.be/items/9484408775-lanvin-curb-sneaker-white-blue","datePosted": "2026-07-25T08:51:00.000Z","listingAgeDays": 4.08,"favourites": 25,"views": 0,"sellerId": "80639665","sellerName": "remmydrost","sellerCountry": "NL","sellerIsBusiness": false,"isPromoted": false,"photoCount": 6,"photos": ["https://images1.vinted.net/tc/..."],"market": "be","searchQuery": "lanvin","scrapedAt": "2026-07-29T10:39:12.000Z"}
A watch-mode record for the same listing, on its fourth check:
{"listingId": "9484408775","status": "vanished","soldSignal": "reserved-then-vanished","brand": "Lanvin","lastKnownPrice": 110,"currency": "EUR","firstSeenAt": "2026-07-25T08:00:00.000Z","lastSeenAt": "2026-07-28T08:00:00.000Z","vanishedAt": "2026-07-29T08:00:00.000Z","daysTracked": 4.0,"daysLive": 3.0,"checks": 4,"consecutiveMisses": 2,"priceChanges": [{ "at": "2026-07-27T08:00:00.000Z", "price": 110 }],"wasReservedBeforeVanishing": true}
Markets: read this before picking one
fr, be, nl, de, it and es all serve the same euro catalogue. Run
the same query against two of them and 17 to 18 of the first 20 results are the
same listings — the differences are promoted slots, not different stock. What
the market actually changes:
- the language of
condition(Très bon état/Goed/Gut) - the currency
- the host in
url
uk (GBP) and pl (PLN) are genuinely separate catalogues with no overlap.
So "scrape Belgium" is not a thing on Vinted. If you need seller country, read
the sellerCountry field and filter on it — Vinted's API has no country filter.
Speed and cost
Measured on Apify, 1 GB memory, no proxy, 2026-07-29:
| Run | Result | Time | Compute units | Platform cost |
|---|---|---|---|---|
index, 89 listings, no seller lookup | 89 | 6.5s | 0.0018 | $0.0008 |
index, 60 listings, with seller country | 60 | 66s | 0.018 | $0.0033 |
full, 10 listings | 10 | 25s | 0.007 | $0.0012 |
watch, seed 25 listings | 25 | 26s | 0.007 | $0.0014 |
watch, re-check 35 listings | 35 | 85s | 0.024 | $0.0041 |
The seller-country lookup is the main cost driver in index mode: it turns one
request per 96 listings into one request per unique seller. Turn
fetchSellerCountry off and a 100-listing scrape finishes in under 7 seconds.
Limitations
Stated plainly, because you will hit these.
- Any single search returns at most 960 results. Vinted caps page size at 96
and page number at 10. This is Vinted's limit, not the actor's. To go deeper,
split the query into price bands with
priceFrom/priceTo, or filter by brand or category. pagination.total_entriesis always 960, on every query, including one that matches three items. It is a display constant in Vinted's API, not a count. This actor ignores it and so should you.viewsis always 0. Vinted zeroes the view count in search results (measured 95 out of 95 listings, maximum 0). The field is kept because it is in their payload and may come back, but todayfavouritesis the only usable demand signal.datePostedis a proxy. Vinted exposes no creation timestamp anywhere. This is the upload time of the listing's first photo, which matched Vinted's own "added N days ago" label on 5 of 5 spot checks. A relisting that reuses old photos will read older than it is.condition,colourandmaterialcome back in the market's language. There is no locale override — the domain is the locale.materialis set on about 10% of listings. Sellers rarely fill it in. That is Vinted's data, not a scraping gap.- The listing-page route is rate-limited to roughly 30 requests per burst,
then answers HTTP 429 for about a minute. That is the ceiling on
fullmode and onwatchmode throughput. The actor paces itself adaptively and retries, so a large watchlist works, it just takes minutes rather than seconds. A rate limit is never counted as "listing gone". - No sold-price history, and none is possible. Vinted deletes sold listings. Watch mode builds a sold series forward from the day you start it and cannot look back. Nothing can.
vanishedis not the same assold. A listing can disappear because it sold, because the seller pulled it, or because Vinted removed it. Onlyreserved-then-vanishedis strong evidence of a sale.
No hosted search layer here
Some sites power their search box with a third-party service (Algolia,
Typesense, Constructor) whose index can be queried directly and cheaply. Vinted
does not. /api/v2/catalog/items is Vinted's own search service, and it is
already the fast path — there is no cheaper index sitting behind the site. So
unlike our Yoox scraper, there is
no index-versus-crawl trade-off to choose here; index mode already reads the
same service the website reads.
Personal data and GDPR
Vinted listings carry personal data: seller usernames, profile photos, city, country, and whatever the seller typed into the description. That is personal data under GDPR whether or not it was posted publicly.
This actor is built to collect less of it by default:
sellerName,sellerIdandsellerCountryare returned because they are part of the listing and most use cases (price comparison, marketplace analysis) need to distinguish sellers and markets.sellerCity,sellerRatingandsellerReviewCountare off by default behindincludeSellerProfile. They go beyond what the listing card shows.descriptionis only fetched infullmode, because it is free text that can contain anything.
If you are processing this data in the EU, you need a lawful basis for it, you
should keep only the fields your use case actually needs, and you should not
retain seller identifiers longer than you need them. Turning
includeSellerProfile off and fetchSellerCountry off, where your use case
allows, is the cheapest way to stay on the right side of that.
Related scrapers
- Yoox Scraper — luxury outlet prices with the supplier-stated RRP beside them. The new-price reference to put next to a Vinted asking price.
- Vinted Scraper (v1) — the
earlier build. Still works on
vinted.fr; this one replaces it everywhere else.
Need this data on a schedule, or a custom version?
Watch mode is designed to be scheduled. Set it to run daily against a
watchStoreName of your choosing and the watchlist accumulates on its own.
If you need a different shape of output, a different market set, or a version that pushes straight into your warehouse, open an issue on the actor page.