# eBay Scraper API - Sold Prices, Listings & Sellers (`vonsensey/ebay-scraper-api`) Actor

Scrape eBay listings, full item details, seller inventory and confirmed sale prices as clean JSON. 19 marketplaces, graded-card fields, watcher and sold counts, per-run spend ceiling. No login, no API key. Export to JSON, CSV or Excel. Pay per row - failed runs are free.

- **URL**: https://apify.com/vonsensey/ebay-scraper-api.md
- **Developed by:** [Blackcube Agency AB](https://apify.com/vonsensey) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

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 Scraper API — sold prices, listings, item detail & sellers

<table style="border-collapse:collapse;width:100%;margin:0 0 4px">
<tr><td colspan="3" style="padding:9px 12px;background:#0B6E75;border:1px solid #0B6E75"><span style="color:#FFFFFF;font-weight:700;font-size:13px;letter-spacing:.3px">eBay Data Suite</span><span style="color:#CFF0F2;font-size:12px"> &nbsp;&bull;&nbsp; 7 Actors, one codebase, one result billed once</span></td></tr>
<tr><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#ECFDF5;vertical-align:top;width:33%"><span style="color:#0B6E75;font-weight:700;font-size:13px">eBay Scraper API</span><br><span style="color:#0B6E75;font-size:11px;font-weight:600">&#10148; You are here</span></td><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#FFFFFF;vertical-align:top;width:33%"><a href="https://apify.com/vonsensey/ebay-watch-count-scraper-api" style="color:#111827;font-weight:700;font-size:13px;text-decoration:none">eBay Watch Count Scraper API</a><br><span style="color:#6B7280;font-size:11px">Watchers &amp; Sold</span></td><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#FFFFFF;vertical-align:top;width:33%"><a href="https://apify.com/vonsensey/ebay-seller-scraper-api" style="color:#111827;font-weight:700;font-size:13px;text-decoration:none">eBay Seller Scraper API</a><br><span style="color:#6B7280;font-size:11px">Inventory &amp; Sales</span></td></tr>
<tr><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#FFFFFF;vertical-align:top;width:33%"><a href="https://apify.com/vonsensey/ebay-sold-prices-scraper-api" style="color:#111827;font-weight:700;font-size:13px;text-decoration:none">eBay Sold Prices API</a><br><span style="color:#6B7280;font-size:11px">Confirmed Sale Prices</span></td><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#FFFFFF;vertical-align:top;width:33%"><a href="https://apify.com/vonsensey/ebay-trading-card-comps-scraper-api" style="color:#111827;font-weight:700;font-size:13px;text-decoration:none">eBay Card Comps API</a><br><span style="color:#6B7280;font-size:11px">PSA, BGS, CGC &amp; Raw</span></td><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#FFFFFF;vertical-align:top;width:33%"><a href="https://apify.com/vonsensey/ebay-price-tracker-api" style="color:#111827;font-weight:700;font-size:13px;text-decoration:none">eBay Price Tracker API</a><br><span style="color:#6B7280;font-size:11px">Monitor Listings</span></td></tr>
<tr><td style="padding:9px 12px;border:1px solid #E5E7EB;background:#FFFFFF;vertical-align:top;width:33%"><a href="https://apify.com/vonsensey/ebay-motors-scraper-api" style="color:#111827;font-weight:700;font-size:13px;text-decoration:none">eBay Motors Scraper API</a><br><span style="color:#6B7280;font-size:11px">Cars, Parts &amp; Bikes</span></td></tr>
</table>

**More from this account:** [YouTube Transcript Suite](https://apify.com/vonsensey/youtube-transcript-scraper) · [Website Contact & Email Suite](https://apify.com/vonsensey/website-contact-email-extractor) · [Career Site & ATS Jobs Suite](https://apify.com/vonsensey/career-page-job-postings-scraper-api) · [Google News Suite](https://apify.com/vonsensey/google-news-scraper-api) · [Keyword Research Suite](https://apify.com/vonsensey/google-keyword-ideas-scraper) · [Shopify Store Intelligence Suite](https://apify.com/vonsensey/shopify-store-leads-scraper) · [Amazon Reviews Suite](https://apify.com/vonsensey/amazon-reviews-scraper-api) · [Reddit](https://apify.com/vonsensey/reddit-scraper-posts-comments-api) · [Meta Ad Library](https://apify.com/vonsensey/facebook-ads-library-scraper-meta-ad-api) · [Vinted](https://apify.com/vonsensey/vinted-scraper-api)

Turn any eBay keyword, item number or seller name into clean, typed JSON.

Four things in one API: **active listings**, **full item detail**, **a seller's entire
inventory**, and **confirmed sale prices — what buyers actually paid**.

- **No login. No eBay API key. No developer application.**
- **No actor start fee.** You pay for rows, never for pressing Run.
- **A run that finds nothing costs nothing.** Errors and diagnostics are free rows.
- **19 marketplaces**, each served from its own country so prices come back in the site's own
  currency. Four are measured end-to-end — US, Germany, France, Italy — with the coverage table
  below; the rest are supported but unmeasured.
- **Set a hard ceiling on what a single run may cost**, in dollars.

> Unofficial and not affiliated with, endorsed by, or sponsored by eBay Inc.
> "eBay" is a trademark of eBay Inc. This actor reads only public, unauthenticated
> pages.

***

### Read this before you buy: eBay's sold-listings search needs a login now

Reported since **23 July 2026**, and verified by us on **18 August 2026**: eBay sends every
anonymous request for *sold* or *completed* search results to a sign-in wall. We checked it with
a real Chrome browser across twelve URL variants, four independent network paths, three
marketplaces, desktop and mobile. Every keyword-search variant lands on `signin.ebay.com`.

**So this actor does not sell you a keyword search over eBay's sold listings, because
nobody can deliver one without an eBay account.** If you point it at a sold-search URL,
you get a free row telling you exactly that, instead of an empty dataset and a bill.

**What you get instead is better for most jobs: real transaction prices.** For any seller, this
actor returns their confirmed completed orders — the price paid, the item, the item number and
the buyer's verdict on the order — and you can filter that feed by keyword. Measured on
18 August 2026: **at least 40,000 transactions reachable per seller**, and on a recent window
every row carried a price.

That is a sale that happened, at a price someone actually paid. Not an asking price.

***

### What you get

| Mode | Give it | Get back |
|---|---|---|
| **Search** | keywords, or any eBay search URL | every matching active listing, up to Max results |
| **Item** | item numbers or `/itm/` URLs | everything on the item page |
| **Seller** | a username | that seller's whole active inventory |
| **Sales** | a username (+ optional keyword) | confirmed orders with the price paid |

Most runs also get a **price summary** row — min, 25th percentile, median, 75th, 90th, max,
mean, standard deviation, total value and graded share. It is billed once per query, not per
result, and it is skipped entirely when a query returned fewer than 10 priced rows. Item mode
does not produce one.

Every run that gets past input validation also gets a **free diagnostics** row telling you how
many pages were fetched, how many were blocked, and exactly why the run stopped.

#### Listing rows

`itemId` · `url` · `title` · `price` · `priceMax` · `currency` · `priceIsRange` ·
`condition` · `listingFormat` · `bestOffer` · `bids` · `timeLeft` · `shippingCost` ·
`freeShipping` · `shippingIsEstimate` · `itemLocation` · **`soldCount`** · **`watchers`** ·
`imageUrl` · `isGraded` · `gradingCompany` · `grade` · **`queryTokenOverlap`** ·
**`titleMatchesQuery`** · `sellerName` · `sellerFeedbackScore` · `sellerPositivePct`

Two notes on those last three. eBay does **not** put the seller on a search result card, so
`sellerName` is filled in Seller mode (you named them) and on Item rows, and is `null` on a plain
keyword search rather than guessed. And every field on a row comes from that row's own listing —
nothing is ever borrowed from a neighbouring card, which is the quiet way a comps table gets
corrupted.

`titleMatchesQuery` is the other rare one. Thin result pages come back mixed with loosely related
listings that no filter catches, and they are the likeliest reason a median comes out wrong. Each
row scores how much of your query its title actually contains, so you can drop the padding
instead of averaging it into your numbers.

**`watchers` is the rarest field here.** Reviewing the published output fields of the twenty
largest eBay actors on the Apify Store in August 2026, we found none returning watch counts. It
is the cheapest demand signal eBay publishes, and it costs you nothing extra to receive.

#### Item rows

`itemId` · `url` · `title` · `price` · `currency` · `condition` · `conditionCode` ·
`soldCount` · `watchers` · `shippingCost` · `sellerName` · `sellerFeedbackScore` ·
`sellerPositivePct` · `isGraded` · `gradingCompany` · `grade` — plus `availability`,
`quantityAvailable`, `shippingCurrency`, `returnsAccepted`, `returnDays`, `brand`, `mpn`,
`model`, `color`, `images[]`, `productRating`, `productRatingCount`, `itemSpecifics{}` and
`categoryPath[]`.

An item row is not a superset of a listing row: auction-only fields (`bids`, `timeLeft`,
`bestOffer`, `listingFormat`) and the search-relevance fields live on listing rows only.

#### Sale rows

`feedbackId` · `seller` · **`price`** · `currency` · `itemId` · `itemUrl` · `itemTitle` ·
`rating` · `comment` · `buyer` · `buyerFeedbackScore` · `verifiedPurchase` ·
`automatedFeedback` · `periodBucket` · `recencyRank` · `isGraded` · `gradingCompany` ·
`grade`

***

### Honest limits, stated up front

Every actor in this category has these. Most do not tell you.

| Limit | The truth |
|---|---|
| **Sold-listing keyword search** | Not offered. eBay requires a login for it — see above. |
| **Sale dates** | eBay publishes only a coarse recency band, never a date, so there is no `soldDate` field — there is no honest way to fill one. `recencyRank` gives you exact ordering instead. |
| **Sale price coverage** | Varies by seller, and recent orders fare best. Measured across five sellers: 100%, 100%, 99%, 100% and 11%. Older feedback tends to keep the price but lose the link to the item. Use the **Sales period** filter to stay in the high-coverage window, and check `rowsFilteredOut` and the price fill in your own output rather than assuming. |
| **Search depth** | Any one query can only be paged so deep. This actor detects the end of the real results, never bills you twice for the same listing, and says so in the diagnostics row. Split a broad query by price band or category to reach more. |
| **Seller inventory depth** | Far deeper — 25,000+ items reachable for a large seller. |
| **Watchers & sold counts** | eBay prints these on some cards only, and which one it prints varies by surface. Measured on our own captured pages: watchers on 8-32% of US search cards, **0% of seller-inventory cards and 0% on DE/FR/IT**; sold counts are the reverse, 98% on seller inventory. Always `null`, never guessed — so filter on them, do not assume them. |
| **Seller on search rows** | eBay does not print the seller on a search card. Use Seller mode, or Item mode, where it is filled. |
| **Blocks** | eBay challenges some requests. When it does and will not relent, you get a **free** error row naming the input that failed. This actor never reports success on a page it could not read, and never bills you for one. |
| **Filters run after the fetch** | `excludeKeywords` and `gradeFilter` apply to rows eBay already returned. The diagnostics row reports how many were removed, and if they removed everything you get a free `ALL_FILTERED` row rather than an empty dataset. |

***

### Pricing

| You are charged for | FREE | BRONZE | SILVER | GOLD+ |
|---|---|---|---|---|
| Each listing row | $4.00 / 1,000 | $3.50 / 1,000 | $3.00 / 1,000 | **$2.50 / 1,000** |
| Each full item-detail row | $9.00 / 1,000 | $8.00 / 1,000 | $7.00 / 1,000 | $6.00 / 1,000 |
| Each confirmed sale row | $6.00 / 1,000 | $5.30 / 1,000 | $4.60 / 1,000 | $4.00 / 1,000 |
| Each price-summary row | $0.05 | $0.044 | $0.039 | $0.035 |

The price summary is one row per query, not per result, and it is skipped entirely on a query
that returned fewer than 10 priced rows — a percentile spread over a handful of listings is
noise, and you should not pay for noise. Turn it off with `includeMarketSummary: false`.

**Never charged:** pressing Run, error rows, diagnostics rows, duplicate rows, or a run
that returns nothing.

Item-detail costs more than a listing row because an item page is roughly 25 times the
data. If you only need price, condition, shipping and seller, stay in Search mode — it is
the cheap one, and it is what the headline price refers to.

**Set `maxCostUsd` and the run stops before it can exceed it**, priced at the highest tier so
the ceiling holds whatever plan you are on. Reviewing the input schemas of the twenty largest
eBay actors in August 2026, we found none exposing a spend ceiling as a run input.

***

### How to scrape eBay sold prices for a seller

Set **What to scrape** to *Sales*, put the seller's username in **Sellers**, and
optionally set **Filter sales by keyword**.

```json
{
  "mode": "sales",
  "sellers": ["musicmagpie"],
  "salesKeyword": "vinyl",
  "salesPeriod": "SIX_MONTHS",
  "maxItems": 1000
}
```

Every row is a completed order with the amount paid. Filtering by keyword is how you get
comparable sales for one product: pick the sellers who move that product, then read what
their buyers actually paid.

### How to scrape eBay listings by keyword

```json
{
  "mode": "search",
  "searchQueries": ["nintendo switch oled", "steam deck oled"],
  "condition": "used",
  "minPrice": 100,
  "maxPrice": 400,
  "sortBy": "price_lowest",
  "maxItems": 500
}
```

**There is no limit on how many keywords you can pass** — the largest actor in this category
caps its keyword list at six. Note that `maxItems` is a ceiling for the whole run, shared across
every keyword, so raise it when you pass many. Keywords the run never reached get a free
`NOT_REACHED` row naming them, rather than vanishing.

### How to scrape an eBay seller's entire inventory

```json
{ "mode": "seller", "sellers": ["musicmagpie"], "maxItems": 5000 }
```

You can add a keyword to search inside that seller's inventory, and any of the price,
condition or format filters.

### How to get full detail for the results of a search

Search and item detail are two calls on purpose, so you are never billed for detail pages you
did not ask for. Run the search, keep the `itemId` of the rows you actually care about, then feed
those into Item mode:

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });

