Vinted.fr - Listings, Item Detail & Seller Reviews avatar

Vinted.fr - Listings, Item Detail & Seller Reviews

Pricing

from $1.00 / 1,000 listing results

Go to Apify Store
Vinted.fr - Listings, Item Detail & Seller Reviews

Vinted.fr - Listings, Item Detail & Seller Reviews

Scrape Vinted.fr, France's C2C second-hand fashion marketplace: search with brand/price/condition/sort filters, paste item or seller URLs, or pull a seller's feedback history. Returns title, brand, price, condition, size, photos, seller rating per listing; reviews mode returns all seller ratings.

Pricing

from $1.00 / 1,000 listing results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Share

Vinted.fr Scraper: Listings, Item Detail & Seller Reviews

Vinted.fr Scraper turns Vinted.fr, France's C2C secondhand fashion marketplace, into structured listing and seller data. Search by keyword with brand, price, condition and sort filters, paste any item or seller/member link directly, or pull a seller's complete feedback history. Every listing carries identity, price, brand and photos out of the box, with full description, condition, size, material, colour and seller reputation available on request. Export to JSON, CSV or Excel, or read results straight through the API.

Why This Scraper?

  • Three ways in. Keyword/brand/category search with real source-side filters, paste any item or seller/member URL directly, or pull a seller's full feedback history.
  • Real search filters, not guesswork. Brand id, price range, condition and sort order map directly to Vinted.fr's own search parameters, verified to narrow results rather than being accepted and silently ignored.
  • Full item detail from the item's own page. Condition, size, material, colour, category and full description, read from the listing's own structured data and on-page attributes, not a third-party estimate.
  • Honest pricing. Vinted.fr shows a second, larger figure next to the listed price ("buyer protection included"), which is the current price plus a checkout fee, never a former price. This scraper reports only the real listed price and does not invent a wasPrice or discount field the marketplace itself doesn't expose.
  • Native seller feedback. Overall rating, feedback count and every individual review (reviewer, date, star rating, comment) sourced from Vinted.fr's own feedback system.
  • Built for schedules. Incremental mode returns only new, changed and reappeared listings on recurring runs; because a sold listing on a C2C marketplace is gone for good, a sold or removed listing comes back marked EXPIRED once a full scan confirms it.
  • Resume without re-billing. Continue one interrupted run from its own previous dataset without re-collecting or re-charging what it already delivered.

Use Cases

  • Resale price research: track a keyword or brand across the marketplace to benchmark asking prices, sizes and condition mix.
  • Deal and restock alerts: schedule a search with incremental mode on and get notified only about new or changed listings.
  • Seller due diligence: pull a seller's profile and complete feedback history before buying from or dealing with them.
  • Marketplace analytics: build a dataset of brand, price and condition trends for a category or set of keywords.
  • Storefront monitoring: watch one seller's whole listing catalogue for new items through URL mode's member enumeration.

Data You Get

Sample shape: values are illustrative placeholders, not from a live listing.

FieldExample
itemId"00000001"
title"Sample knitted jumper"
url"https://www.vinted.fr/items/00000001-sample-knitted-jumper"
brandTitle"Sample Brand"
priceAmount / currency15.0 / "EUR"
promotedfalse
isVisibletrue
photos[{"id": 1, "url": "https://images.example.com/000001.jpeg", "isMain": true}]
seller{"id": "00000002", "username": "sample_seller", "business": false} (search results leave username empty until Fetch item detail fills it)
mainImage (fetchDetails)"https://images.example.com/000001.jpeg"
description (fetchDetails)"Full listing description text appears here when present."
condition (fetchDetails)"Bon état"
conditionSchema (fetchDetails)"UsedCondition"
size (fetchDetails)"M"
material (fetchDetails)"Coton"
color (fetchDetails)"Bleu"
categoryPath (fetchDetails)"Femmes Vêtements"
catalogId (fetchDetails)"1242"
isReserved (fetchDetails)false
sellerUsername / sellerFeedbackRating / sellerFeedbackCount (fetchDetails)"sample_seller" / 0.98 (reputation score from 0 to 1) / 120
scrapedAt"2026-01-01T00:00:00+00:00"

Extra fields on listings: totalPrice and serviceFee (the buyer-protection figure shown next to the price, kept separate from the real listed priceAmount), favouriteCount, photoCount, image (the first photo), and flat seller fields sellerId, sellerUrl, sellerPhoto and isBusinessSeller. A field the source does not serve for a given row is returned empty (null) rather than guessed.

