Resale Marketplace Comps & Repricing
Under maintenancePricing
from $4.00 / 1,000 item comp returneds
Resale Marketplace Comps & Repricing
Under maintenanceReal sold-price comps (not just asking prices) across Vinted, Depop, Poshmark, StockX, and Mercari — median, P10/P90, and sell-through rate per search, so resellers stop pricing inventory by eyeballing listings by hand.
Pricing
from $4.00 / 1,000 item comp returneds
Rating
0.0
(0)
Developer
joseph fadero
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Real sold-price comps, not asking prices — median, P10/P90, and sell-through rate per search, across Vinted, Depop, Poshmark, StockX, and Mercari. The only comparable Apify Store actor is v0.1 and Vinted-only, with Depop and Mercari explicitly flagged "coming in v0.2." Multi-platform coverage with real percentile stats (not just a median) is the differentiation here.
A finding worth being direct about
The build PRD assumed Vinted would be the easiest platform to scrape reliably (it's what the existing competitor covers) and expected it to ship first as the "baseline." Live testing while building this actor found the opposite: Vinted sits behind Datadome bot-protection that blocked even an authenticated session (a real access_token_web token, legitimately issued on a plain page load, still got a 403 on the actual catalog API). Depop 403s on both its API and its main search page. StockX and Mercari both serve a Cloudflare "Just a moment..." challenge page. Poshmark — priority #3 in the PRD, "round out coverage" — turned out to be the one platform that's genuinely, verifiably reliable, with real per-listing sold-price data via a documented availability=sold_out search filter.
This isn't a shortcut; it's what was actually found when tested. The build order below reflects that, not the PRD's original assumption.
Confidence by platform
| Platform | Status | Basis |
|---|---|---|
| Poshmark | ✅ Verified | Confirmed live: poshmark.com/search?availability=sold_out returns real embedded sold-listing data (price, title, size, brand) via a documented window.__INITIAL_STATE__ JSON blob. Tested against a real search ("levi 501") — 48 real sold listings, prices $29–$85. |
| Vinted | ⚠️ Best-effort | API confirmed blocked by Datadome even with a valid session token. Vinted's search also doesn't appear to expose a "sold items" filter at all (consistent with hiding sold listings from search by default) — sold-price comping on Vinted specifically may not be achievable via search at all, only via individual listing pages sellers haven't deleted. |
| Depop | ⚠️ Best-effort | Both webapi.depop.com and the main depop.com/search page returned 403 to every tested request pattern. |
| Mercari | ⚠️ Best-effort | Cloudflare challenge page confirmed on the search endpoint. |
| StockX | ⚠️ Best-effort | Cloudflare challenge page confirmed. Also structurally different from the others — StockX's real strength is its per-product "last sale" transaction data, not search-result scraping; a proper StockX integration would look quite different from this actor's search-based model. |
For the four best-effort platforms: real, reasonable code is implemented (Playwright + structural search over embedded page state, same technique used successfully for TikTok Shop in Actor 24), but none were confirmed working end-to-end. Try them, but verify against known real listings before trusting the output, same as the PRD's own Definition of Done asks for Vinted specifically.
Three more things found while building, not assumed
- Poshmark itself needed a browser, not a plain HTTP request — a subtlety worth knowing. Curl succeeds against Poshmark with a standard browser User-Agent; a Node/axios request with the identical header (and, tested separately, a full set of browser-realistic headers) gets a 403 from Poshmark's CloudFront-fronted WAF. This is a TLS/HTTP-client fingerprint distinction below the header layer — not fixable by adding more headers. This actor uses a real Playwright browser for Poshmark specifically because of this, not because Poshmark needed JS rendering (it doesn't; the data is in the initial server-rendered HTML).
- Two concurrent Playwright crawlers collide. The original design fetched "sold" and "active" listing counts in parallel via
Promise.all, each spinning up its ownPlaywrightCrawler. This reliably crashed with anENOENTon a shared request-queue lock file. Fixed by running them sequentially — a small time cost, and it actually works. - Reading
page.content()after navigation silently lost the data, even with a real browser. Confirmed by directly diffing the raw HTTP response body againstpage.content(): Poshmark's page includes an inline hydration script that readswindow.__INITIAL_STATE__and deletes the global from the DOM synchronously during parsing — beforepage.content()ever runs, no matter how long you wait first, headless or headful. It briefly looked like bot detection (the stripped page still has a correct title and real SSR markup) but wasn't — the raw response body, captured via apreNavigationHookslistener on the page'sresponseevent, is byte-identical to curl's and has the real data. Fixed for both Poshmark and the four best-effort platforms, since any of them could hit the same hydration pattern.
Modes
| Mode | Input | Output |
|---|---|---|
item_comp | searchQuery (+ optional brand/size/condition) | One comp result |
bulk_repricing | itemList | One comp result per item |
Output schema
{"platform": "poshmark | vinted | depop | mercari | stockx","searchQuery": "string","medianSoldPrice": "number | null","p10Price": "number | null","p90Price": "number | null","sellThroughRate": "number | null","activeListingCount": "number | null","soldListingCount": "number | null","currency": "string","checkedAt": "ISO timestamp","status": "success | failed"}
Percentiles use linear interpolation (the standard "R-7" method) — real percentiles, not min/max stand-ins, which is the differentiation the build PRD calls out versus the existing competitor's README (which suggests it may not go this deep).
sellThroughRate = sold / (sold + active) for the same search. Poshmark's own listing-count figures cap at a round number (observed: exactly 5000) for very broad searches rather than giving an exact count for extremely popular queries — treated as-is, not silently presented as more precise than it is.
Pricing
| Event | Price |
|---|---|
| Run started | £0.05 |
| Comp success | £0.06 |
| Comp, no data found | £0.02 |
| Comp failed | free |
Setup note
Playwright/Chrome base image (apify/actor-node-playwright-chrome:20) — every platform in this actor needs a real browser, including Poshmark (for the fingerprinting reason above, not JS rendering). Residential proxy strongly recommended for Vinted/Depop/StockX/Mercari given the real anti-bot systems confirmed in front of them.
n8n integration
- Workflow A (trigger): scheduled repricing run against a reseller's active inventory list.
- Workflow B (processing): flag items priced more than X% above/below current market median — same alerting pattern as the existing Shopify Tracker and TikTok Shop workflows, pointed at this actor's dataset.