const search = await client.actor('vonsensey/ebay-scraper-api').call({
    mode: 'search', searchQueries: ['nintendo switch oled'], minPrice: 150, maxItems: 200,
});
const { items } = await client.dataset(search.defaultDatasetId).listItems();
const shortlist = items
    .filter((i) => i.type === 'listing' && (i.watchers ?? 0) > 20)
    .map((i) => i.itemId);

if (shortlist.length > 0) {
    await client.actor('vonsensey/ebay-scraper-api').call({
        mode: 'item', itemIds: shortlist, maxItems: shortlist.length,
    });
}
```

Filtering between the two calls is the whole point: an item page costs about 25 times a listing
row to fetch, so the cheap pass finds the candidates and the expensive pass runs only on those.

### How to scrape eBay item details in bulk

```json
{
  "mode": "item",
  "itemIds": ["326350933758", "https://www.ebay.com/itm/298593858549"],
  "maxItems": 200
}
```

Item numbers and full URLs both work, mixed in the same list.

### How to scrape eBay for trading card comps (PSA, BGS, CGC, SGC)

Card titles are parsed for a third-party grade, so you can separate slabs from raw cards
without keyword guesswork:

```json
{
  "mode": "search",
  "searchQueries": ["charizard base set holo"],
  "gradeFilter": "graded",
  "excludeKeywords": ["proxy", "custom", "reprint", "lot"],
  "maxItems": 1000
}
```

`gradeFilter` accepts `graded`, `raw` or `any`. Every row carries `isGraded`,
`gradingCompany` and `grade` as separate fields, so you can group by grade in a
spreadsheet. Graders recognised: PSA, BGS/Beckett, CGC, SGC, PCGS and WATA on the name alone; TAG, ACE,
HGA, CSG, MNT, AGS, GMA, KSA, VGA and NGC only when a grade number sits beside them — because
"TAG Heuer" and "ACE Hardware" are not graded slabs, and treating them as such would drop
whole categories out of a `raw` filter.

Set `gradeFilter` to `raw` to get ungraded copies only — the comparison most card sellers
actually want, and the one a keyword blacklist gets wrong because most raw listings never
contain the word "raw".

### How to scrape eBay Germany, Italy, France and 16 other marketplaces

Pick the site in **eBay marketplace**, or just paste a URL from that site — the marketplace is
read from the URL and wins over the dropdown. Nineteen sites are supported; four are measured
end-to-end, and the table below is exactly what we measured.

`ebay.com` · `ebay.co.uk` · `ebay.de` · `ebay.fr` · `ebay.it` · `ebay.es` · `ebay.ca` ·
`ebay.com.au` · `ebay.at` · `ebay.ch` · `ebay.ie` · `ebay.nl` · `ebay.be` · `ebay.pl` ·
`ebay.com.sg` · `ebay.com.my` · `ebay.ph` · `ebay.com.hk` · `ebay.in`

Each site is served from its own country, so a German search returns EUR and an Italian search
returns EUR quoted the Italian way. Every run also reports the currency it actually saw against the one that site should quote, so
a converted price can never pass silently as a native one — which is the difference between a
comps table you can trust and one that is quietly wrong.

eBay also writes the condition, the shipping line and the buying format in each site's own
language. So every row carries both eBay's own wording in `condition` **and** a `conditionCode`
that means the same thing on every site we measured — `NEW`, `NEW_OTHER`, `OPEN_BOX`,
`REFURBISHED`, `USED`, `FOR_PARTS` — which is what makes a mixed-market dataset filterable in
one pass.

Measured on live pages from four marketplaces, 18 August 2026:

| Field | ebay.com | ebay.de | ebay.fr | ebay.it |
|---|---|---|---|---|
| title, price, currency | 100% | 100% | 100% | 100% |
| condition + conditionCode | 100% | 100% | 100% | 100% |
| shipping cost or free-shipping flag | 100% | 63% | 100% | 100% |
| buying format | 44% | 48% | 40% | 60% |
| item location | 100% | 2% | 0% | 0% |

Item location is near-zero outside the US because eBay only prints it for cross-border
listings — a domestic German listing on ebay.de simply does not carry one. It is `null` there,
not guessed.

### How to monitor eBay prices on a schedule

Add a Schedule in the Apify Console and point it at a saved input. There is no start fee,
so a run that finds five new listings costs you the price of five rows and nothing else.

Use `maxCostUsd` to put a hard cap on any single scheduled run.

### How to call the eBay Scraper API from Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("vonsensey/ebay-scraper-api").call(run_input={
    "mode": "sales",
    "sellers": ["musicmagpie"],
    "salesKeyword": "vinyl",
    "maxItems": 500,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "sale":
        print(row["price"], row["currency"], row["itemTitle"])
```

