# Resale Marketplace Comps & Repricing (`conceivable_extension/resale-marketplace-comps`) Actor

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.

- **URL**: https://apify.com/conceivable\_extension/resale-marketplace-comps.md
- **Developed by:** [joseph fadero](https://apify.com/conceivable_extension) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 item comp returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Resale Marketplace Comps & Repricing

**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 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

| Mode | Input | Output |
|---|---|---|
| `item_comp` | `searchQuery` (+ optional `brand`/`size`/`condition`) | One comp result |
| `bulk_repricing` | `itemList` | One comp result per item |

### Output schema

```json
{
  "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.

# Actor input Schema

## `mode` (type: `string`):

item\_comp: one search, full price-comp stats. bulk\_repricing: run item\_comp across every entry in itemList.

## `platform` (type: `string`):

Which marketplace to search. Confidence varies significantly by platform — see README before choosing. Poshmark is the only platform verified working end-to-end during this build; Vinted/Depop/StockX/Mercari are best-effort (real anti-bot systems blocked direct verification).

## `searchQuery` (type: `string`):

Free-text search, e.g. 'levi 501'. Required when mode is item\_comp.

## `brand` (type: `string`):

Optional, appended to the search query for more precise matching.

## `size` (type: `string`):

Optional, appended to the search query for more precise matching.

## `condition` (type: `string`):

Optional, appended to the search query for more precise matching.

## `itemList` (type: `array`):

One entry per item to comp. Each item: { "brand": "string", "itemName": "string", "size": "string", "condition": "string" }. Required when mode is bulk\_repricing.

## Actor input object example

```json
{
  "mode": "item_comp",
  "platform": "poshmark",
  "searchQuery": "Levi's 501 jeans",
  "itemList": [
    {
      "brand": "Levi's",
      "itemName": "501 jeans",
      "size": "32x32",
      "condition": "good"
    }
  ]
}
```

# Actor output Schema

## `resultsDatasetUrl` (type: `string`):

Real sold-price comparables (median, P10/P90, sell-through rate) per search across Depop, Poshmark, StockX and Mercari, produced by this run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQuery": "Levi's 501 jeans",
    "itemList": [
        {
            "brand": "Levi's",
            "itemName": "501 jeans",
            "size": "32x32",
            "condition": "good"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("conceivable_extension/resale-marketplace-comps").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQuery": "Levi's 501 jeans",
    "itemList": [{
            "brand": "Levi's",
            "itemName": "501 jeans",
            "size": "32x32",
            "condition": "good",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("conceivable_extension/resale-marketplace-comps").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQuery": "Levi'\''s 501 jeans",
  "itemList": [
    {
      "brand": "Levi'\''s",
      "itemName": "501 jeans",
      "size": "32x32",
      "condition": "good"
    }
  ]
}' |
apify call conceivable_extension/resale-marketplace-comps --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,conceivable_extension/resale-marketplace-comps"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/seCsO8bBcgDBtRptl/builds/ZvnxxEuYTTwzQpTCB/openapi.json
