Vestiaire Collective Scraper: Sold Items & Seller Intelligence avatar

Vestiaire Collective Scraper: Sold Items & Seller Intelligence

Pricing

from $16.00 / 1,000 listing results

Go to Apify Store
Vestiaire Collective Scraper: Sold Items & Seller Intelligence

Vestiaire Collective Scraper: Sold Items & Seller Intelligence

Scrape public Vestiaire Collective live and sold listings across 70 markets. Extract prices, seller countries, conditions, product details, price history, and duplicate/suspicious seller signals.

Pricing

from $16.00 / 1,000 listing results

Rating

0.0

(0)

Developer

KazKN

KazKN

Maintained by Community

Actor stats

1

Bookmarked

5

Total users

1

Monthly active users

12 days ago

Last modified

Share

What does Vestiaire Collective Smart Scraper do?

Unofficial community Actor. Not affiliated with, endorsed by, or operated by Vestiaire Collective. Use it only for public data and only where you have the required rights and authorization.

Collect public Vestiaire Collective listings, public sold-search observations, product details, seller-level aggregates, and duplicate-listing similarity evidence. Repeated runs can record observed price changes and carefully labelled availability transitions.

It is built for resale comparable analysis, sourcing workflows, catalogue enrichment, and recurring watchlists. Runs can be scheduled and consumed through the Apify API, webhooks, Make, n8n, JSON, CSV, Excel, or Google Sheets.

Run {} for a safe ten-result French-market sample, or choose the exact markets, sold mode, enrichment, and limits you need.

What You Can Extract

  • Live listing records from search terms and public Vestiaire category, search, seller-profile, and product URLs.
  • Configuration for 70 Vestiaire market codes, or selected markets only.
  • Seller-country filtering with sellerCountries, independent from the searched market. Unknown seller countries stay null.
  • Item condition filtering with Vestiaire condition IDs.
  • Optional title/model precision filtering with requiredKeywords.
  • Product detail enrichment from public product pages, with a real-browser fallback when the fast HTTP path is blocked.
  • Sold item records from Vestiaire's public sold search filter and public sold-items pages.
  • Public price observations and likely_sold tracking across repeated runs.
  • Tracking records that preserve seller metadata when known and respect seller-country filters.
  • Seller summary records from observed listings and sold items.
  • Duplicate-listing similarity records from descriptive public evidence.
  • Automatic deduplication when the same listing appears across several markets.
  • Diagnostic records when public requests fail before any records are collected.
  • Dataset views for listings, sold items, price history, seller summaries, risk signals, and run diagnostics.

How to use Vestiaire Collective Smart Scraper

  1. Run the default {} sample, add one or more searchTerms, or add public Vestiaire startUrls.
  2. Keep the safe ["FR"] default, choose ["ALL"] to search every supported Vestiaire market, or pass explicit codes such as ["FR", "US", "GB"].
  3. Leave sellerCountries as ["ALL"] to include every seller location, or pass explicit seller/item country codes such as ["FR", "IT"].
  4. Optionally set itemConditions to restrict results by Vestiaire item condition.
  5. Optionally set requiredKeywords when the search query is too broad, for example ["classic flap"] to exclude Trendy CC Flap results.
  6. Set maxListings for the number of listing-like records to collect, and maxDatasetRecords for the total dataset rows to push.
  7. Set collectionMode to active, sold, or combined. The legacy includeSoldItems input remains supported.
  8. Enable includeDetails, includeSellerInfo, or includeDuplicateSignals depending on the records you need.
  9. Schedule repeat runs with the same trackingStoreName to collect price observations and carefully inferred availability changes over time.

Dataset results can be exported from Apify as JSON, CSV, Excel, or consumed through the Apify API.

Reading The Output

Every dataset row includes a typed recordType, sourceMode, and collection timestamp. Listing-like rows keep all historical fields and add recordSchemaVersion, recordKey, canonicalUrl, marketCountry, productLocationCountry, fieldAvailability, fieldSources, changeSet, and inferences.

  • recordType tells you what the row is: listing, detail, sold_item, seller_summary, risk_signal, or diagnostic data.
  • displayStatus and isSold make active vs sold records clear in the Apify table.
  • itemSummary is a compact human-readable line for quick review.
  • country and marketCountry are the searched Vestiaire market/locale. sellerCountry is populated only from an explicit public seller field. productLocationCountry is separate.
  • condition is the item condition returned by Vestiaire when available. conditionFilter records the requested filter but never fabricates the observed condition.
  • Unknown availability flags remain null; displayStatus is Unknown until Vestiaire exposes a public state.
  • Apify dataset views select columns; they do not filter rows. For sold analysis, filter exported data or API results with recordType === "sold_item" and isSold === true.
  • OUTPUT includes maxListings, maxDatasetRecords, listingRecordsCollected, duplicateRecordsSkipped, sellerCountryRecordsSkipped, and precisionRecordsSkipped so runs are easier to debug.

