Poshmark Sold Comps & Resale Price Scraper avatar

Poshmark Sold Comps & Resale Price Scraper

Pricing

Pay per usage

Go to Apify Store
Poshmark Sold Comps & Resale Price Scraper

Poshmark Sold Comps & Resale Price Scraper

Scrape SOLD Poshmark listings into resale price comps: sold price, days-to-sell, condition, and size, plus a summary per search (median, p25, p75 sold price, comp confidence, and a suggested list price). Built for Poshmark's 403 blocking.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

KULQIZ

KULQIZ

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Poshmark Sold Comps and Resale Price Scraper

Search any brand, item, or keyword on Poshmark and get its SOLD comps: real sold price, days-to-sell, condition, size, and seller. Each run also returns a summary per search term: median, p25, and p75 sold price, average days-to-sell, a comp-confidence score, and a suggested list price. It does the pricing math for you.

Made for resellers, flippers, and sourcing sellers who price from real data. If you have asked "what does this actually sell for on Poshmark, and how fast?", this answers it.

Pay-per-result: you pay for the listing records you get, and maxItems caps the spend. Not affiliated with or endorsed by Poshmark.

Why this over the free Poshmark scrapers

Most Poshmark scrapers on the Store are free hobby projects. They hand you a raw listing dump and leave the analysis to you, and they tend to stall on Poshmark's 403 blocking. This one is built for the pricing decision:

  • Every run writes a per-search comps summary: median sold price, p25/p75, days-to-sell, price by condition, size and brand, a recency-weighted comp-confidence score, and a suggested list price.
  • It is built for Poshmark's 403 reality: proxy rotation, session retirement on a block, challenge-page detection with backoff, and a per-run data_quality record so you see the real block rate and completeness of your own run.
  • It is cheap: it reads Poshmark's search response directly and pages through results, with no headless browser and no per-listing page fetch. Measured around $0.20 per 1,000 results on datacenter proxy (150 comps for about 3 cents).
  • Fields Poshmark does not show come back null, never guessed. Records are schema-validated before they are written.

Every number below comes from a reproducible run in /benchmarks. There are no figures here we did not measure.

Benchmarks

Measured 2026-06-17. Re-run with the scripts in /benchmarks.

What we measuredResult
Live sold listings parsed (coach tabby, lululemon align, nike dunk)17
Passed schema validation17 / 17 (100%)
Core field completeness on live data (price, sold date, days-to-sell, brand, size, condition)100%
Sold comps returned by one search fetch44 / 39 / 16
Block rate, 24 paced requests from a plain datacenter IP, no proxy0 / 24 (0%)

The block-rate number is a floor, not a production figure. It was one IP, a short session, at modest paced volume. Poshmark's anti-bot escalates under sustained load, which is why every run writes a data_quality record and why residential proxy is available for heavy runs. We have not published a sustained-load block rate. Your run's data_quality is the real number.

We did not measure competitor block rates, accuracy, or price. We cannot run another Actor in a controlled way, so there are no competitor numbers here.

What you get

One dataset record per listing:

{
"itemId": "69bac03e74cb47e2344a7847",
"url": "https://poshmark.com/listing/Coach-Tabby-26-Black-Leather-...",
"title": "Coach Tabby 26 Black Leather",
"brand": "Coach",
"department": "Women",
"category": "Bags",
"size": "OS",
"condition": "Like New",
"color": "Black",
"originalRetailPrice": 395.0,
"listingPrice": 240.0,
"soldPrice": 240.0,
"currency": "USD",
"isSold": true,
"soldDateObserved": "2026-03-22",
"daysToSell": 4,
"likesCount": 47,
"commentsCount": 6,
"sellerUsername": "luxuryhandba",
"imageUrls": ["https://di2ponv0v5otw.cloudfront.net/posts/..."],
"scrapedAt": "2026-06-17T03:00:00Z",
"sourceQuery": "coach tabby"
}

One Key-Value Store record per search term (AGGREGATE-<slug>). Example shape (for measured numbers see Benchmarks and /benchmarks):

{
"query": "coach tabby",
"count": 44, "soldCount": 41,
"medianSoldPrice": 196.0, "p25SoldPrice": 160.0, "p75SoldPrice": 230.0,
"outliersRemoved": 2,
"avgDaysToSell": 12.2, "medianDaysToSell": 4,
"sellThroughRate": null,
"windowDays": 140, "pctSoldWithin30Days": 0.67, "pctSoldWithin90Days": 0.83,
"compConfidence": "medium",
"priceByCondition": { "Like New": 220.0, "New With Tags": 245.0, "Used": 150.0 },
"priceBySize": { "OS": 196.0 },
"pricingRecommendation": {
"listAt": 196.0, "fastSaleListAt": 160.0, "topDollarListAt": 230.0,
"expectedDaysToSell": 4, "confidence": "medium"
}
}

compConfidence is transparent: high needs at least 30 sold comps and at least 60% sold within 60 days, medium needs at least 10 sold comps, otherwise low. Price stats are outlier-trimmed (IQR fence) once the sample is large enough, so one mispriced bundle does not skew your median. sellThroughRate is null in the default sold-only mode, because a sold-only sample is 100% sold. Set soldOnly to false to sample sold and active and get a real rate.

A real example (live sample, June 2026)

From a small live sample, reproducible in /benchmarks. Time-to-sell varies a lot by category:

QueryMedian soldp25 to p75Median days-to-sell
coach tabby$195.50$160 to $2302
lululemon align$45.00$40 to $5019
nike dunk$59.50$39 to $8934

