Vinted Scraper — Listings, Prices & Seller Data
Pricing
Pay per event
Vinted Scraper — Listings, Prices & Seller Data
Scrape Vinted listings, prices, sellers and reviews across 27 country markets. Goes past Vinted's hard 960-item search cap and reports exactly how complete each run was. Export to CSV, Excel, JSON or API.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Blackcube Agency AB
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Scrape Vinted listings, prices, sellers and reviews across 27 country markets, and get past the hard 960-item cap that silently truncates every other Vinted tool.
Paste a Vinted URL or type a keyword. Get clean JSON, CSV or Excel — with a per-query report telling you exactly how complete the result was.
- Past the 960-item cap — 6.4× more items than any single Vinted query can return, measured.
- Coverage you can audit — every run says what it reached and what is genuinely unreachable.
conditionin English on every market — Vinted returnsTrès bon état/Sehr gut/Bardzo dobry; a multi-market dataset is unfilterable without this, and no other Vinted tool does it.- Listings, sellers, closets and reviews in one actor, with the two real sale signals the API leaks.
Failed inputs are free. A row that could not be scraped is written to the dataset with a reason and is never charged. If a run returns nothing, it costs nothing.
Unofficial and not affiliated with, endorsed by, or connected to Vinted. This tool reads only publicly visible marketplace data.
How this compares
| This actor | Typical Vinted actor | |
|---|---|---|
| More than 960 items from a single query | ✅ | ❌ |
| Reports how complete each query actually was | ✅ | ❌ |
| Separates "we stopped at your limit" from "Vinted cannot reach it" | ✅ | ❌ |
| Any number of markets in one run | ✅ | ❌ |
| Item condition in English on every market | ✅ | ❌ |
| Seller's completed-sales count next to their live listings | ✅ | ❌ |
| Marks Vinted's automatic review entries, so cancellations aren't read as sales | ✅ | ❌ |
| No actor-start fee — a run that returns nothing costs nothing | ✅ | ❌ |
The 960-item cap, and why your current export is incomplete
Vinted's catalog API returns 96 items per page and stops at page 10. Page 11 answers HTTP 400. So any single Vinted search returns at most 960 items, however much stock actually matches.
Worse, the API reports total_entries: 960 for every saturated query — so a tool that trusts that number tells you it found "960 of 960" and looks complete when it is not.
We measured it. Every one of these broad queries reports exactly 960:
| Query | total_entries reported |
|---|---|
nike | 960 |
zara | 960 |
dress | 960 |
a | 960 |
You will see it claimed that this field is simply a display constant with no meaning. It is not, and that matters: narrow queries report a true count, which is exactly what makes the cap detectable and the fix possible.
| Query | total_entries reported |
|---|---|
supreme box logo hoodie red | 298 |
chanel haute couture vintage 1987 | 4 |
zxcvbnmqwerty | 1 |
Deep mode uses that: it splits a saturated query into price bands, checks each one, and keeps splitting until every band fits under the cap.
Measured on nike / vinted.fr on 2026-08-13:
| Result | |
|---|---|
| Distinct items collected | 6,125 |
| What one Vinted query can ever return | 960 |
| Multiplier | 6.4× |
| Requests used | 129 (0.021 per item) |
| Duplicates in output | 0 |
That run stopped because it hit its 6,000-item target — not because the data ran out. It had covered only €1.00–€2.20 of the price range with 11 bands still queued, so 6.4× is a floor, not a ceiling.
It tells you when it did not get everything
Every run writes a RUN_SUMMARY record with per-query coverage, and the log says so plainly:
"nike" (fr): returned 2501 items but the result set was not exhausted- 17 price band(s) were left unwalked because maxItems was reached - raise it for more.
Three different things are reported separately, because conflating them is how tools mislead you:
unexploredBands— reachable; the run stopped at a budget.stopReasonsays which:targetItemsmeans raisemaxItems,probeBudgetmeans narrow the query or set a price range.truncatedBands— genuinely unreachable; more than 960 items share one exact price, so no price split can separate them. An honest limit, stated rather than hidden.failedBands— a price range whose size could not be read because the request failed. Those items are unaccounted for, and the run says so instead of counting the band as empty.
How to scrape Vinted search results
Type keywords, pick markets, run.
{"searchQueries": ["nike air max", "adidas samba"],"markets": ["fr"],"maxItems": 500}
For a complete pull of a large query, turn on deep mode and raise the ceiling:
{"searchQueries": ["nike"],"markets": ["fr"],"deep": true,"maxItems": 20000}
How to scrape a Vinted URL
Paste any Vinted URL — filtered catalog, item, or member page. Filters in the URL are carried over, and the country comes from the domain.
{"startUrls": ["https://www.vinted.fr/catalog?search_text=levis&price_to=25&brand_ids=7","https://www.vinted.pl/items/9651715467-nike-air-max-720","https://www.vinted.de/member/3175818454-someseller"]}
How to scrape a Vinted seller's closet and reviews
{"startUrls": ["https://www.vinted.fr/member/3175818454-someseller"],"includeSellerProfile": true,"includeSellerReviews": true,"maxReviewsPerSeller": 50}
Returns the seller's profile, their listings, and the reviews buyers left — three row types most Vinted tools do not return at all.
The two real sale signals. Vinted has no sold-listings search, but two fields leak actual transactions:
soldItemCounton a seller row is their lifetime completed sales, next toitemCount(still listed). Together they are a genuine sell-through ratio.- Each review carries
itemIdandcreatedAt— a review only exists after a transaction on that item. CheckisAutomaticfirst: Vinted posts system feedback for cancellations too ("Évaluation automatique : l'acheteur a annulé la transaction"), so onlyisAutomatic: falserows evidence a completed sale.
How to scrape Vinted item descriptions
Descriptions are not in the search response. Turn on includeItemDetail and each item gets one extra fetch:
{ "searchQueries": ["carhartt jacket"], "includeItemDetail": true, "maxItems": 50 }
Output
One row per listing. Every field is either a real value or null — never a guess.
{"type": "listing","id": "9650298818","url": "https://www.vinted.fr/items/9650298818-nike-air-max-blanche","title": "Nike air max blanche","brand": "Nike Air","size": "44","condition": "New with tags","price": 64,"currency": "EUR","buyerProtectionFee": 3.9,"totalPrice": 67.9,"favourites": 5,"views": 0,"photoCount": 7,"photos": ["https://images1.vinted.net/t/05_0209f_.../f800/1786616038.jpeg"],"listedAt": "2026-08-13T10:13:58.000Z","sellerId": "3168303451","sellerLogin": "arkalimal","sellerUrl": "https://www.vinted.fr/member/3168303451-arkalimal","sellerIsBusiness": false,"isPromoted": false,"market": "fr","description": null,"color": null,"scrapedAt": "2026-08-13T13:28:29.908Z"}
Three details worth knowing:
conditionis in English on every market. Vinted localizes it (Très bon état,Sehr gut,Bardzo dobry), which makes a multi-market dataset impossible to filter. The session requests English, so you getVery goodeverywhere.totalPriceis what the buyer actually pays —priceplus Vinted's Buyer Protection fee. Comparing rawpriceacross listings understates the real cost.listedAtis an approximate listing date. Vinted's search response has no creation timestamp at all; this is the upload time of the item's first photo, which is the closest proxy the API exposes. Accurate to the day, not the second.
Which markets exist, and the one thing nobody tells you about them
27 markets, verified live on 2026-08-13 — the domain resolved, returned HTTP 200, and yielded listings:
fr de uk us pl lt es it nl be cz sk at lu pt se dk fi ro hu gr ie hr si lv ee au
Currencies observed: EUR, GBP, USD, PLN, CZK, SEK, DKK, RON, HUF, AUD.
Not included, and why: vinted.no, vinted.ch and vinted.com.tr do not resolve; vinted.ca returns HTTP 403; vinted.bg serves the Swedish catalog in SEK (98% of its listings are identical to vinted.se, versus 0% overlap with vinted.fr), so it is not a Bulgarian market and is excluded.
Vinted is one catalog, not 27 marketplaces
This matters for your bill, so here is the measurement rather than the marketing.
| Comparison | Common item IDs | Same price and currency |
|---|---|---|
nl vs be | 91 | 91 |
fr vs de | 68 | 68 |
Identical listings, identical prices. And where the currency differs, the price is a straight conversion:
| Item | Sweden | Denmark |
|---|---|---|
9651853828 | 285.42 SEK | 193.28 DKK |
9651868165 | 181.63 SEK | 123.00 DKK |
Median implied rate 0.6772 across 93 shared items — the actual SEK→DKK rate, with a 2.4% spread that is rounding.
Two consequences:
-
Adding EU markets multiplies your cost far more than it adds unique listings. Scrape
frand you have most of whatde,nlandbewould return. We put this in the input schema too, rather than selling you a bigger number. -
A "cross-country price gap" computed on the same item ID is an FX artifact, not arbitrage. Any tool comparing raw numbers across markets without normalizing currency reports noise as opportunity.
To be precise about what this does and does not say: cross-border reselling is a real business. What is not real is a same-listing price gap. Genuine dispersion is within a market (two sellers pricing the same model differently) and across platforms (Vinted versus eBay sold). Both need the full price distribution for a query — which is what deep mode exists to give you, and what a 960-item sample cannot.
What this actor does not do, and why
These are commonly advertised. We could not make them work against the public API, so we do not ship them rather than shipping something that returns nothing.
- A searchable sold-listings feed. Vinted deletes sold listings from search and exposes no sold flag, so there is no sold-price history to scrape from the public API. We checked the endpoints this actor uses and found no sold filter that returns data. What this actor does give you is the two genuine sale signals the API leaks, both documented below rather than dressed up as a sold feed: a seller's lifetime
soldItemCount, and per-reviewitemId+ timestamp. - Cross-country arbitrage signals. See the measurement above: within the shared EU pool the same item is the same listing at a converted price. We return
price,currencyandtotalPriceso you can normalize deliberately, rather than shipping a gap number that is mostly FX. - Item measurements and full attribute sets. Not exposed by the endpoints this actor uses.
Using it from Python
There are good open-source Vinted wrappers. They break when Vinted changes its session handling or tightens Datadome, and you maintain that yourself. If you would rather not:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("vonsensey/vinted-scraper-api").call(run_input={"searchQueries": ["nike air max"],"markets": ["fr"],"deep": True,"maxItems": 5000,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["price"], item["currency"])
Node.js, direct HTTP, CSV/Excel download, webhooks and scheduling all work the same way — the dataset is a standard Apify dataset.
Notes on reliability
Residential proxy is required, and it is the default. Here is the measurement rather than a vague warning: Vinted is fronted by Datadome, and from an Apify datacenter IP the very first API call is answered HTTP 403 — with browser-shaped TLS and Chrome headers, not just with a plain HTTP client. The identical build through Apify Proxy RESIDENTIAL returns data on the first try.
| Configuration (run on Apify, 2026-08-13) | Result |
|---|---|
Datacenter IP, plain fetch | HTTP 403, 0 rows |
| Datacenter IP, browser TLS + Chrome headers | HTTP 403, 0 rows |
Apify Proxy RESIDENTIAL | 20 rows, first request, no retries |
That is our measurement on Apify's infrastructure, and it is why the residential default is set for you — you do not need to configure anything. If you run this code somewhere else, measure it there before assuming a proxy is optional.
- A blocked run costs you nothing. Blocked requests produce free error rows, never charges. The 403 runs above billed $0.00.
- Blocks are detected by content, not status code. An
HTTP 200carrying a Datadome interstitial is treated as a block and the session is rebuilt, rather than being recorded as zero results. - Migration-safe. Apify restarts containers routinely. Delivered rows are checkpointed, so a resumed run does not re-deliver or re-charge them.
What a run costs
Pricing is per event. Rows that arrive in bulk from one request are cheap; rows that need their own request cost more.
| Event | What it is | FREE tier | Volume tiers down to |
|---|---|---|---|
listing | A listing row, arriving 96 per request | $0.0030 | $0.0012 |
seller-review | A review row, also arriving in bulk | $0.0030 | $0.0012 |
seller | A seller profile — its own request | $0.0060 | $0.0024 |
item-detail | A listing upgraded with its description | $0.0200 | $0.0140 |
Why item-detail is the expensive one. Vinted publishes descriptions only on the item page, never in the search API, and that page is ~350 KB over a residential proxy — roughly 70× the bandwidth of a listing row. We measured it at $5.50 per 1,000 rows to serve, against $0.071 per 1,000 for plain listings. The price reflects that honestly rather than burying it. Leave includeItemDetail off unless you need descriptions.
There is no actor-start fee, so a run that returns nothing costs nothing — that promise only works without one.
item-detail replaces the listing charge for that row, it is not added on top. You are never billed twice for one row.
Deep mode costs nothing extra. It is the product, not an upsell.
Input reference
| Field | Type | Default | What it does |
|---|---|---|---|
searchQueries | array | ["nike"] | Keywords, run against every selected market |
startUrls | array | — | Any Vinted catalog, item or member URL |
markets | array | ["fr"] | Country markets for keyword searches |
maxItems | integer | 100 | Hard ceiling on billable rows. 0 = unlimited |
deep | boolean | false | Split past the 960-item cap |
priceMin / priceMax | integer | — | Price filter, in the market's currency |
sortBy | enum | relevance | relevance, newest_first, price_low_to_high, price_high_to_low |
includeItemDetail | boolean | false | Fetch descriptions and colour |
includeSellerProfile | boolean | false | Emit seller rows for member URLs |
includeSellerReviews | boolean | false | Emit review rows for member URLs |
maxReviewsPerSeller | integer | 25 | Cap on reviews per seller |
maxConcurrency | integer | 5 | Targets in flight at once |
requestDelayMs | integer | 250 | Pause between requests per market |
Legal
Reads only publicly visible Vinted pages — no login, no private data, no personal data behind authentication. You are responsible for how you use the output, including GDPR obligations where seller information counts as personal data. Not affiliated with Vinted.