Main data fields

FieldMeaning
recordTypelisting, sold_item, detail, seller_summary, risk_signal, or run_diagnostic
recordKeyDeterministic identity for the emitted record
listingId, canonicalUrlStable public listing identity
country, marketCountryMarket used for the request
productLocationCountryProduct location when explicitly exposed
sellerCountrySeller country only when explicitly exposed on the seller data
price, currency, originalPricePublicly displayed price observations
condition, conditionFilterObserved condition and separately requested filter
soldConfidence, soldSourceEvidence label for public sold records
fieldAvailability, fieldSourcesPer-field availability and provenance
changeSet, inferencesObserved changes and explicitly labelled inferred values

Country Selection

countries is optional.

  • Omit countries to use the bounded French default. Pass [] or ["ALL"] to search all 70 supported Vestiaire countries.
  • Pass explicit country codes such as ["FR", "US", "GB"] to restrict the run.
  • countries controls the Vestiaire market/locale searched. It is not the same as seller location.
  • sellerCountries controls the explicit seller location shown in sellerCountry.
  • Omit sellerCountries, pass [], or pass ["ALL"] to include every seller country.
  • Pass explicit seller country codes such as ["FR"] to keep only those sellers.
  • Do not combine ALL with explicit country codes.
  • Unknown country codes are rejected.
  • startUrls can point to any valid public Vestiaire Collective category, search, product, seller-profile, or sold-items URL regardless of selected countries.
  • Duplicate active listings returned by several markets are deduplicated by listingId.
  • When a seller-country filter is active, records without an explicit public seller country are skipped.

Supported Vestiaire countries: AD, AU, AT, BH, BE, BR, BG, CA, IC, CN, HR, CY, CZ, DK, EE, FI, FR, GF, PF, DE, GI, GR, GP, GG, HK, HU, ID, IE, IM, IL, IT, JP, JE, KW, LV, LB, LI, LT, LU, MY, MT, MQ, YT, MC, NL, NC, NZ, NO, PH, PL, PT, QA, RE, RO, SA, SG, SK, SI, ZA, KR, ES, BL, MF, SE, CH, TW, TH, AE, GB, US.

Currency note: some selected countries use a supported Vestiaire display currency such as EUR or USD when the local currency returns zero-price records from Vestiaire's public search API.

Item Condition Filter

itemConditions is optional.

  • Omit itemConditions or pass [] to include every item condition.
  • Pass one or more Vestiaire condition IDs to restrict active searches and sold-search collection.
  • Supported values: 1 = Jamais portรฉ avec รฉtiquette, 2 = Jamais portรฉ, 3 = Trรจs bon รฉtat, 4 = Bon รฉtat, 5 = Correct.
  • conditionFilter preserves the requested labels for provenance.
  • If Vestiaire does not return a condition, condition remains null; a selected filter is never copied into the observed field.

Precision Filter

requiredKeywords is optional.

  • Leave requiredKeywords empty to keep all results returned by Vestiaire for the search query.
  • Add one or more words or phrases to require them in the public title or model.
  • All required keywords must match. ["classic flap"] keeps Chanel Classic Flap handbag and removes Chanel Trendy CC Flap handbag.
  • Matching is case-insensitive and accent-insensitive.

Run Limits

  • maxListings limits listing-like records: listing, sold_item, and tracking rows.
  • maxDatasetRecords limits total dataset rows pushed, including product detail, seller_summary, risk_signal, and diagnostics.
  • maxItems is still accepted for backward compatibility as an alias of maxDatasetRecords. If maxDatasetRecords is set, it wins.
  • maxSearchPages is a global paid-page cap across countries, terms, sold searches, and start URLs. Its default is 25 and its hard maximum is 2,500.
  • With countries: ["ALL"], every country/requรชte combination gets at least a one-listing search budget while the global maxListings cap still controls total output.
  • If includeDetails, includeSellerInfo, or includeDuplicateSignals is enabled, set maxDatasetRecords higher than maxListings so enrichment rows are not capped out.
  • Hard safety ceilings apply: 20 terms, 100 start URLs, 10,000 listings, 25,000 dataset rows, 100 pages per market/query, 2,500 paid pages per run, and 360 runtime minutes.

Example Input: All Markets

{
"searchTerms": ["chanel classic flap", "gucci jackie bag"],
"collectionMode": "combined",
"countries": ["ALL"],
"maxListings": 100,
"maxDatasetRecords": 250,
"maxPagesPerCountry": 2,
"includeDetails": true,
"includeSellerInfo": true,
"includeDuplicateSignals": true,
"proxyConfiguration": {
"useApifyProxy": true
},
"missingRunsThreshold": 2
}