Listings read from a seller page (a /member/<id> link) also carry viewCount, isClosed, isHeavyBulky and itemClosingAction; results pages do not serve these, so they are empty on search, category and brand rows. With Fetch item detail on, every listing also gets category, categoryId, brandId, colors (every colour of the item) and sellerBadges (for example ["Pro"], empty for sellers without a badge). A listing whose item page could not be read is still returned from its listing card, carries a detailError note and is not charged the detail-enrichment event.

Detail enrichment also fills isHidden, instantBuy, canBuy, brand (id, title, slug), sellerId and sellerBusiness as flat fields; the seller's rating, feedback count and username appear both flat (matching the dataset's table view) and nested under seller.feedbackRating / seller.feedbackCount / seller.username, for the same values.

Reviews mode (mode: "reviews") returns a different row shape instead: reviewId, sellerId, itemId (of the reviewed purchase, when available), reviewerUsername, rating, body, isSystemFeedback, createdAt, reviewUrl, and the seller's current sellerFeedbackRating / sellerFeedbackCount attached to every review row.

When incrementalMode is on, every returned record (either shape) also carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt.

Output views

The dataset has four tabs in the Console and through ?view= in the API: overview (listings), detail (full item detail), reviews (seller feedback rows) and changes (changeType, changedFields, first and last seen, for Incremental runs).

