# eBay Listings & Prices (`superslowsloth/ebay-listings`) Actor

Search eBay and get one flat row per listing: price, currency, shipping, sold date for completed listings, condition, seller feedback, bids, Buy It Now and image.

- **URL**: https://apify.com/superslowsloth/ebay-listings.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** E-commerce, AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 listing scrapeds

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

## eBay Listings & Prices

One search in, one flat table out. Give it keywords - or paste an eBay search
URL straight from your browser - and it returns the listings eBay would show
you, each with its price and currency, shipping, condition, seller and feedback,
bid count, Buy It Now flag, image, and, for completed searches, **the date it
sold on**.

Built to be called by an agent or a script: small input, one row per listing, no
nested objects, no HTML.

### What it is for

`soldOnly: false` returns the live listings on sale right now. This is the path
that works today, and it is verified on every run of the test suite.

`soldOnly: true` asks for eBay's completed-listing view - the closest thing to a
public record of what things actually sell for, as opposed to what sellers ask.
**Read the next section before relying on it.**

#### The sold view is currently behind eBay's sign-in wall

Measured 2026-08-25, from a Japanese consumer address, from Apify residential
exit addresses in the US, and from a datacenter address, with a warmed session
and a real browser TLS fingerprint in every case:

| request | answer |
|---|---|
| active search, any address | HTTP 200, full results |
| `LH_Sold=1&LH_Complete=1`, cold session | HTTP 200, "Security Measure" / "Pardon Our Interruption" |
| `LH_Sold=1&LH_Complete=1`, warmed session | HTTP 200, **"Sign in or Register"** |

The same wall appears for `LH_Sold=1` alone, for `LH_Complete=1` alone, on
`m.ebay.com`, and on `ebay.de`. It is uniform across addresses and it is not a
bot check: eBay has put completed listings behind a login.

So `soldOnly: true` will report a refusal rather than results, and it says which
one in the run log. It does not silently return zero listings and charge you for
the run's start as if the market were empty - and no row is ever charged for. If
eBay reopens the view, this actor reads it with no change: the parser handles the
sold caption, and the contract test fails loudly on the day the wall comes down.

### Input

| field | meaning |
|---|---|
| `keywords` | What you would type into eBay's search box |
| `searchUrl` | A full eBay search URL instead. Filters already on it - seller, price band, sort - are kept; only paging is driven by the actor. Overrides `keywords`, `site`, `condition` and `category` |
| `soldOnly` | `true` for sold and completed listings, `false` (default) for live ones |
| `site` | `ebay.com`, `ebay.co.uk` or `ebay.de` |
| `condition` | `new`, `opened_never_used`, `refurbished`, `used`, `for_parts`, or an eBay numeric condition code |
| `category` | eBay numeric category id, the `_sacat` value from a search URL |
| `maxResults` | Stop after this many listings. eBay serves 240 per page, so anything up to 240 is a single request |
| `proxyConfiguration` | **Residential is required.** See below |

### Output

One item per listing:

| field | meaning |
|---|---|
| `item_id` | eBay's listing id |
| `title` | Listing title, with eBay's "New Listing" badge and screen-reader tail removed |
| `url` | Canonical `ebay.com/itm/<id>` link, query string stripped |
| `price` | The listing price in `currency`. For an auction, the current bid; for a completed listing, what it ended at |
| `currency` | ISO 4217 |
| `price_text` | What eBay printed, verbatim - useful when a listing is a price range |
| `shipping_cost` | Shipping in the same currency. `0.0` only when eBay said the shipping is free |
| `free_shipping` | Whether eBay said so in as many words |
| `shipping_text` | The shipping caption, verbatim |
| `sold_date` | ISO date the listing sold, completed searches only |
| `sold_date_text` | The caption eBay printed for it, verbatim |
| `condition` | `New`, `Pre-Owned`, `Parts Only`, and so on, as eBay labels it |
| `seller_name` | eBay user id of the seller |
| `seller_feedback_percent` | Positive feedback, 0-100 |
| `seller_feedback_count` | Feedback score. eBay abbreviates large ones on the search page ("40.5K"), so this is expanded and approximate above 1,000 |
| `bids` | Bid count. Auctions only |
| `buy_it_now` | Whether the listing can be bought outright |
| `image_url` | Gallery image |
| `query`, `site`, `sold_only` | The search this row came from, echoed onto every row |

