Vestiaire Collective Scraper: New Listings, Price Drops & Sold avatar

Vestiaire Collective Scraper: New Listings, Price Drops & Sold

Pricing

from $3.42 / 1,000 listing returneds

Go to Apify Store
Vestiaire Collective Scraper: New Listings, Price Drops & Sold

Vestiaire Collective Scraper: New Listings, Price Drops & Sold

Vestiaire Collective scraper by keyword: title, brand, price, size, image and link per luxury resale listing, no login. Monitoring returns new listings, price drops, and gone or confirmed-sold ones with a running sell-through rate. Pay per listing returned; quiet runs are free.

Pricing

from $3.42 / 1,000 listing returneds

Rating

0.0

(0)

Developer

Adrian Voss

Adrian Voss

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Watch a search on Vestiaire Collective, get only what's new. A Vestiaire Collective alert for new listings, price drops and confirmed sold items since your last run, charged per new row, free on quiet days. Schedule it and send it to Discord, Slack, n8n, or to Google Sheets.

This actor searches Vestiaire Collective the way its own search bar does: type a keyword (a brand, a model, a category) and get one clean row per listing with the title, brand, price, a euro conversion, size, the main photo and the link. Turn on monitoring and each run returns only the listings that appeared, or got cheaper, since the previous run, plus, if you ask, the ones that disappeared — some confirmed sold by Vestiaire's own data, the rest presumed: a luxury resale price tracker and sold items tracker with a running sell-through rate.

What you type in searchesWhat you getExample
Brand + modelThe tightest match — this is how Vestiaire's own search bar works toochanel classic flap bag, hermes birkin 30
A single brand or category wordEverything under it — can be thousands of listings; only the newest maxListingsPerSearch come backchanel
brand: <name>A brand-only browse, no keywords at allbrand: Chanel

Be specific: model names narrow results. A one-word brand search returns whatever Vestiaire ranks first for it, not everything it has; add the model, size, or a distinctive word from the listing title to get the pieces you actually want.

Finding one exact item. Search the model name as specifically as you can (hermes birkin 30 togo beats hermes bag), then use includeKeywords to require a size, colour, or other detail, or maxListingsPerSearch set low with sort: "relevance" to see only the closest matches.

Keeping results to one brand. Set Brands (below the search settings) to a list of brand names — every line in searches is then restricted to those brands, resolved against Vestiaire's own brand list live (exact name, case-insensitive). A name Vestiaire doesn't recognize costs nothing and comes back as one row naming the closest matches instead of silently returning nothing or guessing an id. brand: Chanel as a search line does the same thing for just that one line, without touching the Brands setting.

Vestiaire has no structured "condition" field on its public search — condition only appears as free text inside the listing description, so this actor doesn't invent a condition column either way.

How to filter

All filters are optional and off by default — leave them all empty and you get exactly what this actor has always returned.

Only sold pieces, by seller country:

{ "searches": ["chanel classic flap bag"], "availability": "sold", "countries": ["FR", "IT"] }

Keeps only listings Vestiaire's own sold flag has marked sold, and only where the seller's country (the sellerCountry/country columns) is France or Italy. Case-insensitive, ISO 3166-1 alpha-2.

A price band on one brand, title-filtered:

{ "searches": ["birkin"], "brands": ["Hermes"], "minPrice": 8000, "maxPrice": 20000, "excludeKeywords": ["mini"] }