How to Use

  1. Pick a mode: search (keyword/brand/category), url (paste item or seller/member links), or reviews (a seller's full feedback history).
  2. Fill in the fields for that mode, and turn on Fetch item detail if you want full description, condition, size, material, colour and seller reputation.
  3. Set Max items total (and optionally Max pages per search) to control run size and cost, then click Start.
  4. Download the dataset as JSON, CSV or Excel, or read it through the API.

Basic keyword search:

{
"mode": "search",
"queries": ["sample keyword"],
"maxItems": 20
}

Search with brand, price range, condition and sort:

{
"mode": "search",
"queries": ["sample keyword"],
"brandId": "53",
"minPrice": 5,
"maxPrice": 60,
"conditions": ["3", "4"],
"sortBy": "price_low_to_high",
"fetchDetails": true,
"maxItems": 20
}

Paste item and seller/member links:

{
"mode": "url",
"urls": [
"https://www.vinted.fr/items/00000001-sample-listing-title",
"https://www.vinted.fr/member/00000002"
],
"maxItems": 20
}

URL mode: supported link shapes. The seller, item, search, category and brand shapes below were fetched live through the Apify proxy (2026-10-27) and each returned its real content; m. links are accepted and mapped onto the main site but were not fetched under their own host. If you run URL mode with the URLs field untouched, it now scrapes one example of each distinct shape (a seller page, an item page, a keyword search page, a filtered search page, a sub-category page, a top-level category page and a brand page) instead of returning nothing. Clear the field or paste your own links to change that. A link in any other shape is skipped with a warning in the log, never silently.

Link shapeExampleWhat you get
Item pagevinted.fr/items/<id>-<slug>That one listing, with full detail
Seller pagevinted.fr/member/<id>Every listing the seller has
Search pagevinted.fr/catalog?search_text=nikeSearch results; search_text, catalog[], brand_ids[], status_ids[], color_ids[], size_ids[], material_ids[], price_from, price_to and order are honoured. Any other filter parameter on the link is not applied, and the log names it in a warning for that link
Category pagevinted.fr/catalog/<id>-<name>Listings in that category
Brand pagevinted.fr/brand/<id>-<name>Listings of that brand
Mobile and tracked linksm.vinted.fr/..., extra ?utm_... parametersTreated like the same link on the main site; tracking parameters are ignored

The default URLs value is one example of each of the seller, item, keyword search, filtered search, sub-category, top-level category and brand shapes. The m. host form is accepted but is not part of that default. Four more link shapes are accepted and are covered by a default entry, because they resolve to the same target (the page number is ignored and listings dedupe by id), so they are not repeated there:

Accepted link shapeCovered by the default entry
Seller link with a username slug (vinted.fr/member/<id>-<username>)Seller page (same seller id)
Item link with the id only (vinted.fr/items/<id>)Item page (same item id)
Item link on the vinted.com hostItem page (same item id)
Search link with a page number (...&page=2)Keyword search page (the page number is ignored)

The default only applies in URL mode; in search and reviews mode an untouched URLs field is ignored and does not change your Incremental state.

A page=N parameter is ignored: results always start from the first page and are bounded by Max pages per search. In search mode, Brand and Category accept a plain name (for example Nike or Robes; a shared name such as Baskets can be written as Hommes > Chaussures > Baskets) or a numeric id; an unknown brand, or a category name shared by several categories, stops the run with a message that says what to enter.

Pull a seller's full feedback history:

{
"mode": "reviews",
"sellers": ["00000002"],
"maxItems": 100
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/vinted-fr-scraper").call(run_input={"mode": "search", "queries": ["sample keyword"], "maxItems": 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["title"], item["priceAmount"], item["currency"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/vinted-fr-scraper').call({ mode: 'search', queries: ['sample keyword'], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

How Max items and Max pages per search shape a run

The item budget (Max items total) splits evenly across every query, member URL or seller in one run. Max pages per search additionally caps how many result pages are walked per entry; leave it at 0 to walk as many pages as needed, bounded by Max items and a 1000-page cap.

A search run with more than one keyword that gets capped by its per-keyword share of Max items partway through a result page keeps the rest of that page marked as already seen internally, even though those listings were never returned. If a later keyword in the same run matches any of those listings, they are silently skipped there as well, so they are returned by neither keyword and the run can end with fewer rows than Max items. Keep Max items high enough to clear a full page for each keyword (or use 0 for the 100,000 maximum, still bounded by Max pages per search) when several overlapping keywords run together, or split heavily-overlapping keywords into separate runs.

In Incremental mode specifically, the per-target budget of a keyword search, a seller's listing walk or a seller's review walk is drawn down as records are read, not only as they are actually returned; an unchanged, suppressed record still counts against the budget. On a recurring run where most previously-tracked records haven't changed, a walk can stop once it has read its share of the budget even though far fewer (or zero) new or changed rows were returned, while newer records further down the results stay unread; the run then reports that nothing changed. While the result order stays the same, later runs read the same first records and can keep missing those deeper changes. Raise Max items (up to the 100,000 maximum) above the size of the tracked scope on monitoring runs, and for searches consider sorting by newest first so fresh listings sit at the top of the walk.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset ID and the actor skips everything already collected there, so you don't pay twice.
  • Incremental mode (incrementalMode) is for scheduled runs over the same scope. A listing's favourite and view counts, the fee figures (serviceFee, totalPrice), the promoted flag and the seller's running feedback tally still appear in every row but never make a record UPDATED on their own, so a tracked listing is not returned (or billed) again just because someone favourited it. Each record is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run that scanned the whole scope, and only with emitExpired). stateKey names or shares the stored state. With Incremental mode off, output is exactly as before.
  • Turning on emitExpired adds a synthetic EXPIRED row for every tracked listing no longer found, once a run has fully scanned the tracked scope. These rows are added after Max items has already been applied to the run's freshly scraped listings, so a monitoring run with a large number of sold or removed listings can return, and be billed for, more rows in total than Max items specifies. If a hard per-run cap matters more than complete expiry tracking on a given run, leave emitExpired off, or expect the occasional oversized run when tracking a scope that turns over heavily.
  • Combining resumeFromRunId with Incremental mode, on a state key with no prior incremental baseline, folds every id the resumed run already delivered (listings, or reviews in reviews mode) into the new baseline as a bare placeholder (marked present, with nothing recorded to compare against yet). The first later ordinary run (without Resume) that reads each of those records then has nothing on file to diff beyond presence, so it returns, and bills, every one of them as UPDATED with every field listed in changedFields, even when nothing on the marketplace actually changed. This happens once per record, on the first run that reads it after the bootstrap (usually the next run, unless Max items stops that run before reaching it); treat those UPDATED rows as informational rather than a real change signal.
  • A manually set stateKey shared by runs with different searches, URLs, sellers or modes merges them into one tracked scope. With emitExpired on, a complete run of one configuration then marks every record tracked only by the other configuration as EXPIRED (and bills it), even though it was simply outside this run's scope, and it comes back as REAPPEARED when the other configuration runs again. Leave stateKey empty, or give each configuration its own key, unless every sharing run covers the same scope.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch, url, or reviews.
queriesarray(none)Free-text keywords (search mode). Item budget splits evenly across them.
categoryIdstring(none)Vinted catalog id (search mode, optional). Narrows a keyword search, or browses the whole category when Search keywords is left empty.
brandIdstring(none)Vinted brand name or numeric id (search mode, optional).
brandIdsarray(none)Extra brands as names or numeric ids, combined with brandId.
colorIdsarray(none)Numeric Vinted colour ids, as in the color_ids[] filter of a search URL. A non-numeric entry (for example blue) stops the run with a message naming it.
sizeIdsarray(none)Numeric Vinted size ids, as in the size_ids[] filter of a search URL. A non-numeric entry (for example M) stops the run with a message naming it.
conditionsarray(none)Restrict to one or more condition levels (search mode, optional). Leave empty for any condition.
minPriceinteger(none)Minimum price in EUR (search mode, optional).
maxPriceinteger(none)Maximum price in EUR (search mode, optional).
sortBystringrelevancerelevance, newest_first, price_low_to_high, or price_high_to_low.
urlsarrayfour sample linksItem, seller/member, search, category or brand links (url mode); see the link shapes table above. Filter fields above are ignored in this mode.
sellersarray(none)Numeric member ids or /member/<id> URLs to fetch feedback for (reviews mode). A plain username is not resolved to a member and is skipped.
fetchDetailsbooleantrueAdds full description, condition, size, material, colour, category, and the seller's feedback rating/count. Identity, price, brand and photos are already included without this toggle.
maxPagesinteger0Stop after this many result pages per keyword/category/URL entry, or per seller's reviews. 0 means the 1000-page cap. Bounded by Max items.
maxItemsinteger20Hard cap on total items (listings or reviews) returned across the whole run, and the review limit in reviews mode (split evenly across sellers). Maximum 100,000; 0 means that maximum.
proxyobjectApify ProxyThe connection to Vinted.fr. The run observes which connection works for your account and falls back automatically; see Plan Requirement.
mcpConnectorsarray(none)Optional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.
resumeFromRunIdstring(none)Continue one interrupted run without returning or charging for records already collected there.
ignoreFieldsForChangesarray[]Incremental mode only: field names (matched at any depth) that never make a record UPDATED; they are still returned.
incrementalModebooleanfalseTurn on for daily or recurring monitoring; returns only new, changed and reappeared records on later runs.
stateKeystring(none)Name this monitoring campaign to keep its state stable, or to deliberately share state across differently-configured runs. Auto-derived from mode/search/URL/seller/detail settings when left empty.
emitUnchangedbooleanfalseAlso return (and bill) records unchanged since the last run, marked UNCHANGED.
emitExpiredbooleanfalseAlso return (and bill) records no longer found since the last run, marked EXPIRED, once a run has fully scanned the tracked scope.

Output Example

Sample shape: values are illustrative placeholders, not from a live listing.

{
"itemId": "00000001",
"title": "Sample knitted jumper",
"url": "https://www.vinted.fr/items/00000001-sample-knitted-jumper",
"path": "/items/00000001-sample-knitted-jumper",
"brandTitle": "Sample Brand",
"priceAmount": 15.0,
"currency": "EUR",
"isVisible": true,
"promoted": false,
"photos": [
{ "id": 1, "url": "https://images.example.com/000001.jpeg", "width": 800, "height": 1200, "isMain": true }
],
"seller": {
"id": "00000002",
"username": "sample_seller",
"photo": "https://images.example.com/seller-000002.jpeg",
"business": false,
"feedbackRating": 0.98,
"feedbackCount": 120
},
"description": "Full listing description text appears here when present.",
"mainImage": "https://images.example.com/000001.jpeg",
"conditionSchema": "UsedCondition",
"condition": "Bon état",
"size": "M",
"material": "Coton",
"color": "Bleu",
"categoryPath": "Femmes Vêtements",
"catalogId": "1242",
"isReserved": false,
"sellerId": "00000002",
"sellerBusiness": false,
"sellerFeedbackRating": 0.98,
"sellerFeedbackCount": 120,
"sellerUsername": "sample_seller",
"scrapedAt": "2026-01-01T00:00:00+00:00"
}

Plan Requirement

Vinted.fr sits behind an anti-bot check, so this actor needs a working proxy connection. An Apify plan with proxy access is required: free plans do not include the Apify proxy. Measured on 2026-10-27: the default Apify proxy connection (Datacenter, no group chosen) served every page shape this actor reads (search, category and brand pages, seller pages, item pages and the seller listing and feedback routes), so the default is the cost-efficient choice. The run starts a short browser session through that connection to clear the check, then reads pages over a lightweight connection. If the default connection is refused it falls back automatically to Apify Residential and then to backup connections, and remembers which one your account is allowed to use. You do not have to change anything; if runs still fail, choose the Residential group under Proxy & connection or supply your own proxy URLs.

If the run cannot read any page it stops with one of these messages instead of returning an empty dataset:

  • The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required. Check your plan, or the credentials of your own proxy URLs.
  • No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Vinted pages. Upgrade your plan or supply your own proxy URLs.
  • Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Try again later.

On a free plan the log also prints a notice that the selected connection is unavailable and that the run continues on a backup connection, where some pages may still be unavailable.

FAQ

How much does it cost?

Billing is pay per event, with three events. A start event is charged once per run. A per-record event is charged for each listing or review row returned. A detail-enrichment event is charged per returned listing whose item page was read, only while Fetch item detail is on (it is on by default). Records suppressed by Incremental mode, skipped as already collected by Resume, or not pushed are never charged. The Pricing tab shows the current rates. Use Max items total to cap the cost of any run, and turn off Fetch item detail for the cheapest listing rows.

This actor collects only publicly available marketplace listings and seller feedback. You are responsible for how you use it: follow Vinted.fr's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Do not use it to collect personal data beyond what a listing or public feedback entry itself shows.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental changes for scheduled runs. Each run then returns only new, updated and reappeared records, and unchanged ones are not billed unless you turn on Emit unchanged records.

What's the difference between Resume and Incremental mode?

Resume from a previous run continues one specific interrupted run so you don't re-collect or re-pay for what it already delivered; you paste its run or dataset ID once. Incremental mode is for recurring monitoring of the same search, URLs or sellers: the actor remembers its own state between scheduled runs, so you never paste an ID, and it keeps classifying records as new, changed, unchanged, reappeared or expired every time it runs.

Why did my run return fewer listings than Max items?

Two run shapes can do this. First, in a search with more than one keyword, a result page cut short by a keyword's share of Max items still marks the rest of that page as seen internally, so any of those listings that a later keyword also matches are skipped there too and returned by neither; keep Max items high enough to clear a full page per keyword, or run heavily-overlapping keywords separately. Second, in Incremental mode, the per-target budget is drawn from records read during the walk, not only from ones actually returned, so a recurring run where most records are unchanged (and suppressed) can stop at its budget having returned far fewer rows than Max items, or none, even with newer records left unread; raise Max items above the tracked scope on recurring runs (and sort searches by newest first) if you want every change picked up.

Why did the run right after a Resume plus Incremental bootstrap mark everything UPDATED?

Starting Incremental mode together with resumeFromRunId on a fresh state key seeds every id the resumed run already delivered into the new baseline without a stored snapshot to compare against. The next ordinary run (without Resume) that reads each of those records finds nothing on file to diff beyond "it exists", and returns (and bills) it as UPDATED with every field listed as changed. This happens once per record, normally on the very next run; treat those UPDATED rows as informational. Once a record has been read this way, its classification is accurate from then on.

Why did my run fail instead of returning an empty dataset?

If the site refuses every request, the run stops with a clear message so "no listings match" is never confused with "nothing could be read". Run it again in a few minutes. If only some pages could be read, you still get what was found.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

🔗 Want more Vinted data?

Pair this actor with these related scrapers from the same team:

🏷️ Vinted Multi-Country Scraper
Scrape Vinted across 27 country marketplaces: keyword search with brand, price and...
🏷️ Leboncoin FR
Pull public leboncoin.fr listings across cars, property, jobs, electronics, furniture...
🏷️ ThredUp Scraper
Scrape ThredUp resale listings by keyword, department, brand, size, condition, price or...
🏷️ bol.com Scraper
Scrape bol.com products: title, price, list price and discount, EAN, brand, images...
🏷️ Daangn Scraper
Scrape Daangn (당근) marketplace listings by keyword and region. Returns 35+ fields per...
🏷️ Chrono24 Scraper
Scrape Chrono24 luxury watch listings by keyword, filters or URL. Extract 50+ fields...

👉 Browse all abotapi scrapers

💬 Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.