Example Input: Selected Markets And Seller Countries

{
"searchTerms": ["loewe puzzle bag"],
"countries": ["FR", "US", "GB"],
"sellerCountries": ["FR", "IT", "GB"],
"itemConditions": ["3", "4"],
"maxListings": 50,
"maxDatasetRecords": 75,
"maxPagesPerCountry": 1,
"includeDetails": false,
"includeSellerInfo": true
}
{
"searchTerms": ["chanel classic flap"],
"countries": ["ALL"],
"sellerCountries": ["FR"],
"itemConditions": ["3", "4"],
"requiredKeywords": ["classic flap"],
"maxListings": 20,
"maxDatasetRecords": 40,
"maxPagesPerCountry": 2,
"includeDetails": false,
"includeSellerInfo": false,
"includeDuplicateSignals": false,
"includeSoldItems": false
}

This searches all selected Vestiaire markets but only keeps listings whose seller country is explicitly returned as France. If the market returns the same listing several times, only one listing row is pushed.

Example Input: Sold Items Page

{
"startUrls": [
{
"url": "https://us.vestiairecollective.com/c/vip-sold-items-12125/"
}
],
"countries": ["US"],
"maxListings": 25,
"maxDatasetRecords": 25,
"includeSoldItems": true,
"includeDetails": false
}

With search terms, collectionMode: "sold" queries only Vestiaire's public sold-search filter; "combined" queries active and sold sources. With start URLs, sold paths become sold_item rows and direct product URLs become detail rows.

Output Examples

Listing:

{
"recordType": "listing",
"sourceMode": "SEARCH_API",
"country": "FR",
"query": "chanel classic flap",
"listingId": "101",
"title": "Chanel classic flap bag",
"brand": "Chanel",
"condition": "Trรจs bon รฉtat",
"conditionSource": "vestiaire_field",
"price": 4200,
"currency": "EUR",
"status": "available",
"displayStatus": "Available",
"url": "https://fr.vestiairecollective.com/women-bags/handbags/chanel/classic-flap-101.shtml",
"sellerUsername": "pariscloset",
"sellerCountry": "FR"
}

Sold item:

{
"recordType": "sold_item",
"sourceMode": "SOLD_SEARCH_API",
"country": "US",
"listingId": "303",
"title": "Saffiano leather tote",
"brand": "Prada",
"price": 650,
"currency": "USD",
"status": "sold",
"isSold": true,
"soldDisplayedPrice": 650,
"lastPublicPrice": 650,
"soldDetectedAt": "2026-06-06T12:01:00.000Z",
"soldSource": "api-search",
"soldConfidence": "api_sold_filter_verified"
}

Price observations across repeated runs:

{
"recordType": "listing",
"sourceMode": "TRACKING",
"listingId": "101",
"status": "likely_sold",
"sellerUsername": "pariscloset",
"sellerCountry": "FR",
"lastPublicPrice": 3900,
"currency": "EUR",
"likelySoldDetectedAt": "2026-06-06T12:01:00.000Z",
"priceHistory": [
{ "price": 4200, "currency": "EUR", "observedAt": "2026-06-01T12:00:00.000Z" },
{ "price": 3900, "currency": "EUR", "observedAt": "2026-06-04T12:00:00.000Z" }
]
}

Seller summary:

{
"recordType": "seller_summary",
"sellerId": "seller-1",
"sellerUsername": "pariscloset",
"sellerCountry": "FR",
"activeListingCountObserved": 12,
"soldListingCountObserved": 4,
"avgActivePrice": 1820,
"avgSoldPriceObserved": 1540,
"activeToSoldRatioObserved": 0.25,
"priceStatsByCurrency": {
"EUR": {
"activeListingCountObserved": 12,
"soldListingCountObserved": 4,
"avgActivePrice": 1820,
"avgSoldPriceObserved": 1540
}
}
}

Duplicate-listing similarity signal:

{
"recordType": "risk_signal",
"duplicateClusterId": "cluster-4c8f8e90a1c4f0b0d3c01f23",
"duplicateSignalScore": 0.95,
"riskSignalLevel": "medium",
"inferenceLabel": "duplicate_listing_similarity",
"duplicateReasons": ["same_title_brand_category", "same_image_url", "similar_price_band"],
"similarListingIds": ["101", "102"],
"sellerUsername": "pariscloset"
}

Run diagnostic:

{
"recordType": "run_diagnostic",
"diagnosticType": "public_request_error",
"ok": false,
"message": "Public Vestiaire request failed before any dataset records could be collected.",
"publicRequestErrors": [
{
"url": "https://fr.vestiairecollective.com/search/?q=chanel&page=1",
"statusCode": 403,
"message": "Vestiaire public request failed with HTTP 403"
}
]
}