Restricts every search line to Hermes (resolved against Vestiaire's own brand list, exact name, case-insensitive), keeps only listings priced $8,000–$20,000, and drops anything whose title or brand mentions "mini".

Available only, must mention a size:

{ "searches": ["chanel bag"], "availability": "available", "includeKeywords": ["30"] }

Drops sold listings and keeps only titles or brands mentioning "30" (useful for a bag size like "Birkin 30"). includeKeywords/excludeKeywords match the listing's title and brand, not the title alone.

There is no conditions filter on this actor: Vestiaire's public search API has no structured condition field anywhere (see "How to search" above), so there is nothing to filter on and no condition column either.

Who it's for

  • Resellers and luxury flippers watching for underpriced pieces from a specific brand or model before anyone else grabs them.
  • Sniper-bot and alert-bot builders who want a stable JSON row per listing instead of maintaining their own scraper against a site with no public API docs.
  • Price researchers tracking what a bag, watch or jacket really sells for on the resale market, and how fast it sells.
  • Sourcing teams building a shortlist of listings across many searches at once, exported straight to Google Sheets.

Why this one

  • A real keyword search, not a personalized feed. Vestiaire Collective's public search API silently ignores the wrong field name and falls back to a "you may also like" feed instead of erroring — this actor uses the real one (confirmed live, not guessed), so results actually match what you typed.
  • Monitoring built in, not bolted on. deltaMode remembers what each watchlist has seen. New listings and price drops (with your own minimum drop %) come back; everything else is removed before billing. A quiet run returns one summary row and costs only the start fee.
  • Two sold signals, not one. A tracked listing that reappears with Vestiaire's own sold flag set is reported soldConfirmed: true — no guessing. A listing that simply vanishes gets gonePresumedSold only when it was priced at or under the market and stayed up more than one run, the same honest heuristic already shipped on this portfolio's Vinted and Marktplaats actors.
  • No login, no personal data. Vestiaire Collective's own site is Cloudflare-gated even to a plain request; this actor reaches its public search API without ever needing an account, a cookie, or a CAPTCHA. Seller identity (name, id) is never returned — only the seller's country.

What you get

By default each listing is its own row. Every row also repeats the search it came from.

FieldWhat it is
listingId, url, titleVestiaire's listing ID, the listing link and its title
brand, sizeAs shown on Vestiaire Collective
price, currencyThe asking price in the search country's currency
priceEurprice converted to euros at the ECB daily reference rate
soldVestiaire's own flag for this listing, as returned this run
createdAtVestiaire's own listing timestamp
imageUrlLink to the main photo (links only, nothing is downloaded)
sellerCountryThe seller's country — no seller name, id or other personal data is ever returned
listingStatus, country, listedAtThis portfolio's cross-marketplace standard names for sold/sellerCountry/createdAt above — same values, added alongside (not instead of) the existing columns. listingStatus is "available" or "sold" (Vestiaire has no separate reserved state)
isNew, changeType, firstSeenAtMonitoring: new, price-drop, gone, sold or seen, and when this watchlist first saw it
lastSeenAt, daysListedMonitoring: the last run that saw the listing, and days between first and last sighting
previousPrice, priceDropPctMonitoring: the price last seen and the drop in %, on price-drop rows
lastPrice, gonePresumedSoldMonitoring, on gone rows: the last price seen, and the presumed-sold flag (see below)
soldConfirmedMonitoring, on sold rows: always true — Vestiaire's own data confirmed the sale
sellThroughRateMonitoring: (gone + sold) listings / listings ever tracked by this watchlist, 0 to 1
medianPriceEurMonitoring: median euro price of everything the run read for this search
searchQuery, listingCount, totalAvailable, truncatedThe search summary
newCount, priceDropCount, goneCount, soldCount, monitorStatusMonitoring summary: NEW_ROWS, NO_NEW_ROWS or SEEDED

Not available anywhere on Vestiaire Collective's public search, so not in this actor: a structured numeric condition (it only exists as free text inside the full listing description, and as an internal filter id — this actor doesn't invent a column from either), and the seller's name or id.

Monitoring: new listings and price drops

The recipe most buyers use:

  1. Put your search in searches (keywords like "chanel bag" or "rolex submariner"), and turn on Only return results that are new, cheaper, gone or sold since the last run (deltaMode).
  2. Optionally turn on Seed silently so the first run remembers today's listings without sending them all to your webhook.
  3. Save it as a Task and add a Schedule in Apify.
  4. Add a webhook or integration on the Task for Run succeeded: Discord or Slack webhook, an n8n or Make automation, a Google Sheets append, or an HTTP call to your own bot.
{
"searches": ["chanel bag"],
"country": "US",
"maxListingsPerSearch": 120,
"deltaMode": true,
"skipFirstRun": true,
"alertOnNew": true,
"alertOnPriceDrop": true,
"minPriceDropPct": 10
}

How it decides:

  • New means this watchlist has never returned that listing ID before.
  • Price drop means the price is at least minPriceDropPct below the price last seen. The remembered price updates every run, so a second cut is measured from the latest price.
  • Unchanged listings are removed before you are billed. A run with nothing new returns one summary row with monitorStatus: NO_NEW_ROWS, listingCount: 0, and costs only the start fee.
  • Monitoring always searches newest-first, regardless of the Sort order setting — that's the only sort Vestiaire Collective's API is confirmed to return in a genuine, ordered sequence.
  • Each watchlist remembers up to 5,000 listings per search, oldest forgotten first, and forgets any listing it has not seen for 30 days.
  • The watchlist name is derived from your country, price and keyword filters, so two schedules with different filters never share a memory. Set deltaName to choose your own.