#### `null` is not zero

Almost every field above is nullable, and that is deliberate. eBay's search page
is one template rendering several kinds of listing: an auction has bids and no
Buy It Now, a fixed-price listing has the reverse, a completed listing carries a
sold date and a live one never does, and a seller who ships free prints no
shipping figure. A `0` in any of those places would read as a measurement -
"free shipping", "no bids" - when the truth is that eBay did not say. So:

- `bids` is `null` on a fixed-price listing, never `0`.
- `shipping_cost` is `null` when eBay printed no shipping line, and `0.0` only
  when it printed "Free shipping".
- `sold_date` is `null` on every row of an active search, and `null` on a
  completed one whose caption could not be read as a date - in which case
  `sold_date_text` still holds the words eBay printed.

### Currency follows the exit address, not the seller

eBay converts prices for whoever is looking. A residential proxy exiting in
Japan sees `JPY 21,154` on a US listing priced in dollars. Every row therefore
carries the `currency` it was quoted in; do not assume the site's home currency.
To pin the currency, pin the proxy country in `proxyConfiguration`.

### The proxy is not optional

Measured 2026-08-25:

- plain HTTP clients get **403** from eBay's search page regardless of headers.
  This actor uses a client that presents a real browser's TLS fingerprint, which
  gets **200**.
- the **sold and completed** view is guarded harder than the active one. From a
  datacenter address, a sold search returns eBay's bot check ("Pardon Our
  Interruption") or a sign-in wall, while the identical active search returns
  full results.

So the actor defaults to `RESIDENTIAL` and rotates to a new exit address on each
retry rather than re-asking from a refused one. Running it with no proxy, or on
datacenter addresses, will produce a refusal rather than a wrong answer - the
run log names which one.

### Billing

Pay per event: one small `actor-start` charge once the input has parsed, then
one `listing-scraped` charge per row written. A search that legitimately matches
nothing costs the start event and nothing else, and an item repeated across
eBay's page boundaries is charged once.

# Actor input Schema

## `keywords` (type: `string`):

What you would type into eBay's search box, e.g. "nintendo switch oled". Leave empty if you are supplying a full search URL instead.

## `searchUrl` (type: `string`):

A full eBay search URL, pasted from the browser. Anything already on it - a seller filter, a price band, a sort order - is kept; only paging is driven by this actor. When supplied it overrides the keywords, site, condition and category fields.

## `soldOnly` (type: `boolean`):

On: ask for listings that have already ended and sold, each with the date it sold on. Off (default): the live listings on sale now. IMPORTANT, measured 2026-08-25: eBay has put its completed-listing view behind a sign-in wall, and answers this request with a sign-in page from every address tried - residential included. The run will report that refusal rather than return rows. Leave this off until the README says otherwise.

## `site` (type: `string`):

Which eBay marketplace to search. Prices are shown in the currency that marketplace serves to the exit address, and every row carries the currency it was quoted in.

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

Restrict to one item condition. Leave empty for any condition. Refurbished covers all of eBay's refurbished grades.

## `category` (type: `string`):

eBay numeric category id to search inside, taken from the \_sacat parameter of an eBay search URL. Leave empty to search all categories.

## `maxResults` (type: `integer`):

Stop after this many listings. eBay serves 240 per page, so anything up to 240 costs a single request; each further page is one more.

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

Residential is required. Measured 2026-08-25: eBay answers a sold or completed search from a datacenter address with a sign-in wall or its bot check, and returns results for the same search over a residential address.

## Actor input object example

```json
{
  "keywords": "nintendo switch",
  "soldOnly": false,
  "site": "ebay.com",
  "condition": "",
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

No description

# 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 = {
    "keywords": "nintendo switch",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/ebay-listings").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 = {
    "keywords": "nintendo switch",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/ebay-listings").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 '{
  "keywords": "nintendo switch",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call superslowsloth/ebay-listings --silent --output-dataset

```

## MCP server setup

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

```

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/Opa8ufUxcJQkeqKDx/builds/B19vdbkxQ3W2sszvY/openapi.json