A Coach Tabby in good shape near $195 tends to move within days. A Nike Dunk at these prices sits much longer. Small live sample; compConfidence rises as you raise maxItems, since each search page exposes 16 to 44 comps.

Input

FieldTypeDefaultDescription
searchQueriesarray of stringrequiredSearch terms. Each is scraped on its own and gets its own aggregate.
brandstring(none)Keep only listings whose brand matches (case-insensitive).
departmentenum(none)Women, Men, Kids, Home, Electronics, Pets, or Other.
categorystring(none)Keep only listings whose category contains this text (e.g. Bags).
sizesarray of string(none)Keep only these sizes (e.g. ["M","L","OS","34"]).
conditionsarray of string(none)Keep only matching conditions (e.g. ["New With Tags"]).
soldOnlybooleantrueOnly collect SOLD listings. Set false for sell-through.
maxItemsinteger200Hard cap on total records across all queries. Caps cost.
includeSellerStatsbooleanfalseExperimental. Fetches each seller's closet; often null until verified, so off by default.
computeAggregatesbooleantrueWrite one summary record per query to the Key-Value Store.
maxConcurrencyinteger3Parallel pages. Keep low to stay polite and avoid blocks.
proxyConfigurationproxydatacenterDatacenter by default (cheapest, works at modest volume). Switch to RESIDENTIAL for heavy or blocked runs.

Example input:

{
"searchQueries": ["coach tabby", "lululemon align"],
"soldOnly": true,
"maxItems": 100,
"computeAggregates": true,
"proxyConfiguration": { "useApifyProxy": true }
}

Export the dataset as JSON, CSV, Excel, or HTML from the run's Dataset tab. Read the per-query summary from the Key-Value Store tab (AGGREGATE-<query-slug>), and the per-run reliability record at DATA_QUALITY.

Reliability and the 403 question

Poshmark blocks scraping with HTTP 403. This is the real risk for any Poshmark Actor, so here is the honest version instead of a slogan:

  • Datacenter proxy by default (cheapest, and it works for Poshmark at modest volume). Switch to residential for heavy or blocked runs.
  • The session pool retires IPs on 403, 429, or 503 and rotates to a fresh session.
  • A block or challenge page (including PerimeterX-style pages) triggers jittered backoff, a session rotation, then a retry. If a page stays blocked it is skipped and the run finishes with partial data instead of crashing.
  • Every run writes a DATA_QUALITY record: block rate, items returned versus requested, and per-field completeness. You measure reliability on your own run.
  • Measured on the platform: 150 comps across 4 paginated requests, 0 blocks, about 96% core completeness, around $0.21 per 1,000 results on datacenter (compConfidence reaches "high" at this sample). Your DATA_QUALITY record is the number for your run.

If yields drop, lower maxConcurrency, switch to residential proxy, and reduce maxItems.

How to run

In the Apify Console, open the Actor, paste the input, and click Start.

By API:

curl -X POST "https://api.apify.com/v2/acts/<username>~poshmark-sold-comps/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{ "searchQueries": ["coach tabby"], "maxItems": 50 }'

Local development:

pip install -r requirements.txt
apify run
python -m src.main --validate
python -m pytest -q
python -m benchmarks.fetch_live "coach tabby" --per-query 7
python -m benchmarks.measure_live

FAQ

Will Poshmark's 403 blocking break my run? It is the main risk for any Poshmark scraper. This one rotates sessions on a block, backs off, and finishes with partial data plus a DATA_QUALITY record rather than dying. Datacenter proxy is the default and cheapest; switch to residential for heavy or blocked runs.

Are these real sold prices? Yes, filtered to availability=sold_out. Poshmark exposes no separate final or offer amount, so soldPrice equals the listing price at the time of sale.

Why is sellThroughRate null? The default mode collects sold listings only, which is 100% sold by definition. Set soldOnly to false to sample sold and active and get a true rate.

Can I get eBay or Mercari comps? The engine sits behind a thin marketplace adapter, so another marketplace can be added without rewriting the crawler. Ask if you need one.

  • Public data only. It reads publicly visible listing pages. No login, credentials, tokens, or paywall bypass.
  • No personal data beyond public seller handles and stats. No buyer data.
  • Respect Poshmark's Terms of Service and your local laws. Scraping public pages is widely considered permissible, but Poshmark's ToS restricts automated access, and you are responsible for how you use this Actor and the data. Use modest volumes and cache results.
  • Intended for analytics and pricing research by resellers. Not affiliated with or endorsed by Poshmark.

Limitations and known-brittle spots

  • Sold price equals the listing price at the time of sale. Poshmark exposes no separate final amount.
  • Seller rating, sales, and followers are best-effort from the public closet page and may be null until verified for your region and layout.
  • Brand is seller-entered and sometimes inconsistent (for example "Coach" versus "Coach Tabby"), so priceByBrand is most useful across multi-brand queries.
  • Condition labels are normalized from Poshmark's internal codes. Uncommon codes fall back to New or Used, or the raw code, rather than guessing a grade.
  • Comps per query are bounded by how many sold results Poshmark has for the term; the Actor pages through them up to maxItems. Broad terms return thousands, narrow terms fewer.
  • Poshmark can change its DOM or payload at any time. Extraction is layered (embedded app-state first, then JSON-LD, then meta tags, then the DOM) and is verified against live HTML in /benchmarks. See NOTES.md for the exact brittle points.

Found this useful

If it saved you time, a short review on the Store helps other people find it. Found a bug or a missing field? Open an issue and it gets fixed.

See CHANGELOG.md. Current version: 0.4.0.