The window limitation. A run only sees the newest maxListingsPerSearch listings (120 by default). A listing that drops in price after it has slid out of that window is not seen again. For price-drop alerts keep searches narrow (brand plus model) or raise maxListingsPerSearch.

Sold signal and sell-through

Turn on Alert on gone/sold listings (alertOnGone) next to deltaMode and a watchlist also returns the listings it saw on its previous run that have since left the search — split honestly into two kinds, not lumped into one guess.

The honesty note. Vestiaire Collective does not always confirm a sale on the way out: a listing that sells is often just gone from search, exactly like a listing that was deleted, reserved, or edited so it no longer matches your filters. This actor only ever claims a confirmed sale when Vestiaire's own data says so:

  • changeType: "sold", soldConfirmed: true — a listing this watchlist was tracking came back in the same search response with Vestiaire's own sold flag set. This is a fact, not a guess: no extra request, no heuristic.
  • changeType: "gone", gonePresumedSold — a tracked listing vanished from the search entirely, with no such proof. gonePresumedSold: true only when its last price was at or under this run's median and it had been seen on 2 or more runs in a row — the same pattern of "cheap, sat for a while, then vanished" this portfolio's Vinted and Marktplaats actors already use. Otherwise it is only gone: withdrawn, edited out of your filters, or paused, as often as sold.
  • sellThroughRate is (gone + sold) listings / listings ever tracked, over the watchlist's lifetime. It is on every row (and the summary row of a quiet run), and counts both kinds even when alertOnGone is off.
  • medianPriceEur is the median euro price of everything the run read for the search, not just the rows returned.

How a run decides a listing is gone, not just out of view. A run only reads the newest maxListingsPerSearch listings. The actor remembers each listing's position in Vestiaire's newest-first feed (sortBy: "recency", confirmed live to be a genuine, ordered sort keyed on Vestiaire's own listing timestamp), counts the new arrivals above it, and calls a missing listing gone or sold only if it should still sit inside the window (with a margin of 2 places or 5%, whichever is larger). Listings near the bottom edge of the window are therefore never called gone/sold, so give a sold-signal watchlist some headroom. No check is made on a watchlist's first run, or on a run Vestiaire refused partway.

A gone or sold listing is reported once. If it reappears later (a cancelled sale, for example), it is quietly taken back off the sell-through count. Gone/sold rows are billed as ordinary listing rows, at the same price, only when alertOnGone is on; no extra request is ever made for them.

{
"searches": ["chanel bag", "rolex submariner"],
"maxListingsPerSearch": 200,
"deltaMode": true,
"deltaName": "sell-through-luxury",
"alertOnNew": false,
"alertOnPriceDrop": false,
"alertOnGone": true
}

Scheduled daily, that returns only the listings that went, split into confirmed sold and presumed, with daysListed and the running sellThroughRate: a Vestiaire Collective sold items tracker for a brand list, in a Google Sheet.

Price

  • Listing returned: $4.5 per 1,000 listings

Plus a $0.00005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (found:false) are never charged.

  • Listings: billed per listing returned, plus a small start fee per run (see the price above, set once this actor is published — this is a private, unpriced build as of this README).
  • Gone/sold listings (with "Alert on gone/sold listings" on) are ordinary listing rows at the same price. No separate event, no extra request.
  • A monitoring run with nothing new costs the start fee only. A search that returns nothing is never billed.

How to use

  1. In the Apify Console. Open the actor page and click Start — the searches field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. Via the API. Call it directly with a POST request — no Console needed once you have an API token:
    curl "https://api.apify.com/v2/acts/accountable_eel~vestiaire-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"searches":["chanel bag"]}'
  3. On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.

Tips:

  • Keep a search to a brand plus model ("chanel classic flap", "rolex submariner") for the cleanest price-drop and sold-signal tracking — a one-word brand search can have thousands of matches, and only the newest maxListingsPerSearch are ever seen.
  • includeKeywords and excludeKeywords match the title and brand before billing.
  • Only United States (country: "US") is live-verified end to end. The other country options are inferred from Vestiaire's own locale rules, not independently confirmed — treat them as best effort until proven otherwise.

Input

{
"searches": [
"chanel bag"
]
}

One search per line. Brand + model works best, the way Vestiaire's own search bar does — "chanel classic flap bag", "hermes birkin 30". Be specific: model names narrow results. Use "brand: Chanel" as a line to browse one brand with no keywords, or set Brands below to keep every search above to that brand. No login required. Accepted formats: chanel classic flap bag, hermes birkin 30, brand: Chanel, rolex submariner.

Sample output

queryfoundstatussearchQuerylistingCounttotalAvailabletruncatednewCountpriceDropCountgoneCountsoldCountmonitorStatussellThroughRatemedianPriceEurlistingslistingIdtitlebrandpricecurrencypriceEursizesoldcreatedAtimageUrlurlsellerCountryisNewchangeTypepreviousPricepriceDropPctfirstSeenAtlastSeenAtdaysListedlastPricegonePresumedSoldsoldConfirmedlistingStatuscountrylistedAtscrapedAt
chanel bagtrueOK<gone this run (no sale proof)><sell-through rate (lifetime)><median price this run (eur)><all listings found (full list)> <brand><price in eur (ecb daily rate)><sold (as returned this run)><listed on (vestiaire's own timestamp)><seller's country><is this listing new?><price drop %><last known price before it went gone/sold><presumed sold (no confirmation)><sold, confirmed by vestiaire's own sold flag><status (available/sold)><seller's country (iso alpha-2)><listed on (alias of createdat)>1970-01-01T00:00:00.000Z

Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

curl "https://api.apify.com/v2/acts/accountable_eel~vestiaire-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-X POST \
-H "Content-Type: application/json" \
-d '{"searches":["chanel bag"]}'

n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~vestiaire-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"searches":["chanel bag"]} (swap in an expression from an earlier node for a real value).

Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~vestiaire-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"searches":["{{search}}"]}, mapping the row's search into the searches array.

MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Vestiaire Collective Scraper | Apify" — the agent will find and run this actor.

Discord or Slack alerts without code. Schedule the monitoring Task, then add an integration: in n8n or Make, trigger on "Apify: run succeeded", read the run's dataset, skip rows where listingCount is 0, and post title, brand, price, currency and url to a Discord or Slack webhook. Google Sheets users can append the same rows to a sheet for a running price log.

vs. alternatives

What it costsWhat you getTrade-off
This actorPay per listing returned, quiet monitoring runs freeKeyword search, euro prices, built-in new-listing, price-drop, gone and confirmed-sold monitoring, sell-through rateSearch results only; no structured condition or seller name, because Vestiaire doesn't expose them publicly
Generic Vestiaire scrapers on the Apify StoreVariesA dump of search resultsRarely combine monitoring with a keyword search, so you rebuild "what's new" yourself
Self-hosted sniper bots (GitHub)Free, plus your server and timeFull controlBreak whenever Vestiaire changes its site; you maintain proxies, parsing and dedupe

Data & privacy

This actor reads public search results that anyone can see without logging in. It doesn't log in, solve CAPTCHAs, or reveal hidden seller details. Seller identity is never returned — no name, no id — only the seller's country, which Vestiaire's own search response already includes per listing. Photo links are returned as-is; nothing is downloaded. Not affiliated with Vestiaire Collective.

FAQ

Is this allowed? It collects the same public listing data your browser shows, for the searches you choose. It's built for monitoring a search, not for copying the marketplace. Check that your use fits Vestiaire Collective's terms and your local law.

Why did my monitoring run return nothing? Nothing new or cheaper appeared since the last run. You get one row with

monitorStatus: NO_NEW_ROWS
and are charged only the start fee. On the first run with "Seed silently" on, the status is SEEDED.

Does it find sold listings? Two ways. If Vestiaire's own data still shows the listing with its sold flag set, you get changeType: "sold", soldConfirmed: true — a fact, not a guess. If a tracked listing simply disappears with no such proof, you get changeType: "gone", with gonePresumedSold: true only when it looks like a sale (cheap, up for 2+ runs). See "Sold signal and sell-through" above.

What do I need to set up? Nothing. No Vestiaire account, no cookies, no proxy settings — the actor handles Vestiaire Collective's anti-bot protection on its own.

Can I get the seller's name? No. Only the seller's country is returned; names and ids are never collected.

Can an AI agent call this? Yes, through the Apify MCP server or the API call shown above. Ask for "Vestiaire Collective Scraper: New Listings, Price Drops & Sold".