### How to call it from Node.js

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('vonsensey/ebay-scraper-api').call({
    mode: 'search',
    searchQueries: ['pokemon card psa 10'],
    gradeFilter: 'graded',
    maxItems: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.table(items.filter((i) => i.type === 'listing'));
```

### How to export eBay data to CSV, JSON or Excel

Every run's dataset exports as JSON, CSV, Excel, XML or JSONL from the Console, or from
the API with `?format=csv`. The dataset ships with five saved views — **All results**,
**Listings**, **Confirmed sales**, **Price summary** and **Run diagnostics** — so a mixed
run opens as a clean table instead of a wall of nulls.

***

### Why not eBay's own API?

Checked against eBay's own developer documentation in August 2026.

| Route | Status |
|---|---|
| **Finding API** | Decommissioned 4 February 2025. |
| **Shopping API** | Decommissioned 4 February 2025. |
| **Browse API** | Active listings only. No sold data. Needs an approved developer account. |
| **Marketplace Insights API** | The only official sold-price API. Limited Release — closed to new applicants, and capped at 90 days. |
| **Terapeak** | Free with a seller account, but aggregated only. It never shows you the individual transactions, and there is no API. |

No key, no application, no approval queue. Run it and get rows.

***

### Reading the output

The dataset mixes row types; every row carries a `type` field.

| `type` | Meaning | Charged |
|---|---|---|
| `listing` | An active listing from a search or a seller's inventory | yes |
| `item` | Full detail from an item page | yes |
| `sale` | A confirmed order with the price paid | yes |
| `summary` | Price distribution over one query | once per query |
| `error` | An input that produced nothing, and why | **free** |
| `diagnostics` | One per run: pages, blocks, and why it stopped | **free** |

Error rows carry a stable machine-readable `reason`, so you can branch on it:
`INVALID_INPUT`, `INVALID_URL`, `NO_RESULTS`, `NO_SALES`, `ITEM_NOT_FOUND`, `ALL_FILTERED`,
`NOT_REACHED`, `FETCH_FAILED`, `SOLD_SEARCH_LOGIN_GATED`, `BLOCKED_CHALLENGE`,
`BLOCKED_REFUSED`, `BLOCKED_LOGIN_REQUIRED`, `RUN_FAILED`.

**Null means "eBay did not publish it here", never "we guessed".** A price range gives you
`price`, `priceMax` and `priceIsRange: true` rather than a single made-up number. A card
listing with no grade gives you `grade: null`, not `0`.

***

### Legal and data use

Public, unauthenticated pages only. No logins, no accounts, and no personal data beyond the
masked buyer handles eBay publishes publicly. You are responsible for how you use the data,
including under GDPR and eBay's terms.

Unofficial. Not affiliated with, endorsed by, or sponsored by eBay Inc.

***

### Support

Open an issue on the Actor's **Issues** tab. Include the run ID — the diagnostics row in
that run's dataset already contains most of what is needed to answer you.

> **Run it without configuring anything** — [Scrape eBay search results and sold prices](https://apify.com/vonsensey/ebay-scraper-api/examples/ebay-search-results-and-sold-prices), a ready-made example you can start as-is or copy.

### Use cases

- **Price something before you list it.** Confirmed sale prices, not asking prices, are what tell you the number a buyer actually paid.
- **Track a price over time.** Run it on a schedule and the dataset becomes a price history you own.
- **Watch a seller.** Pull a competitor's whole live inventory and what has been selling out of it.
- **Value graded cards.** Comps split by PSA, BGS, CGC and raw, so a valuation has evidence behind it.

### Run it on a schedule

A one-off pull answers a question; a schedule answers it every day without you. Open **Schedules** in the Apify Console, point a cron at this Actor, and the dataset keeps filling on its own — no server, no cron box, no babysitting. Everything here is built to be re-run: you are billed per result delivered, so a scheduled run that finds nothing new costs nothing.

### FAQ

#### Can I get sold prices, not just active listings?

Yes. Confirmed sale prices with their dates come back alongside the live listings, in the same run.

#### Which eBay marketplaces are covered?

19 country marketplaces, chosen per run.

#### Can I see how many people are watching a listing?

Yes — watcher and sold counts are fields on the row, which is the closest public proxy for real demand.

#### Do failed or blocked lookups cost me anything?

No. Anything that could not be read comes back as a free diagnostic row rather than silently vanishing.

***

Something wrong, or a field you need that is missing? Open an issue on the **Issues** tab — it is read and it gets fixed. If this saved you time, a rating on the Store page helps the next person find it.

# Actor input Schema

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

search = active listings for a keyword or eBay search URL. item = full detail for specific item numbers. seller = a seller's entire active inventory. sales = a seller's confirmed transactions with the price the buyer actually paid.

## `searchQueries` (type: `array`):

One or more keywords. There is no limit on how many you can pass. Used by mode "search", and optionally as a filter in mode "seller".

## `startUrls` (type: `array`):

Paste eBay URLs instead of typing a query: search pages (/sch/), item pages (/itm/), seller profiles (/usr/, /str/). The marketplace is read from the URL. Sold and completed search URLs cannot be scraped - see the README.

## `itemIds` (type: `array`):

eBay item numbers for mode "item", for example 326350933758. Full /itm/ URLs also work.

## `sellers` (type: `array`):

eBay usernames for mode "seller" and mode "sales", for example musicmagpie. Profile URLs also work.

## `marketplace` (type: `string`):

Which eBay site to scrape. The proxy country is matched to the site automatically. A URL in "eBay URLs" overrides this.

## `maxItems` (type: `integer`):

Hard ceiling on billable rows for the whole run, shared across every keyword and seller you pass. Error and diagnostics rows are free and never count against it.

## `maxCostUsd` (type: `number`):

Optional hard spend ceiling. The run stops delivering billable rows before it can exceed this. Leave empty for no ceiling.

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

Filter listings by condition.

## `listingFormat` (type: `string`):

Restrict to auctions, fixed-price listings, or listings accepting Best Offer.

## `minPrice` (type: `number`):

Lowest price to include, in the marketplace currency.

## `maxPrice` (type: `number`):

Highest price to include, in the marketplace currency.

## `categoryId` (type: `string`):

Restrict a search to one eBay category, for example 139971. Leave empty to search all categories.

## `sortBy` (type: `string`):

How eBay should order the results before we page through them.

## `freeShippingOnly` (type: `boolean`):

Only return listings that ship free.

## `excludeKeywords` (type: `array`):

Drop any row whose title contains one of these words. Case-insensitive. Useful for stripping reprints, lots, damaged goods or specific graders.

## `gradeFilter` (type: `string`):

Keep only graded slabs, only raw cards, or everything. The grade is read from the title. PSA, BGS/Beckett, CGC, SGC, PCGS and WATA are recognised on the name alone; TAG, ACE, HGA, CSG, MNT, AGS, GMA, KSA, VGA and NGC only when a grade number sits beside them, so ordinary listings like "TAG Heuer" are not mistaken for slabs.

## `salesPeriod` (type: `string`):

How far back to read the transaction feed in mode "sales". Recent periods have close to 100 percent price and item-link coverage; older feedback loses the item link first and then the price.

## `salesKeyword` (type: `string`):

In mode "sales", only return transactions whose item title matches this keyword. This is how you get confirmed sold prices for one product from one seller.

## `includeAutomatedFeedback` (type: `boolean`):

eBay posts automated feedback on many orders. Those rows still carry a real price but no buyer comment. Untick to keep only buyer-written feedback.

## `includeMarketSummary` (type: `boolean`):

Emit one extra row per query with min, 25th percentile, median, 75th, 90th, max, mean, standard deviation, total value and graded share. Billed once as a market summary, not per row.

## `proxyConfiguration` (type: `object`):

Residential proxy is the default and is required for reliable results.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "pokemon card psa 10"
  ],
  "startUrls": [],
  "marketplace": "ebay.com",
  "maxItems": 100,
  "condition": "any",
  "listingFormat": "all",
  "sortBy": "best_match",
  "freeShippingOnly": false,
  "gradeFilter": "any",
  "salesPeriod": "All",
  "includeAutomatedFeedback": true,
  "includeMarketSummary": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Every listing, item, sale, summary, error and diagnostics row from this run.

## `csv` (type: `string`):

The same rows as a spreadsheet-ready CSV.

## `consoleDataset` (type: `string`):

Open the dataset in the Console.

# 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 = {
    "searchQueries": [
        "pokemon card psa 10"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("vonsensey/ebay-scraper-api").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 = { "searchQueries": ["pokemon card psa 10"] }

# Run the Actor and wait for it to finish
run = client.actor("vonsensey/ebay-scraper-api").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 '{
  "searchQueries": [
    "pokemon card psa 10"
  ]
}' |
apify call vonsensey/ebay-scraper-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vonsensey/ebay-scraper-api"
        }
    }
}

```

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/ONsg0erHlJHGSl2nh/builds/2yi3f8F0vbPiSE7gi/openapi.json
