Vestiaire Collective Scraper: Sold Items & Seller Intelligence
Pricing
from $16.00 / 1,000 listing results
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
Maintained by CommunityActor stats
1
Bookmarked
5
Total users
1
Monthly active users
12 days ago
Last modified
Categories
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 staynull. - 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_soldtracking 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
- Run the default
{}sample, add one or moresearchTerms, or add public VestiairestartUrls. - Keep the safe
["FR"]default, choose["ALL"]to search every supported Vestiaire market, or pass explicit codes such as["FR", "US", "GB"]. - Leave
sellerCountriesas["ALL"]to include every seller location, or pass explicit seller/item country codes such as["FR", "IT"]. - Optionally set
itemConditionsto restrict results by Vestiaire item condition. - Optionally set
requiredKeywordswhen the search query is too broad, for example["classic flap"]to exclude Trendy CC Flap results. - Set
maxListingsfor the number of listing-like records to collect, andmaxDatasetRecordsfor the total dataset rows to push. - Set
collectionModetoactive,sold, orcombined. The legacyincludeSoldItemsinput remains supported. - Enable
includeDetails,includeSellerInfo, orincludeDuplicateSignalsdepending on the records you need. - Schedule repeat runs with the same
trackingStoreNameto 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.
recordTypetells you what the row is:listing,detail,sold_item,seller_summary,risk_signal, or diagnostic data.displayStatusandisSoldmake active vs sold records clear in the Apify table.itemSummaryis a compact human-readable line for quick review.countryandmarketCountryare the searched Vestiaire market/locale.sellerCountryis populated only from an explicit public seller field.productLocationCountryis separate.conditionis the item condition returned by Vestiaire when available.conditionFilterrecords the requested filter but never fabricates the observed condition.- Unknown availability flags remain
null;displayStatusisUnknownuntil 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"andisSold === true. OUTPUTincludesmaxListings,maxDatasetRecords,listingRecordsCollected,duplicateRecordsSkipped,sellerCountryRecordsSkipped, andprecisionRecordsSkippedso runs are easier to debug.
Main data fields
| Field | Meaning |
|---|---|
recordType | listing, sold_item, detail, seller_summary, risk_signal, or run_diagnostic |
recordKey | Deterministic identity for the emitted record |
listingId, canonicalUrl | Stable public listing identity |
country, marketCountry | Market used for the request |
productLocationCountry | Product location when explicitly exposed |
sellerCountry | Seller country only when explicitly exposed on the seller data |
price, currency, originalPrice | Publicly displayed price observations |
condition, conditionFilter | Observed condition and separately requested filter |
soldConfidence, soldSource | Evidence label for public sold records |
fieldAvailability, fieldSources | Per-field availability and provenance |
changeSet, inferences | Observed changes and explicitly labelled inferred values |
Country Selection
countries is optional.
- Omit
countriesto 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. countriescontrols the Vestiaire market/locale searched. It is not the same as seller location.sellerCountriescontrols the explicit seller location shown insellerCountry.- 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
ALLwith explicit country codes. - Unknown country codes are rejected.
startUrlscan 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
itemConditionsor 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. conditionFilterpreserves the requested labels for provenance.- If Vestiaire does not return a condition,
conditionremainsnull; a selected filter is never copied into the observed field.
Precision Filter
requiredKeywords is optional.
- Leave
requiredKeywordsempty to keep all results returned by Vestiaire for the search query. - Add one or more words or phrases to require them in the public
titleormodel. - All required keywords must match.
["classic flap"]keepsChanel Classic Flap handbagand removesChanel Trendy CC Flap handbag. - Matching is case-insensitive and accent-insensitive.
Run Limits
maxListingslimits listing-like records:listing,sold_item, and tracking rows.maxDatasetRecordslimits total dataset rows pushed, including productdetail,seller_summary,risk_signal, and diagnostics.maxItemsis still accepted for backward compatibility as an alias ofmaxDatasetRecords. IfmaxDatasetRecordsis set, it wins.maxSearchPagesis 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 globalmaxListingscap still controls total output. - If
includeDetails,includeSellerInfo, orincludeDuplicateSignalsis enabled, setmaxDatasetRecordshigher thanmaxListingsso 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}
Example Input: French Seller Deal Search
{"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 withrecordType === "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
missingfirst. - It becomes
likely_soldonly aftermissingRunsThresholdconsecutive 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
soldin later runs. - Seller fields are stored in tracking state when Vestiaire returns them, so later
TRACKINGrecords can preservesellerId,sellerUsername,sellerCountry, andsellerUrl. - Seller-country filters also apply to
TRACKINGrows. Old tracking states without seller country are skipped when a restrictivesellerCountriesfilter 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 name | Trigger | FREE | BRONZE | SILVER | GOLD+ |
|---|---|---|---|---|---|
search-page | One successfully fetched and parsed search, sold-search, or start URL page | $0.0020 | $0.0018 | $0.0015 | $0.0012 |
listing-result | One active listing or tracking result pushed to the dataset | $0.025 | $0.020 | $0.018 | $0.016 |
sold-item | One public sold item result pushed to the dataset | $0.030 | $0.025 | $0.022 | $0.020 |
detail-enrichment | One product detail enrichment row pushed to the dataset | $0.007 | $0.006 | $0.005 | $0.004 |
seller-profile | One seller summary row pushed to the dataset | $0.006 | $0.004 | $0.003 | $0.002 |
duplicate-cluster | One duplicate-listing similarity row pushed to the dataset | $0.006 | $0.004 | $0.003 | $0.002 |
Billing notes:
listing-resultis the primary buyer-facing event.- At BRONZE tier, listing-only runs are about
$20.08 / 1,000results 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-startevent enabled at its default price. - Disable
apify-default-dataset-itemor set it to0because this Actor already charges explicit dataset-record events. OUTPUT.searchPagesProcessedandOUTPUT.searchPagesChargedhelp verify page-level billing in smoke runs.OUTPUT.maxSearchPagesandOUTPUT.searchPageLimitReachedshow whether the global page-cost guard stopped a broad search.OUTPUT.trackingCommittedconfirms whether staged tracking and search indexes were committed after dataset output.- Memory is capped at
512-1024 MBinactor.jsonto 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 installnpm testnpm run test:coveragenpm run lintnpm run buildapify validate-schemaapify run --purge --input-file test/smoke/inputs/search-small.json