Output Views

  • listings: live listing and tracking records.
  • sold_items: public sold item records.
  • product_details: detail enrichment columns for product descriptions, material, authentication, shipping, and breadcrumbs. Use rows with recordType === "detail".
  • price_history: tracking states and public price observations.
  • seller_summary: observed seller-level aggregates.
  • risk_signals: conservative duplicate-listing similarity evidence.
  • diagnostics: non-charged run diagnostics when public requests fail before records are collected.

Tracking Behavior

The Actor stores durable state in the named key-value store set by trackingStoreName, defaulting to vestiaire-smart-tracker.

  • First observation records the listing as active unless the page explicitly marks it sold.
  • Repeated observations append public price observations when the displayed price or currency changes.
  • A disappeared listing becomes missing first.
  • It becomes likely_sold only after missingRunsThreshold consecutive absences from comparable, complete snapshots.
  • Comparable snapshots are isolated by market, query, condition, precision keywords, and seller-country filters.
  • An explicit sold page state remains sold in later runs.
  • Seller fields are stored in tracking state when Vestiaire returns them, so later TRACKING records can preserve sellerId, sellerUsername, sellerCountry, and sellerUrl.
  • Seller-country filters also apply to TRACKING rows. Old tracking states without seller country are skipped when a restrictive sellerCountries filter is active.
  • The same listing can be seen through several market countries, but pushed listing/tracking rows are deduplicated by listingId.
  • Failed, capped, blocked, malformed, or otherwise partial snapshots do not mark previous listings as missing.
  • Tracking state is staged during collection and committed only after every planned dataset row is committed.

Billing And Limits

This Actor uses Pay Per Event billing. Search/start pages are charged only after a valid public response is parsed. Valuable records use Apify's atomic pushData(record, eventName) path, so a row is not made available without its matching paid event. A per-run in_flight checkpoint is written before that atomic call and becomes charged afterwards. A restarted run skips both completed emissions and the narrow uncertain state where Apify accepted the atomic call but the final checkpoint could not be written; this prevents duplicate output and rebilling. Every emitted row also carries a deterministic emissionId.

Live Pay Per Event setup:

Event nameTriggerFREEBRONZESILVERGOLD+
search-pageOne successfully fetched and parsed search, sold-search, or start URL page$0.0020$0.0018$0.0015$0.0012
listing-resultOne active listing or tracking result pushed to the dataset$0.025$0.020$0.018$0.016
sold-itemOne public sold item result pushed to the dataset$0.030$0.025$0.022$0.020
detail-enrichmentOne product detail enrichment row pushed to the dataset$0.007$0.006$0.005$0.004
seller-profileOne seller summary row pushed to the dataset$0.006$0.004$0.003$0.002
duplicate-clusterOne duplicate-listing similarity row pushed to the dataset$0.006$0.004$0.003$0.002

Billing notes:

  • listing-result is the primary buyer-facing event.
  • At BRONZE tier, listing-only runs are about $20.08 / 1,000 results assuming roughly 24 results per search page; listing + details is about $26.08 / 1,000. At GOLD+ tier, listing + details is about $20.05 / 1,000.
  • Keep the synthetic apify-actor-start event enabled at its default price.
  • Disable apify-default-dataset-item or set it to 0 because this Actor already charges explicit dataset-record events.
  • OUTPUT.searchPagesProcessed and OUTPUT.searchPagesCharged help verify page-level billing in smoke runs.
  • OUTPUT.maxSearchPages and OUTPUT.searchPageLimitReached show whether the global page-cost guard stopped a broad search.
  • OUTPUT.trackingCommitted confirms whether staged tracking and search indexes were committed after dataset output.
  • Memory is capped at 512-1024 MB in actor.json to avoid paying 4 GB run costs for lightweight HTTP scraping.

Limits:

  • Works with public pages only.
  • No login, cookies, private account data, or hidden seller data.
  • Sold prices are public displayed prices, not private settlement amounts.
  • Duplicate-listing signals are similarity evidence, not authenticity, fraud, or seller-trust decisions.
  • Live page structure can change; use small smoke runs before scaling.
  • The Actor is unofficial and is not affiliated with or endorsed by Vestiaire Collective.

Proxy Behavior

Apify Proxy is enabled by default through proxyConfiguration: { "useApifyProxy": true }. A blocked product-detail requestโ€”whether from a direct product URL or includeDetails search enrichmentโ€”retries once in Chromium through the same configured proxy and emits a detail row only when the public page is usable. Other blocked requests, or a failed browser fallback, produce a non-charged diagnostic. The Actor never silently retries outside the configured proxy.

Local Development

npm install
npm test
npm run test:coverage
npm run lint
npm run build
apify validate-schema
apify run --purge --input-file test/smoke/inputs/search-small.json