# eBay Sell-Through & Sold Price Comps · 90 Days (`doesaiknow/ebay-comps-sell-through`) Actor

Median sold price, p25-p75 band, sell-through rate and active-listing count for any eBay search. One row per product, 7/30/90-day window, per-condition breakdown, optional Amazon price spread. Pay per delivered report; a repeat of the same search within 24 hours is free.

- **URL**: https://apify.com/doesaiknow/ebay-comps-sell-through.md
- **Developed by:** [David S](https://apify.com/doesaiknow) (community)
- **Categories:** E-commerce, SEO tools
- **Stats:** 2 total users, 1 monthly users, 87.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.05 / product report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## eBay Product Research: Sold Prices & Sell-Through Comps

Run **eBay product research** on a list of product phrases and get one decision-ready row each:
the median **sold price** with its p25–p75 band, the **sell-through rate**, how many competing
listings are live right now, and how fast the product moves per day.

Built for resellers, dropshippers, liquidation buyers, and category managers who decide what to
buy and what to charge — not for people who want 10,000 raw listing rows to pivot by hand. One
search in, one row out, **$0.05 per report** at the volume tier.

### What does the eBay comps actor do?

You give it product phrases (or full eBay search URLs). For each one it reads the sold listings
inside a 7-, 30-, or 90-day window and the active listings competing for the same search, then
answers the three questions behind a buying decision: **what does it sell for**, **how often does
a listing actually sell**, and **how fast**. Prices come back as a median plus a p25–p75 band, so
you see the price the market pays and the spread around it, split per item condition.

It is an aggregator, not a listing dump: it returns one row per product, not a page of offers.

### Why use this eBay sell-through calculator

- **Median sold price, not asking price** — p25/p75 band from realized sales inside your window.
- **Sell-through rate** = sold ÷ active listings, the demand-vs-supply ratio eBay does not show.
- **Counts you can trust** — de-duplicated by item ID, and every count carries an exactness flag.
- **Sales pace and trend** — sold per day, plus the percent change between the newer and older half
  of the window, so a flat median does not hide a collapsing category.
- **Per-condition breakdown** — New, Pre-Owned and Refurbished each get their own count and median.
- **Optional Amazon spread** — when the product publishes a UPC, the row adds the Amazon price and
  the percentage gap against your eBay median.
- **Repeat searches are free for 24 hours** — the same search, window and filters is re-delivered
  from cache and not billed as a report.

### How to check eBay sold prices and sell-through

1. Open the **Input** tab and paste your product phrases into **Product searches**, one per line
   (a full eBay search URL works too, and overrides the filters below it).
2. Pick the **eBay marketplace** — 14 sites, from `EBAY_US` to `EBAY_GB` and `EBAY_DE`. All prices
   come back in that marketplace's currency.
3. Pick the **sales window**: 7, 30, or 90 days. 30 days is the usual restocking window.
4. Optionally narrow by **item condition** and a **minimum / maximum price**.
5. Leave **Add Amazon price spread** on if you also want the Amazon comparison for products that
   publish a UPC.
6. Click **Start** and read the **Overview** view of the dataset, or pull the rows through the API.

Minimal input:

```json
{
  "queries": ["logitech mx master 3s", "sony wh-1000xm4"],
  "ebaySite": "EBAY_US",
  "windowDays": "30",
  "enableAmazonSpread": true
}
```

### What data you get per product

One row per search phrase. A real row looks like this:

```json
{
  "query": "logitech mx master 3s",
  "ebaySite": "EBAY_US",
  "windowDays": 30,
  "windowStart": "2026-07-05",
  "windowEnd": "2026-08-03",
  "currency": "USD",
  "soldCount": 459,
  "soldCountExact": true,
  "activeCount": 853,
  "activeCountExact": true,
  "sellThroughRate": 0.5381,
  "soldPriceMedian": 60,
  "soldPriceP25": 40,
  "soldPriceP75": 79.99,
  "soldVelocityPerDay": 15.3,
  "velocityTrendPct": 12.4,
  "conditionBreakdown": [
    { "condition": "Pre-Owned", "soldCount": 198, "medianPrice": 52.5 },
    { "condition": "Brand New", "soldCount": 121, "medianPrice": 79.99 },
    { "condition": "Certified - Refurbished", "soldCount": 74, "medianPrice": 63.99 }
  ],
  "amazonUpc": "097855161581",
  "amazonAsin": "B09HM94VDS",
  "amazonPrice": 99.99,
  "amazonSpreadPct": 66.65,
  "amazonMatchMethod": "upc",
  "pagesFetchedSold": 4,
  "pagesFetchedActive": 6,
  "source": "primary",
  "status": "ok",
  "notice": null,
  "fetchedAt": "2026-08-03T12:46:54.276Z"
}
```

| Field | Type | What it tells you |
|---|---|---|
| `query`, `ebaySite`, `windowDays` | string / string / int | Input echo — what this row answers |
| `windowStart`, `windowEnd` | date | The closed window that was counted, exactly `windowDays` long |
| `currency` | string | Currency of every price in the row |
| `soldCount`, `activeCount` | int | Sold in the window and live competitors now, de-duplicated by item ID |
| `soldCountExact`, `activeCountExact` | bool | `false` = the count is a lower bound, see `notice` |
| `sellThroughRate` | float | `soldCount / activeCount`, `0.54` = 54%; `null` when there is no denominator |
| `soldPriceMedian`, `soldPriceP25`, `soldPriceP75` | float | Realized price and its accepted band |
| `soldVelocityPerDay` | float | Average sold listings per day in the window |
| `velocityTrendPct` | float|null | Pace of the newer half vs the older half of the window |
| `conditionBreakdown[]` | object\[] | `{condition, soldCount, medianPrice}` per condition |
| `amazonUpc`, `amazonAsin`, `amazonPrice`, `amazonSpreadPct`, `amazonMatchMethod` | mixed | Amazon comparison, UPC join only |
| `pagesFetchedSold`, `pagesFetchedActive` | int | How deep the review went behind the numbers |
| `source` | string | `primary` or `fallback` for the active-listing page |
| `status`, `notice` | string | `ok` / `not_found` / `too_broad`, plus a plain-English caveat |
| `fetchedAt` | datetime | When the row was measured |

Two dataset views ship with the actor: **Overview** (the six decision columns) and **Needs a
narrower query**, which isolates rows whose counts hit the review depth limit.

### How sell-through, percentiles, and trend are calculated

Sell-through is `soldCount / activeCount` on the same phrase with the same filters, so it is
comparable across your list. The median and both percentiles use one interpolation method on
realized prices only — asking prices of live listings never enter them. `velocityTrendPct` compares
the sales pace (sales ÷ days) of the newer half of the window against the older half, so a 30-day
window tells you whether the last 15 days ran hotter than the first 15. When a count cannot be
completed, the row says so in `notice` and flips the matching `*Exact` flag to `false` instead of
publishing a number that reads as final.

### Input parameters

| Parameter | Type | Default | Notes |
|---|---|---|---|
| `queries` | string\[] | — | 1–100 phrases or eBay search URLs; one row per entry |
| `ebaySite` | select | `EBAY_US` | 14 marketplaces; sets the currency of the row |
| `windowDays` | select | `30` | `7`, `30`, or `90` days |
| `condition` | select | Any | New / Refurbished / Used |
| `priceMin`, `priceMax` | int | empty | Bounds in the marketplace currency |
| `enableAmazonSpread` | bool | `true` | Adds the Amazon columns when a UPC exists |

The full descriptions live on the **Input** tab, and the same schema drives the Apify API and the
MCP server at `mcp.apify.com`, so an AI agent can call this actor without a wrapper.

### How much does eBay product research cost?

Pay per event — you pay for delivered reports, not for compute time.

| Event | What triggers it | Price |
|---|---|---|
| `actor-start` | Once per run that delivers at least one report | $0.005 |
| `product-report` | Each delivered row, including `not_found` answers | $0.08 → $0.05 |

The report price is a ladder across plan tiers: **$0.08** on Free, then $0.07 and $0.06, and
**$0.05** from the volume tier up. A run with one product costs **$0.085** minimum. Cache hits and
rows that could not be measured are never charged.

### eBay comps actor vs per-listing scrapers and manual research

| | This actor | Per-listing eBay scrapers | Manual eBay search |
|---|---|---|---|
| Output | One aggregated row per product | Hundreds of raw listing rows | A page you read yourself |
| Sell-through rate | Yes — sold and active in one row | No, sold listings only | No |
| Price band | Median + p25/p75 + per condition | You compute it | Eyeballed |
| Cost per product | $0.05 per report | Billed per listing, hundreds per product | Free, minutes per product |
| 100 products | One run | One run per product | Hours |

### eBay comps actor vs Terapeak

Terapeak is eBay's own product-research tool inside Seller Hub, and for a single product it is
excellent — first-party data with up to 3 years of history, free with an eBay seller account.
This actor is not a Terapeak clone; it covers the part Terapeak does not:

| | This actor | Terapeak Product Research |
|---|---|---|
| Access | Public API — no eBay account needed | Requires an eBay seller account, browser UI |
| Bulk | Up to 100 products per run | One search at a time |
| Automation | Schedulable runs, JSON/CSV dataset, API | Manual searches, manual export |
| History window | 7 / 30 / 90 days | Up to 3 years |
| Data source | Public sold + active listings (see limits below) | eBay first-party sales data |
| Sell-through | Sold vs active in the same row | Available |
| Cross-market check | Optional Amazon price spread (UPC join) | eBay only |
| Price | $0.05–0.08 per product report | Free with a seller account |

Rule of thumb: researching **one product deeply** and you already sell on eBay — open Terapeak,
it is free and has longer history. Screening **a list of candidates**, feeding a repricer or a
sourcing pipeline, or working **without a seller account** — that is what this actor is for.
Terapeak has no public API to plug into a workflow; this actor is the automatable route to the
same class of answer.

### How the numbers stay honest

- **De-duplication by item ID**, within a page and across pages — eBay repeats listings between
  result pages, and an undeduplicated count inflates demand by double digits.
- **Every listing is date-checked** against `windowStart`/`windowEnd`; sold pages mix in results
  far older than your window.
- **Depth limits are disclosed**, never silent: `*Exact: false` plus a `notice`, surfaced in the
  "Needs a narrower query" view.
- **No invented sell-through** — unmeasured sold data leaves every sold-side field `null`.

### What this actor does not do

- It does **not** measure demand outside eBay. eBay is a **proxy for demand, not your buyer's
  channel** — a product that sells well on eBay can behave differently on Amazon, Shopify, or in
  retail, and the reverse is just as true.
- It does **not** fill the Amazon columns for every product. The match is a strict UPC join, and a
  usable UPC is published for roughly **30–40% of products** (games, fashion, and spare parts are
  usually not among them). The eBay core columns are always filled.
- It does **not** match products by title — a title match returns the wrong product often enough to
  poison a buying decision, so it is not offered at any confidence level.
- It does **not** return individual listings, seller names, or buyer data. It is an aggregate.
- It does **not** track products over time on its own. It is stateless — schedule it to build history.
- It does **not** guarantee exact counts on very broad phrases; those come back flagged as
  `too_broad` with a lower bound.

### FAQ

#### How do I check the real sold price of an item on eBay?

Enter the product phrase and a window. The row returns `soldPriceMedian` for realized sales inside
that window, plus `soldPriceP25` and `soldPriceP75` so you see the spread rather than one number.

#### What is a good sell-through rate on eBay?

Resellers commonly treat 50%+ over 30 days as healthy demand and under 20% as a slow mover. This
actor gives you `sellThroughRate` per product, so you compare candidates on the same scale.

#### Why is sellThroughRate sometimes null?

Because there was no denominator — no active listings matched, or sold data could not be measured.
A `null` is an honest "not measured"; it is never published as a 0% sell-through.

#### Is this a Terapeak alternative?

For bulk and automated research, yes. Terapeak is free with an eBay seller account and has longer
history for a single product, but it is a manual browser tool with no public API. This actor
answers the same question — realized prices and sell-through — for up to 100 products per run,
on a schedule, as a dataset, with no eBay account. See the comparison table above.

#### How many products can I check in one run?

Up to 100 phrases per run, one billed report each. Re-running the same phrase within 24 hours
re-delivers the cached report and is not billed.

#### Does it work on eBay UK, Germany, or Australia?

Yes — 14 marketplaces, selected with the `ebaySite` field. Prices are returned in that
marketplace's currency, so do not mix currencies when you compare rows across sites.

### Related actors

- [Amazon Listing Optimizer](https://apify.com/doesaiknow/amazon-listing-optimizer) — when the
  Amazon spread says a product is worth listing there, this audits the listing that has to sell it.

See the doesaiknow publisher page for the rest of the e-commerce research suite.

### Legal & support

- This actor returns **aggregated public marketplace statistics** — counts, medians, percentiles.
  It stores no personal data and returns no buyer or seller identities.
- Data is retrieved through a licensed data **API**, not by driving your account: no login, no
  scraping infrastructure, no anti-bot circumvention.
- Output is provided **as-is** for market research. Sold-listing samples are point-in-time
  observations of a public marketplace, not audited sales records, and not a guarantee of future
  prices or demand.
- You are responsible for using the output in line with the terms of the marketplaces you sell on
  and the law in your jurisdiction. eBay and Amazon are trademarks of their respective owners; this
  actor is not affiliated with or endorsed by either company.
- Questions or a bug? Open an issue on the actor's **Issues** tab; see the **API** tab for
  integration details.

### SEO keywords

ebay product research, ebay sold prices, ebay sell through rate, ebay comps, sold price lookup,
ebay sold listings, ebay market research, ebay price research tool, sell through rate calculator,
ebay median sold price, dropshipping product research, ebay reseller tools, ebay demand analysis,
ebay competitor analysis, ebay pricing data, ebay sales history, ebay completed listings, product
sourcing research, ebay arbitrage tool, amazon to ebay spread, ebay sales velocity, ebay listing
competition, ebay category research.

Built by doesaiknow.

# Actor input Schema

## `queries` (type: `array`):

One product phrase per line (for example: logitech mx master 3s), or a full eBay search URL. Each entry returns exactly one result row: median sold price, p25–p75, sell-through rate and active-listing count. A full eBay search URL overrides the marketplace, condition and price filters selected below.

## `ebaySite` (type: `string`):

Marketplace the sold and active listings are read from. Prices are returned in the currency of that marketplace.

## `windowDays` (type: `string`):

How far back sold listings are counted. Longer windows give a steadier median but cost more pages to read; 30 days is the usual choice for restocking decisions.

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

Restricts both sold and active listings to one condition. Keep "Any condition" to compare the whole market and use the per-condition breakdown in the output instead.

## `priceMin` (type: `integer`):

Ignore listings below this price, in the currency of the selected marketplace. Leave empty for no lower bound.

## `priceMax` (type: `integer`):

Ignore listings above this price, in the currency of the selected marketplace. Leave empty for no upper bound.

## `enableAmazonSpread` (type: `boolean`):

Matches the product to Amazon by UPC only and adds the Amazon price and the spread against the eBay median. A UPC is published for roughly 30–40% of products, so this column is empty for the rest; the core sell-through columns are always filled.

## Actor input object example

```json
{
  "queries": [
    "logitech mx master 3s"
  ],
  "ebaySite": "EBAY_US",
  "windowDays": "30",
  "condition": "any",
  "enableAmazonSpread": true
}
```

# Actor output Schema

## `results` (type: `string`):

All delivered rows: query, windowStart/windowEnd, soldCount, activeCount, sellThroughRate, soldPriceMedian, soldPriceP25/P75, soldVelocityPerDay, velocityTrendPct, conditionBreakdown, the Amazon columns, status and notice.

## `overview` (type: `string`):

The same rows narrowed to the decision columns: query, soldCount, sellThroughRate, soldPriceMedian, soldVelocityPerDay, amazonSpreadPct.

## `needsANarrowerQuery` (type: `string`):

Rows whose counts are lower bounds because the phrase was too broad to read to the end, with the notice explaining what to change.

## `cache` (type: `string`):

Reports kept for 24 hours per search, window and filters; a cache hit re-delivers the row and is never billed beyond the one-time run start.

# 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 = {
    "queries": [
        "logitech mx master 3s"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("doesaiknow/ebay-comps-sell-through").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 = { "queries": ["logitech mx master 3s"] }

# Run the Actor and wait for it to finish
run = client.actor("doesaiknow/ebay-comps-sell-through").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 '{
  "queries": [
    "logitech mx master 3s"
  ]
}' |
apify call doesaiknow/ebay-comps-sell-through --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,doesaiknow/ebay-comps-sell-through"
        }
    }
}

```

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/UmHgd56PfYd63GQoN/builds/0m2oKapLnmuIcIySy/openapi.json
