Resale Marketplace Comps & Repricing avatar

Resale Marketplace Comps & Repricing

Under maintenance

Pricing

from $4.00 / 1,000 item comp returneds

Go to Apify Store
Resale Marketplace Comps & Repricing

Resale Marketplace Comps & Repricing

Under maintenance

Real 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

joseph fadero

Maintained by Community

Actor 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

PlatformStatusBasis
Poshmark✅ VerifiedConfirmed 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-effortAPI 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-effortBoth webapi.depop.com and the main depop.com/search page returned 403 to every tested request pattern.
Mercari⚠️ Best-effortCloudflare challenge page confirmed on the search endpoint.
StockX⚠️ Best-effortCloudflare 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 own PlaywrightCrawler. This reliably crashed with an ENOENT on 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 against page.content(): Poshmark's page includes an inline hydration script that reads window.__INITIAL_STATE__ and deletes the global from the DOM synchronously during parsing — before page.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 a preNavigationHooks listener on the page's response event, 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

ModeInputOutput
item_compsearchQuery (+ optional brand/size/condition)One comp result
bulk_repricingitemListOne 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

EventPrice
Run started£0.05
Comp success£0.06
Comp, no data found£0.02
Comp failedfree

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.