# eBay Product & Sold Scraper (`cirkit/ebay-product-scraper`) Actor

Scrape eBay search results, listing details, and SOLD/completed listing history. Built-in price-band partitioning to break past the 10-page (600-result) cap. Confirmed sold prices, not asking prices.

- **URL**: https://apify.com/cirkit/ebay-product-scraper.md
- **Developed by:** [Crikit](https://apify.com/cirkit) (community)
- **Categories:** E-commerce, Business
- **Stats:** 74 total users, 21 monthly users, 60.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 & Sold Scraper

**Scrape eBay listings and sold prices.** This **eBay scraper** covers active search results, full listing detail, and — most importantly — **SOLD and completed listing history** with confirmed sale prices rather than asking prices. Built-in price-band partitioning breaks past eBay's 10-page, 600-result ceiling.

No eBay API key, no login, and no headless browser. Results land in a structured dataset you can export to JSON, CSV, Excel, or XML, or pull straight from the Apify API.

### What is eBay Product & Sold Scraper?

eBay Product & Sold Scraper is an [Apify Actor](https://apify.com/actors) that extracts search results, listing details, and sold history from [eBay](https://www.ebay.com) and returns them as clean, structured records. Sold data is what makes eBay valuable for pricing. An asking price tells you what a seller hopes for; a sold price tells you what the market actually paid, and that is the number resale and arbitrage decisions need.

### What data can this eBay scraper extract?

Every run writes one row per listing. The full schema carries **28 fields**; the most-used ones are below.

| Field | Type | Description |
| --- | --- | --- |
| `listingId` | string | eBay's numeric listing identifier (data-listingid). 12 digits for single listings; 15 digits for variation groups. |
| `title` | string | Listing title as displayed in search results or detail. |
| `itemUrl` | string | Canonical eBay item URL (https://www.ebay.com/itm/<id>). |
| `imageUrl` | string | Full-resolution primary image (i.ebayimg.com s-l1600.webp variant). |
| `epid` | string | Canonical product taxonomy ID. Listings of the same SKU share an EPID. |
| `price` | number | Numeric USD price. For variations: the lower bound. For 'Best offer accepted' sold listings: null (eBay hides this). |
| `priceText` | string | Raw price string as shown on eBay, including range / approximation / 'Best offer accepted' / foreign-currency markers. |
| `priceCurrency` | string | ISO 4217 code of the native listing currency. |
| `priceUsdApprox` | number | eBay's USD approximation for foreign-currency listings. |
| `finalPriceHidden` | boolean | True for sold listings where eBay shows 'Best offer accepted' instead of the numeric sold price. |
| `shippingText` | string | Shipping cost or 'Free shipping' as displayed. |
| `soldDate` | string | ISO date the listing sold (sold listings only). |
| `soldDateText` | string | Raw 'Sold MMM DD, YYYY' string from the SRP card. |
| `isSold` | boolean | True if this listing is sold/completed. |
| `isNewListing` | boolean | True if eBay tagged this 'New Listing' (posted in the last 24 hrs). |
| `condition` | string | Item condition (New, Pre-Owned, Refurbished, etc.). |
| `subtitle` | string | Card subtitle line (typically combines condition and a carrier/variant note). |
| `bidCount` | integer | Number of bids (auctions only). |
| `listingType` | string | AUCTION / FIXED\_PRICE / BEST\_OFFER inferred from the card or detail page. |
| `seller` | object | Seller summary parsed from the SRP card. |
| `searchQuery` | string | The input query that produced this result. |
| `searchUrl` | string | The eBay SRP URL where this listing was found. |

See the **Output** tab in Apify Console for all 28 fields.

### How to scrape eBay listings and sold prices

1. Open [eBay Product & Sold Scraper](https://apify.com/cirkit/ebay-product-scraper) and click **Try for free**.
2. Add `searchQueries`, or paste specific `itemUrls`.
3. Set `mode` to choose active listings or sold and completed history.
4. Filter with `condition`, `listingType`, `priceMin`, `priceMax`, and `sortBy`.
5. Turn on `scrapeItemDetails` for the full per-listing record, and set `maxResultsPerQuery`.
6. Click **Start** and watch rows appear live in the **Output** tab.
7. Export the dataset as JSON, CSV, Excel, or XML — or fetch it from the [Apify API](https://docs.apify.com/api/v2) once the run finishes.

### eBay Product & Sold Scraper input options

| Input | Type | What it does | Default |
| --- | --- | --- | --- |
| `searchQueries` | array | Keyword searches to run. Each query runs independently. Quotes and minus signs work the same as in the eBay search box. | `["iphone 15 pro"]` |
| `itemUrls` | array | Direct eBay item URLs (https://www.ebay.com/itm/) to scrape detail-only, skipping search. Works for active or ended... |  |
| `mode` | string | What kind of listings to return. eBay now requires a signed-in account to view sold and completed listings, so... | `"active"` |
| `maxResultsPerQuery` | integer | Hard cap per query. The eBay SRP itself caps at 600 results per query (10 pages × 60); to exceed, the actor... | `60` |
| `scrapeItemDetails` | boolean | If true, fetch each search hit's detail page for extra fields (condition description, item specifics, shipping,... | `false` |
| `condition` | string | Filter by item condition. | `"any"` |
| `listingType` | string | Filter by auction or Buy It Now. | `"any"` |
| `priceMin` | integer | Lower price bound. |  |
| `priceMax` | integer | Upper price bound. |  |
| `sortBy` | string | Sort order applied to the eBay search results page. | `"recently_ended"` |

Proxy is configured through the standard `proxyConfiguration` object; the defaults shipped with this Actor are already tuned for the target site.

### Example output

```json
{
  "listingId": "a1b2c3d4",
  "title": "Example title",
  "itemUrl": "https://example.com/item/12345",
  "imageUrl": "https://example.com/item/12345",
  "epid": "a1b2c3d4",
  "price": 129.99,
  "priceText": "Example text ...",
  "priceCurrency": "USD",
  "priceUsdApprox": 129.99,
  "finalPriceHidden": true,
  "shippingText": "Example text ...",
  "soldDate": "2026-08-30T12:00:00.000Z",
  "soldDateText": "2026-08-30T12:00:00.000Z",
  "isSold": false,
  "isNewListing": true,
  "condition": "...",
  "subtitle": "Example title",
  "bidCount": 1483
}
```

### How much does it cost to scrape eBay?

This Actor bills through Apify platform usage (compute units and proxy traffic) rather than a per-result fee. Runs are HTTP-based and lightweight, which keeps compute low. Every Apify account includes free monthly usage credit to trial it.

### What can you build with eBay data?

#### Price resale inventory from real sold comps

Sold prices with dates are the ground truth for what an item is worth today, which is exactly what asking-price data cannot tell you.

#### Run retail-arbitrage sourcing

Compare eBay sold prices against retail prices from the Walmart, Target, or Best Buy Actors to find items with a genuine spread.

#### Track sell-through rate for a product category

Active listing counts against sold counts over the same window gives the sell-through ratio that drives inventory decisions.

#### Build a price guide for collectibles

Condition, sold date, and final price across many sales produce a defensible price guide for graded or collectible goods.

#### Monitor competitor sellers

Seller fields let you follow what specific sellers list, at what price, and what actually clears.

### eBay scraping tips and limits

- eBay caps a single search at roughly 600 results across 10 pages. This Actor partitions by price band to get past that — leave the partitioning in place on broad queries.
- `isSold` and `soldDate` are the fields that matter for comps. Filter on them rather than assuming a sold-mode run contains only sold rows.
- `finalPriceHidden` marks best-offer sales where eBay withholds the accepted amount. Exclude those rows from price averages or they will drag the mean down.
- Narrow queries beat broad ones. 'iPhone 15 Pro 256GB unlocked' produces far more usable comps than 'iPhone'.

### Integrations and automation

Run eBay Product & Sold Scraper on a [schedule](https://docs.apify.com/platform/schedules) to keep a eBay dataset fresh, or trigger it from your own stack through the [Apify API](https://docs.apify.com/api/v2) and the official [JavaScript](https://docs.apify.com/sdk/js) and [Python](https://docs.apify.com/sdk/python) clients. Native [integrations](https://docs.apify.com/platform/integrations) push results into Google Sheets, Slack, Airtable, Zapier, Make, GitHub, or any webhook endpoint. The Actor also works as an [MCP](https://docs.apify.com/platform/integrations/mcp) tool, so an AI agent can call it directly.

### Related scrapers

| Actor | What it does |
| --- | --- |
| [Poshmark Listings & Sold Comps Scraper](https://apify.com/cirkit/poshmark-search-scraper) | Fashion resale comps with sold prices and dates. |
| [Amazon Product Scraper](https://apify.com/cirkit/amazon-product-scraper) | Amazon retail pricing to compare against eBay resale. |
| [Walmart Product Scraper](https://apify.com/cirkit/walmart-product-scraper) | Walmart retail prices for arbitrage sourcing. |
| [Etsy Scraper - Listings, Shops & Search Results](https://apify.com/cirkit/etsy-shop-product-scraper) | Handmade and vintage listings and shop data. |

### Frequently asked questions

#### Can I scrape eBay sold listings?

Yes, and it is the main reason to use this Actor. Set `mode` to sold or completed and rows come back with the confirmed final price and the sold date.

#### How do I get more than 600 results?

Price-band partitioning splits a broad query into narrower price ranges, each of which gets its own result budget. That is how the Actor exceeds eBay's per-search ceiling.

#### Do I need a eBay API key?

No. eBay Product & Sold Scraper reads publicly available eBay pages and endpoints directly, so there is no key to obtain, no OAuth app to register, and no account to connect.

#### Can I export eBay data to CSV, Excel, or Google Sheets?

Yes. Every run stores results in an Apify dataset that exports to JSON, JSONL, CSV, Excel, XML, or HTML with one click, and the Google Sheets integration writes rows straight into a spreadsheet.

#### Can I run eBay Product & Sold Scraper on a schedule?

Yes. Apify schedules run the Actor hourly, daily, weekly, or on any cron expression, and webhooks can notify your systems the moment a run finishes.

#### Is it legal to scrape eBay?

Scraping publicly available data is broadly lawful in the US and EU, but the answer depends on what you collect and how you use it. This Actor is built to gather public listing and completed-sale information eBay publishes publicly, including seller usernames. Personal data carries extra obligations under GDPR and CCPA. Read Apify's guide on [whether web scraping is legal](https://blog.apify.com/is-web-scraping-legal/) and take your own legal advice for your use case.

### Support and feedback

Found a bug, a missing field, or a eBay page shape this Actor does not handle yet? Open an issue from the **Issues** tab on the Actor page. Feature requests and custom-scraper enquiries are welcome there too.

# Actor input Schema

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

Keyword searches to run. Each query runs independently. Quotes and minus signs work the same as in the eBay search box.

## `itemUrls` (type: `array`):

Direct eBay item URLs (https://www.ebay.com/itm/<id>) to scrape detail-only, skipping search. Works for active or ended listings.

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

What kind of listings to return. eBay now requires a signed-in account to view sold and completed listings, so "sold" and "both" return a diagnostic row explaining that rather than data. Use "active" for live listings.

## `maxResultsPerQuery` (type: `integer`):

Hard cap per query. The eBay SRP itself caps at 600 results per query (10 pages × 60); to exceed, the actor automatically partitions by price band.

## `scrapeItemDetails` (type: `boolean`):

If true, fetch each search hit's detail page for extra fields (condition description, item specifics, shipping, watchers, full photo list). Roughly doubles cost and run time.

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

Filter by item condition.

## `listingType` (type: `string`):

Filter by auction or Buy It Now.

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

Lower price bound.

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

Upper price bound.

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

Sort order applied to the eBay search results page.

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

Residential US proxy is REQUIRED — eBay blocks datacenter IPs at the Akamai layer.

## Actor input object example

```json
{
  "searchQueries": [
    "iphone 15 pro"
  ],
  "itemUrls": [],
  "mode": "active",
  "maxResultsPerQuery": 60,
  "scrapeItemDetails": false,
  "condition": "any",
  "listingType": "any",
  "sortBy": "recently_ended",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Listings extracted from eBay search results and item detail pages.

## `datasetCsv` (type: `string`):

CSV export of the run's listings.

# 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": [
        "iphone 15 pro"
    ],
    "mode": "active",
    "maxResultsPerQuery": 60,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("cirkit/ebay-product-scraper").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": ["iphone 15 pro"],
    "mode": "active",
    "maxResultsPerQuery": 60,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("cirkit/ebay-product-scraper").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": [
    "iphone 15 pro"
  ],
  "mode": "active",
  "maxResultsPerQuery": 60,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call cirkit/ebay-product-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/bwO9tUK0rayw9u9Ul/builds/kvgp2XOE0Y5YVWDcI/openapi.json
