# eBay.de Listings Scraper (`nice_dev/ebay-listings-scraper`) Actor

Scrape live eBay.de listings by keyword or search URL: price, shipping, condition, seller rating, private or commercial seller, watchers and units sold. 14 eBay sites. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/ebay-listings-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** E-commerce, MCP servers
- **Stats:** 4 total users, 3 monthly users, 94.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 listing from the results pages

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🛒 What is eBay.de Listings Scraper?

**eBay.de Listings Scraper** extracts **live listings from [eBay.de](https://www.ebay.de)** and 13 other eBay marketplaces: **price, condition, shipping, seller rating, private or commercial seller, watchers and units already sold**, for any keyword or search URL.

Type a **keyword** (`iphone 13`) or paste any eBay search URL, click **Start**, and download the listings in JSON, CSV or Excel. No login, no API key, nothing to set up — from **$0.60 per 1,000 listings**, $1.09 with the item page read (Gold plan; $0.63 and $1.39 with no subscription).

### 📋 What data can you extract from eBay?

One item per listing (or per sale), 70 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Listing** | title, link, item number, marketplace — `Apple iPhone 13 256GB` |
| 💰 **Price** | price (and the top of a price range), price with coupon, list price (UVP), currency, shipping cost, free shipping, returns |
| 📦 **Item** | condition, brand, EAN, part number, the whole item specifics table, category and its number, size / colour choices, every photo, description |
| 🔨 **Format** | buy it now, auction or best offer, number of bids, time left |
| 📈 **Demand** | watchers, units already sold, units left |
| 🧑‍💼 **Seller** | user name, shop name, private or commercial, positive feedback %, number of ratings, units sold in total, member since, the four detailed ratings, logo, presentation, legal details (Impressum) |
| 🗣️ **Seller reviews** | the buyers' reviews of the seller shown on the item page: rating, masked buyer and score, period, verified purchase, comment, the item each is about (option) |
| 🧾 **Sold prices** | a seller's recent sales, read from its public feedback: item, price paid, period, masked buyer, rating and comment (option) |
| ⭐ **Catalogue product** | eBay product number (ePID), its stars and number of reviews |
| 🔎 **Search** | the keyword and search it came from, the results page and the rank on it, eBay's badges |

Every field, with an example, is listed in the **Output** section below.

Fields marked **detail** in the Output tab (`descriptionUrl`, `specifics`, `brand`, `ean`, `mpn`, `categories`, `categoryId`, `quantityAvailable`, `storeName`, `sellerUrl`, `sellerLegal`, the seller block — `sellerItemsSold`, `sellerMemberSince`, `sellerAbout`, `sellerLogoUrl`, `sellerDetailedRatings` —, `sellerReviews`, `taxText`, `variations`, all `images`) are filled when **Extract details** is on (off by default). Turn it off for a results-page-only scrape that is faster and cheaper. `description` needs **Include description** on top of it: eBay serves the description text on a page of its own, so it costs one more request per listing (off by default; `descriptionUrl` always says where that page is).

### ✅ Why use eBay.de Listings Scraper?

- 🇩🇪 **Built for eBay.de**: German marketplace by default, and the one thing every other eBay scraper drops — `sellerType`, the **Gewerblich / Privat** distinction, plus, with **Extract details** and **Seller contact** ticked, the trader's legal details (Impressum) on commercial listings.
- 📊 **Demand, not just prices**: `watchers`, `bidCount` and `soldQuantity` say what people actually want, on listings that are still live.
- 🎯 **Type the keyword, not a URL**: or paste any eBay search URL — every filter you set on the site is kept.
- 💶 **You only pay for listings that really match your search**: when eBay pads a poor search with results matching fewer words, they are left out — never delivered, never charged. Tick **Title must contain the keyword** to also drop the listings eBay finds through their item specifics or a « compatible with » list.
- 🧾 **Sold prices, still public**: eBay hid sold listings behind a login in August 2026 — give **Sellers' sold prices** a list of sellers and get their recent sales with the price paid, one row per sale.
- 🧩 **Nothing missed, nothing twice**: pagination is automatic, each listing is returned once, even across several searches.
- 🗂️ **Several searches in one run**: keywords × sellers, with a cap per search so that one broad keyword cannot eat the whole budget.
- 🔔 **Monitoring built in**: tick **Only new listings**, schedule the Actor, and each run returns (and charges) only what it has never delivered before.
- 🌍 **14 marketplaces**: de, at, ch, com, co.uk, fr, it, es, nl, be, pl, ie, ca, com.au.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape eBay

1. Create a free Apify account.
2. Open **eBay.de Listings Scraper** and type a **Search keyword** (e.g. `iphone 13`).
3. Or paste your own eBay URLs into **Start URLs**: any search results page (all filters set on the site are kept, pagination is automatic) or single item pages.
4. Set **Max listings** (100 by default, 0 = no limit) — and **Max listings per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

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

This Actor uses **pay per event** pricing: each listing is charged **one** price, set by how far it is read, and the price goes down with your Apify plan.

| Each listing saved (per 1,000)                                            | No subscription | Bronze | Silver | Gold and above |
| ------------------------------------------------------------------------- | --------------- | ------ | ------ | -------------- |
| From the results pages only (**Extract details** off)                     | $0.63           | $0.62  | $0.61  | $0.60          |
| With its item page read (**Extract details**, off by default)              | $1.39           | $1.38  | $1.19  | $1.09          |
| With its item page and its description read (**Include description**)    | $7.19           | $7.18  | $7.17  | $7.16          |

- A single item URL pasted in `startUrls` is always read in full: charged the item-page price.
- **$0.019 per run start**: a real browser opens at the start of each run. Apify charges it once per GB of the run's memory: $0.019 at the default 1 GB, **$0.038 at 2 GB** (2 × $0.019) if you raise it.

Examples with no subscription: 20,000 listings without details ≈ $12.62; 1,000 listings with details ≈ $1.41; a daily monitor of 300 new listings with details ≈ $0.44 a run. Already-delivered listings are free. Platform usage (compute, residential proxy) is included in the price.

| Charged apart (options and filters), per 1,000 units                        | No subscription | Bronze | Silver | Gold and above |
| --------------------------------------------------------------------------- | --------------- | ------ | ------ | -------------- |
| **Seller contact** (`seller-contact`): listings with the seller's legal details | $0.27       | $0.26  | $0.25  | $0.24          |
| **Seller reviews** (`seller-review`): reviews delivered                     | $0.45           | $0.44  | $0.43  | $0.42          |
| **Sellers' sold prices** (`sale`): sales delivered                          | $1.79           | $1.78  | $1.77  | $1.76          |
| **Price summary per search** (`price-summary`): searches summed up          | $44.99          | $39.99 | $34.99 | $31.99         |
| **Filter check** (`filter-check`): listings checked by the Actor's filters  | $0.049          | $0.048 | $0.047 | $0.046         |

**Price summary per search** (`includePriceSummary`): charged once per search summed up (event `price-summary`, $0.045 each with no subscription), never for a search with fewer than 5 priced listings, and only once the summary is saved.

**Options charged apart** (prices in the table above), each only where its data is delivered: **Seller contact** (`includeSellerContact`, off by default; it needs **Extract details** or a pasted item URL) per listing delivered with a commercial seller's legal details (event `seller-contact`; private sellers have none, nothing charged); **Seller reviews** (`includeSellerReviews`) per review delivered (event `seller-review`); **Sellers' sold prices** (`salesSellers`) per sale delivered (event `sale`, instead of the listing price). No extra request to eBay for the first two.

The filters of the Actor itself (**Exclude keywords**, **Title must contain the keyword**, **Min watchers**, **Min units already sold**, **Min seller rating**, **Min seller feedback count**, **Auctions ending within**) read every listing of the search: each listing they DROP is charged a filter fee (event `filter-check`, $0.049 per 1,000 listings dropped with no subscription, $0.046 on Gold); a listing they keep pays its own price only, so filtering never costs more than taking everything. The filters eBay applies itself (condition, price, category, buying format, location…) cost nothing, and neither do the results eBay adds to a poor search (left out before any check). An item page opened only to check a filter would be the separate `detail-filter-check` event of the Pricing tab; none of these filters needs one today, so it is never charged.

### ⚙️ Input

```json
{
    "query": "iphone 13",
    "maxItems": 200,
    "extractDetails": true
}
```

Several searches, a cap per search, only commercial sellers, only the listings not delivered before:

```json
{
    "searchQueries": ["iphone 13", "ipad air"],
    "sellers": ["rebuy-shop"],
    "sellerType": "commercial",
    "maxItemsPerQuery": 50,
    "onlyNew": true,
    "stateKey": "iphone-de"
}
```

Only what is in demand, under a price, in good condition:

```json
{
    "query": "nintendo switch",
    "condition": ["new", "refurbishedCertified"],
    "maxPrice": 300,
    "minWatchers": 5,
    "minSellerFeedbackPercent": 98,
    "excludeKeywords": ["defekt", "bastler"]
}
```

Sold prices of two sellers, the last 6 months, with the price summary of their sales:

```json
{
    "salesSellers": ["aix-axore", "rebuy-shop"],
    "salesPeriod": "6m",
    "maxSalesPerSeller": 400,
    "includePriceSummary": true
}
```

Or with your own URLs:

```json
{
    "startUrls": [
        { "url": "https://www.ebay.de/sch/i.html?_nkw=iphone+13&LH_BIN=1" },
        { "url": "https://www.ebay.de/itm/267443825233" }
    ],
    "maxItems": 500
}
```

| Field                                                            | Notes                                                                                                                                       |
| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`, `searchQueries`                                            | Free-text search, exactly as typed on eBay; `searchQueries` adds more keywords (one search each). Ignored when `startUrls` is set. Without a keyword, a seller, a start URL or `salesSellers` the run stops at once: eBay shows no listings then (a category alone included). |
| `keywordMatch`                                                      | How eBay matches the keyword: `allWords` (eBay's default), `anyWords`, `exactPhrase` or `exactWords`. The results eBay adds to a poor search (« results matching fewer words ») are never delivered. A pasted search URL keeps its own setting. |
| `sellers`                                                           | eBay user names (`rebuy-shop`): every keyword is searched for every seller (max 500 searches per run). Ignored when `startUrls` is set.        |
| `ebaySite`                                                          | Which marketplace to search: `ebay.de` by default, up to `ebay.com.au`. With `startUrls`, their own site.                                                                       |
| `categoryId`                                                        | One eBay category, by its number (`9355`). Empty = all categories.                                                                            |
| `startUrls`                                                         | Search results pages (filters kept, pagination automatic), single item pages (always read in full: charged the item-page price) or seller feedback pages (`https://www.ebay.de/fdbk/feedback_profile/aix-axore`: that seller's sales), all on one eBay site. With **Extract details** on, each item URL takes one of the `maxItems` places first, and the searches fill the others with their first listings. |
| `extractDetails`                                                    | Open each item page for the item specifics, all photos, quantity, VAT note, variations, the seller's block (units sold in total, member since, detailed ratings) and the trader's legal details (default off).           |
| `includeDescription`                                                | Also read the description text — one MORE request per listing, since eBay serves it on a separate page (default off).                         |
| `includePriceSummary`                                               | At the end of the run, the price summary of each search (count, min, max, mean, median, percentiles, per currency, with and without shipping) in the **PRICE_SUMMARY** record — no extra request to eBay (default off). |
| `includeSellerContact`                                              | A commercial seller's legal details (Impressum: company, address, phone, e-mail, VAT and register numbers) in the sellerLegal column — read on the item page, charged per listing where found (default off; needs **Extract details** or a pasted item URL, else the run says so in its log; off = that column is empty). |
| `includeSellerReviews`                                              | The buyers' reviews of the seller the item page shows, up to 16, in the sellerReviews column — charged per review (default off). |
| `salesSellers`                                                      | eBay user names (`aix-axore`) whose recent sales you want, read from their public feedback: one row per sale, with the price paid. With keywords, only the sales whose title matches them. Runs with or without a listing search. Not on ebay.be, which serves no feedback page: choose ebay.fr or ebay.nl (same sellers, same sales). |
| `maxSalesPerSeller`                                                 | Sales read per seller, kept or not by your filters (200 by default, `0` = all, up to 40,000). |
| `salesPeriod`                                                       | Only the sales of this period: `all`, `1m`, `6m` or `12m`. |
| `maxItems`                                                          | Stop after this many listings for the whole run (`0` = unlimited).                                                                           |
| `maxItemsPerQuery`                                                  | Cap for EACH search (keyword × seller, or search URL). 0 = no per-search cap.                                                                 |
| `condition`                                                         | eBay's own condition filter: `new`, `openBox`, `refurbishedCertified`, `refurbishedSeller`, `used`, `forPartsNotWorking`.                     |
| `buyingFormat`                                                      | `all`, `auction`, `buyItNow` or `bestOffer`.                                                                                                  |
| `sellerType`                                                        | `all`, `private` (Privatverkäufer) or `commercial` (gewerblicher Verkäufer) — an eBay.de distinction.                                         |
| `itemLocation`                                                      | Where the item ships from: `all`, `site` (the marketplace's own country), `europe` (the European Union, European sites), `northAmerica` (ebay.com, ebay.ca) or `worldwide`. A region the site does not offer is refused (none on ebay.com.au).                                            |
| `sortBy`                                                            | eBay's sort order: `bestMatch`, `newlyListed`, `endingSoonest`, `priceLowest`, `priceHighest`, `mostWatched`.                                 |
| `minPrice`, `maxPrice`, `freeShipping`, `returnsAccepted`           | Price range in the marketplace's currency, free delivery only, returns accepted only.                                                         |
| `excludeKeywords`                                                   | Drop the listings whose title contains one of these words (case and accents ignored).                                                         |
| `titleMustMatchQuery`                                               | Keep only the listings whose title holds every word of their own search keyword (one of them with **Any of the words**). Case, accents and punctuation ignored, a number counts whole (5Ah is not in 7,5Ah); a word the keyword excludes (minus sign) is skipped, a group in brackets needs one of its words. Decided on the results page: a dropped listing is not saved and its item page is not opened; each listing checked costs the filter fee, kept or not. |
| `minWatchers`, `minSoldQuantity`, `endingWithinHours`               | Demand filters: at least 5 watchers, at least 1 unit sold, auctions ending within 24 hours.                                                   |
| `minSellerFeedbackPercent`, `minSellerFeedbackCount`                | Drop the listings of sellers under 98% positive feedback or under 50 ratings, and those that show no rating. `0` = no filter.                  |
| `onlyNew`, `stateKey`, `resetState`                                 | Monitoring: only the listings never delivered under this memory key; `resetState` forgets the memory.                                          |
| Advanced                                                            | `proxyConfiguration` (included in the price; the residential proxy cannot be chosen here), `maxConcurrency`, `maxRequestsPerMinute` (with `includeDescription`, a listing page and its description count as one request), `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

```json
{
    "recordType": "listing",
    "id": "267443825233",
    "listingId": "267443825233",
    "url": "https://www.ebay.de/itm/267443825233",
    "title": "Apple iPhone 13 256GB Rosa - Gut - Refurbished",
    "marketplace": "ebay.de",
    "price": 276.21,
    "priceMax": 276.21,
    "priceText": "EUR 276,21",
    "priceWithCoupon": 262.4,
    "listPrice": null,
    "currency": "EUR",
    "condition": "Gut - Refurbished",
    "buyingFormat": "buyItNow",
    "bidCount": null,
    "timeLeftText": null,
    "endsAt": null,
    "shippingCost": 0,
    "shippingText": "Kostenloser Versand",
    "freeShipping": true,
    "shipsFrom": "Italien",
    "returnsAccepted": true,
    "returnsText": "Kostenloser Rückversand",
    "watchers": 11,
    "soldQuantity": null,
    "quantityAvailable": 1,
    "sellerName": "aix-axore",
    "storeName": "AXORE",
    "sellerUrl": "https://www.ebay.de/str/miniumitalia",
    "sellerFeedbackPercent": 99,
    "sellerFeedbackCount": 11625,
    "sellerType": "commercial",
    "sellerLegal": null,
    "sellerItemsSold": 43384,
    "sellerMemberSince": "Nov 2017",
    "sellerAbout": "AXORE™ la qualità al primo posto…",
    "sellerLogoUrl": "https://i.ebayimg.com/images/g/XkgAAeSwEAtobkbd/s-l140.jpg",
    "sellerDetailedRatings": { "Genaue Beschreibung": 4.8, "Angemessene Versandkosten": 5, "Lieferzeit": 5, "Kommunikation": 5 },
    "sellerReviews": [
        { "rating": "positive", "buyerName": "9***s", "buyerFeedbackCount": 291, "automated": false, "period": "Letzter Monat", "verifiedPurchase": true, "comment": "Schnell, gut verpackt, danke!", "itemId": null, "itemTitle": null, "thisListing": true }
    ],
    "soldPeriod": null,
    "buyerName": null,
    "buyerFeedbackCount": null,
    "verifiedPurchase": null,
    "feedbackText": null,
    "feedbackId": null,
    "feedbackRating": null,
    "automatedFeedback": null,
    "badges": ["Refurbished"],
    "sponsored": null,
    "description": "Generalüberholtes Gerät, neuer Akku.",
    "specifics": { "Marke": "Apple", "Modell": "iPhone 13" },
    "brand": "Apple",
    "ean": null,
    "mpn": null,
    "productId": "2320328646",
    "productRating": 4.5,
    "productReviewCount": 136,
    "categories": ["Handys & Kommunikation", "Handys & Smartphones"],
    "categoryId": "9355",
    "images": ["https://i.ebayimg.com/images/g/abc/s-l1600.jpg"],
    "imageUrl": "https://i.ebayimg.com/images/g/abc/s-l1600.jpg",
    "publishedAt": null,
    "searchQuery": "iphone 13",
    "searchUrl": "https://www.ebay.de/sch/i.html?_nkw=iphone+13&_sop=12&_ipg=240&_pgn=1",
    "searchPage": 1,
    "searchPosition": 5,
    "scrapedAt": "2026-09-20T12:00:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 70 fields

| Fields                                                                | What you get                                                                     |
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `recordType`, `id`, `listingId`, `url`, `title`, `marketplace`          | `listing` (or `sale`), `267443825233` (the feedback id on a sale), the item number, `https://www.ebay.de/itm/267443825233`, `Apple iPhone 13 256GB`, `ebay.de` |
| `price`, `priceMax`, `priceText`, `priceWithCoupon`, `listPrice`, `currency` | `276.21`, `276.21`, `EUR 276,21`, `262.4`, `851.32` (UVP, when eBay prints one), `EUR` |
| `condition`, `buyingFormat`, `bidCount`, `timeLeftText`, `endsAt`       | `Gut - Refurbished`, `buyItNow`, `7`, `Noch 3 Std 12 Min`, `null`            |
| `shippingCost`, `shippingText`, `freeShipping`, `shipsFrom`             | `0`, `Kostenloser Versand`, `true`, `Italien`                                |
| `returnsAccepted`, `returnsText`                                        | `true`, `Kostenloser Rückversand`                                            |
| `watchers`, `soldQuantity`, `quantityAvailable`                         | `11`, `24`, `3` — how many people watch it, how many are already sold        |
| `sellerName`, `storeName`, `sellerUrl`, `sellerFeedbackPercent`, `sellerFeedbackCount` | `aix-axore` (user name), `AXORE` (shop name), `https://www.ebay.de/str/miniumitalia`, `99`, `11625` |
| `sellerType`, `sellerLegal`                                             | `commercial` (Gewerblich) or `private` (Privat), and the trader's legal details |
| `sellerItemsSold`, `sellerMemberSince`, `sellerAbout`, `sellerLogoUrl`, `sellerDetailedRatings` | `43384` units sold in total, `Nov 2017`, the seller's own presentation, its logo, `{"Lieferzeit": 5, "Kommunikation": 5, …}` |
| `sellerReviews`                                                         | with **Seller reviews**: `[{"rating": "positive", "buyerName": "9***s", "buyerFeedbackCount": 291, "period": "Letzter Monat", "verifiedPurchase": true, "comment": "…", "itemId": …, "itemTitle": …, "thisListing": true, "automated": false}]` |
| `soldPeriod`, `buyerName`, `buyerFeedbackCount`, `verifiedPurchase`, `feedbackText`, `feedbackId`, `feedbackRating`, `automatedFeedback` | a sale only (`recordType` = `sale`, price = the price paid): `Past 6 months`, `e***s`, `163`, `true`, the buyer's comment, its id, `positive`, `false` (`true` when eBay left it itself) |
| `badges`, `sponsored`                                                   | `["Refurbished"]`, `true` for a card in eBay's advert block (else `null`)      |
| `description`, `descriptionUrl`, `specifics`, `brand`, `ean`, `mpn`, `categories`, `categoryId` | full text (with **Include description**), the page it comes from, the `Artikelmerkmale` table, `Apple`, EAN, part number, breadcrumb, `9355` |
| `productId`, `productRating`, `productReviewCount`                      | the eBay catalogue product (ePID) `2320328646`, its stars `4.5` and `136` reviews |
| `taxText`, `variations`                                                 | `(inkl. MwSt.)`, and the size / colour dropdowns: `[{"name": "Größe", "values": ["S", "M", "L"]}]` |
| `images`, `imageUrl`                                                    | every photo, full size                                                        |
| `publishedAt`, `searchQuery`, `searchUrl`, `searchPage`, `searchPosition`, `scrapedAt` | `null` (eBay publishes no listing date), `iphone 13`, the search it came from, results page `1` and rank `5` on it, ISO timestamp |

#### Price summary per search

With **Price summary per search** on, the run's key-value store gets a **PRICE_SUMMARY** record (a link in the Output tab): one entry per search with at least 5 priced listings, computed from the listings the run saved — after your filters, without the listings eBay only padded the search with. An auction counts at its current bid, a range of prices at its lowest.

```json
{
    "searchQuery": "nintendo switch oled",
    "listings": 100,
    "priced": 100,
    "currencies": [
        {
            "currency": "EUR",
            "listings": 100,
            "price": { "count": 100, "min": 56.86, "max": 299, "mean": 190.41, "median": 189.5, "p10": 131, "p25": 169.71, "p75": 209.99, "p90": 250.9, "stdDev": 44.66, "total": 19040.51 },
            "priceWithShipping": { "count": 100, "min": 64.55, "median": 190, "p90": 259.49, "…": "…" },
            "auctions": 11,
            "freeShipping": 36
        }
    ]
}
```

### 💡 Tips

#### How to get more results

Set `maxItems` to `0` and use a broad keyword. eBay itself caps how deep a single search goes, so several narrower searches (`searchQueries`, a `categoryId`, a price range) return more than one wide one. For monitoring, sort by `newlyListed` and schedule the Actor.

#### How to reduce costs

The price is per listing, so the levers are `maxItems`, `maxItemsPerQuery`, the filters eBay applies itself (a listing they drop is never read; the Actor's own filters cost a filter fee per listing checked) and `onlyNew` for recurring runs — you never pay twice for the same listing. Leaving `extractDetails` off (the default) keeps the price per listing lower and the run faster; turn it on for the item page fields.

#### Several searches in one run

Fill `searchQueries` and / or `sellers`: the Actor runs one search per keyword × seller (3 keywords × 4 sellers = 12 searches, up to 500 per run). The single `query` field still works and is added to the list. A listing found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget. You can also paste several search URLs into `startUrls`: each one is a search of its own, with the same cap.

#### Monitoring: only the new listings

Tick **Only new listings** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the listings already delivered: they are not saved, not charged, and their item page is not even opened. The memory lives in a named key-value store of your account (`ebay-listings-scraper-seen`, up to 150,000 listings per key) and is only updated with listings that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's listings), and tick `resetState` once to start over. Keyword searches left on the default sort are then sorted by newest (a pasted search URL keeps its own sort), and a newest-first search stops once it meets 240 listings in a row that you already have — one full results page (listings pinned at the top are not counted); with a `maxItems` / `maxItemsPerQuery` of your own, once 80 % of what the previous runs delivered under that cap is met again, in a row or not (a listing sold since, or a new one filed inside the block, never makes it read on). A search on another sort stops after 20 results pages in a row with nothing new. With **Only new listings**, a listing your filters drop is checked (and charged) once; the next runs with the same filters skip it for free. Change a filter, or tick `resetState`, to check them again.

#### Watchers, bids and units sold

eBay shows, on a live listing, how many people watch it (`watchers`), how many bids an auction has (`bidCount`) and how many units a multi-quantity listing has already sold (`soldQuantity`). `minWatchers` and `minSoldQuantity` keep only the listings that already have an audience, and `endingWithinHours` keeps the auctions about to close. A listing that shows none of these is dropped by those filters rather than kept with an empty value.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per eBay listing. Actor id: `nice_dev/ebay-listings-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/ebay-listings-scraper`.

Smallest input, for a cheap first call (results pages only):

```json
{
    "query": "iphone 13",
    "maxItems": 10,
    "extractDetails": false
}
```

Key output fields: `url`, `title`, `price`, `currency`, `condition`, `buyingFormat`, `sellerName`, `sellerFeedbackPercent`.

Cost: $0.63 per 1,000 listings from the results pages only ($0.60 on Gold), $1.39 with the item page read (`extractDetails`, off by default; $1.09 on Gold), plus $0.019 per run start ($0.038 at 2 GB of memory); the Actor's own filters are charged on top, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape eBay?

The Actor only reads what eBay shows publicly to any anonymous visitor. It logs in to nothing and solves no captcha. Results contain seller user names and ratings — and, with **Extract details**, the seller's own presentation text, which can hold a phone number — which are personal data protected by GDPR: do not store them without a legitimate reason. You are responsible for using the data in compliance with eBay's Terms of Use and applicable law. This Actor is not affiliated with eBay.

#### Can I get sold listings and sold prices?

Yes, seller by seller. Since August 2026 eBay shows its sold-listings search only to a signed-in account, and this Actor does not log in. What stays public is each seller's feedback page, where every buyer's rating names the item and the price paid: give **Sellers' sold prices** (`salesSellers`) a list of sellers and you get their recent sales, one row per sale (`recordType` = `sale`), with a period (« Past month ») rather than an exact date. On live listings the demand is there too: `watchers`, `bidCount`, and `soldQuantity` on multi-quantity listings.

#### How long does a run take?

A real browser opens once per session before the listings are read, so a run starts slower than a plain page reader. The default memory, **1 GB**, is enough for 500 listings with details (measured on the platform) and for sellers' sold prices; raise it to 2 GB only for very long runs. Measured on the platform: **20 listings with full details in about 3 minutes**, start included.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy cannot be chosen in the form). A request eBay turns away is retried at once on a new proxy session, up to 3 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 30 seconds). If the residential route is unavailable, the run stops and says so: what was already saved is kept, and the pages not read are not charged.

**Apify free plan:** the included proxy is for paying Apify plans only. On the free plan, add your own proxy URLs in **Proxy configuration**; without them the run stops at once with a message saying so.

#### Why do I get fewer listings than eBay shows?

When a search finds few or no listings, eBay fills the page with « results matching fewer words » (listings that hold only part of your keyword). The Actor stops at that point: those listings are not delivered and not charged, and the log says how many were left out. A search with 2 real results gives 2 rows, not 242. To widen a search on purpose, set `keywordMatch` to `anyWords`.

#### Is the data safe to open in Excel or to show on a web page?

Titles, descriptions and item specifics are the sellers' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a title such as `-20% heute`): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every URL field holds an http(s) URL or `null`. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- **Live listings only** — sold and completed listings are behind eBay's sign-in wall (see above).
- eBay publishes no listing date, so `publishedAt` is `null` and there is no date filter. Use `sortBy: "newlyListed"` and `onlyNew` to follow what appears.
- Site filters that are not in the input can still be used by pasting a filtered search URL into `startUrls`.
- The fields marked **detail** (listed above) come from the item page: they are `null` / empty when `extractDetails` is off, and `images` then holds the card's one photo.
- An item URL pasted in `startUrls` has no results card: `listPrice`, `badges`, `productId`, `productRating`, `productReviewCount` and the search fields (`searchQuery`, `searchUrl`, `searchPage`, `searchPosition`) stay empty; everything else is read on its item page.
- `sponsored` is `true` only for a card inside a block eBay names as adverts, `null` otherwise (eBay does not mark its other adverts in a readable way). `endsAt` is always `null`: eBay prints a countdown (`timeLeftText`), not an end date.
- `description` is empty unless `includeDescription` is on: eBay never puts the description text in the item page, only a link to the page that carries it (`descriptionUrl`). Reading it doubles the requests of a detailed run.
- `variations` names the size / colour choices of a listing; the price and stock of EACH variation are not published as data on the page, so one row stays one listing, at its lowest price (`price`) and highest (`priceMax`).
- `onlyNew` remembers listing ids, not their content: a listing whose price changed is not returned again.
- With `onlyNew`, a listing that does not pass a time-dependent filter yet (a minimum count that keeps rising — watchers, units sold, seller feedback count — or an auction not yet inside `endingWithinHours`) is checked again on the next run.
- Two runs sharing the same `stateKey` at the same time may both return the same new listing.

**A run the platform stops without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. The listings already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `extractDetails` on, the last listings read but not yet written at the moment of the stop (fewer than 50) are missing and not charged: the run fills their places with the next listings, up to `maxItems`.
- With `onlyNew`, the memory is saved right after each write (at most every 2 seconds): resurrect the stopped run and the listings it had saved meanwhile join the memory; leave it stopped for good, and the next run may return up to 2 seconds of them once more.

#### Something doesn't work?

The last line of the log counts the listings saved, filtered out and no longer on eBay (sold or ended while the run was reading them), and the requests that failed after every retry. Those requests and the removed listings are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause (a search URL that does not exist says so, instead of "run it again"). A run that saved some listings fails too when at least as many requests failed for good as were read: a green run with a short dataset would hide an outage. One failed request among many is only a warning.

If eBay changes its pages, you are told instead of paying for blank rows. A results page that counts listings but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No listings found". If the first 20 listings read all lack their title, price, seller or — with `extractDetails` — their item specifics, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first listings are charged. A listing whose price a filter cannot read counts among those 20.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

eBay search-result URLs (all filters set on the site are kept, pagination is automatic), single item URLs (always read on their item page, charged the item-page price) or seller feedback URLs (https://www.ebay.de/fdbk/feedback_profile/<seller>: that seller's sales, see Sold prices). When this list is not empty, the search fields below (keywords, sellers, site, category) are ignored; filters, caps and monitoring still apply. Max 1 000 URLs.

## `query` (type: `string`):

Free-text search, exactly as typed on eBay (e.g. `iphone 13`). Can stay empty with Sellers, Start URLs or Sellers' sold prices; with none of them there is nothing to search (eBay shows no listings without a keyword or a seller, a category alone included) and the run stops at once.

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

Several keywords in one run: one search per keyword. Added to **Search keyword**; listings found by several searches are saved once.

## `keywordMatch` (type: `string`):

How eBay matches your keyword — the keyword option of its own advanced search. **All words** is eBay's default: when a search finds few or no listings, eBay pads it with results matching fewer words — those are left out and never charged. **Any of the words** widens the search. **Exact phrase** and **Exact words** are stricter and pad nothing. A pasted search URL (Start URLs) keeps its own setting.

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

Which eBay marketplace to search. Prices and shipping are returned in that site's currency. With Start URLs, their own site is used (one site per run).

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

Restrict the search to one eBay category, by its numeric ID (the `_sacat=` value in an eBay search URL, e.g. `9355` for mobile phones). Empty = all categories.

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

Only listings from these eBay sellers, by user name (e.g. `rebuy-shop`). Each seller is searched with every keyword (keywords × sellers, max 500). Empty = all sellers.

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

Maximum number of listings to save for the whole run (after deduplication and filters). 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (keyword × seller, or search URL), so that the first search cannot use up the whole **Max listings** budget. 0 = no per-search cap.

## `extractDetails` (type: `boolean`):

Open each item page (1 extra request per listing) for all photos, item specifics, brand / EAN, categories, quantity available, the seller's block (shop, profile link, units sold, detailed ratings) and — for commercial sellers — their legal details. Off = results-card fields only: one request per results page of up to 240 listings, cheaper and much faster. The description text needs **Include description** as well.

## `includeDescription` (type: `boolean`):

Also read the description text (1 MORE request per listing, on top of **Extract details**). eBay serves it in a separate page, never in the item page: off, the **description** column is empty and **descriptionUrl** points at that page.

## `includePriceSummary` (type: `boolean`):

At the end of the run, sum up the prices of each search: number of listings, lowest, highest, mean, median, 10th / 25th / 75th / 90th percentiles, standard deviation and total, per currency, with and without shipping (plus how many auctions and free-shipping listings). Computed from the listings this run saved (after your filters; listings eBay only padded the search with are left out), for each search with at least 5 priced listings. Saved in the **PRICE_SUMMARY** record of the run's key-value store (Output tab). Charged once per search summed up, never for a search with too few prices. No extra request to eBay.

## `includeSellerContact` (type: `boolean`):

With **Extract details**, fill `sellerLegal` with the legal details a commercial seller publishes on its item page (company name, address, phone, e-mail, VAT and register numbers). Charged as a separate `seller-contact` event, only for listings where they are found (private sellers have none). Off = `sellerLegal` is empty. No extra request to eBay. Ticked alone, it gives nothing unless **Extract details** is on or an item URL is pasted in Start URLs: the run says so in its log.

## `includeSellerReviews` (type: `boolean`):

With **Extract details**, add in `sellerReviews` the buyers' reviews of the seller the item page shows (up to 16: rating, masked buyer and score, period, verified purchase, comment, and the item each is about). Charged per review delivered (`seller-review` event); nothing for a listing without any. No extra request to eBay.

## `salesSellers` (type: `array`):

eBay user names of sellers (e.g. `aix-axore`) whose recent sales you want, with the price paid. Runs with or without a search: with a search keyword, only the sales whose title matches it (eBay's own feedback search, over the last 5 years — Sales period is then applied by the Actor on each sale's period). Each sale is one result (`recordType` = `sale`). Not on ebay.be, which serves no feedback page: choose ebay.fr or ebay.nl (same sellers, same sales).

## `maxSalesPerSeller` (type: `integer`):

Stop after this many sales read from one seller's feedback (kept or not by your filters: they are read 200 at a time). 0 = all of them, up to 40,000 (the last 5 years eBay keeps).

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

Only the feedback left in this period (eBay's own filter on the feedback page; with a search keyword, which eBay does not combine with a period, the Actor keeps only the sales of the period).

## `condition` (type: `array`):

Item condition. Empty = any condition.

## `buyingFormat` (type: `string`):

Auction, fixed price (Sofort-Kaufen) or listings accepting a best offer.

## `sellerType` (type: `string`):

Private sellers (Privat) or commercial sellers (Gewerblich). This is an eBay.de distinction — commercial sellers must publish legal details and grant statutory returns.

## `minPrice` (type: `integer`):

Lowest price, in the currency of the chosen eBay site.

## `maxPrice` (type: `integer`):

Highest price, in the currency of the chosen eBay site.

## `itemLocation` (type: `string`):

Where the item ships from — eBay's own filter. The region is the site's: European Union on the European sites, North America on ebay.com and ebay.ca, none on ebay.com.au; a region the site does not offer is refused.

## `freeShipping` (type: `boolean`):

Only listings with free delivery (Kostenloser Versand).

## `returnsAccepted` (type: `boolean`):

Only listings that accept returns (Rücknahme akzeptiert).

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

eBay's own sort order. It decides which listings come first when **Max listings** stops the run.

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

Drop the listings whose title contains one of these words, e.g. `defekt` (case and accents ignored).

## `titleMustMatchQuery` (type: `boolean`):

Keep only the listings whose TITLE contains every word of their own search keyword (at least one with **Any of the words**). eBay also returns listings found through their item specifics or a "compatible with" list — a part number alone brings back accessories: this drops them before their item page is opened, so they are never charged as a listing (each listing checked is charged the filter fee, kept or not). Case, accents and punctuation are ignored (`18V-55` = `18v 55` = `18v55`), a number counts whole (`5Ah` is not in `7,5Ah`); in the keyword, `-word` (excluded by eBay) is skipped, `(a,b)` needs one of `a` / `b`, quotes and `*` are dropped. Listings from pasted item URLs are kept.

## `minSellerFeedbackPercent` (type: `integer`):

Drop listings from sellers whose positive-feedback percentage is below this (e.g. `98`). Listings without a rating are dropped. 0 = no filter. With **Extract details**, a listing whose results card does not show the figure is decided on its item page.

## `minSellerFeedbackCount` (type: `integer`):

Drop listings from sellers with fewer ratings than this (e.g. `50`). Useful to skip brand-new accounts. Listings without a rating count are dropped. 0 = no filter. With **Extract details**, a listing whose results card does not show the figure is decided on its item page.

## `minWatchers` (type: `integer`):

Only listings watched by at least this many people (e.g. `5`) — a live demand signal eBay still publishes (Beobachter). Listings without a watcher count are dropped. 0 = no filter. With **Extract details**, a listing whose results card does not show the figure is decided on its item page.

## `minSoldQuantity` (type: `integer`):

Only listings that already sold at least this many units (e.g. `1`), shown on multi-quantity fixed-price listings (N verkauft). Listings without a sold count are dropped. 0 = no filter. With **Extract details**, a listing whose results card does not show the figure is decided on its item page.

## `endingWithinHours` (type: `integer`):

Only auctions whose end time is within this many hours (e.g. `24`). Leave empty to keep every listing.

## `onlyNew` (type: `boolean`):

Skip the listings that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and their item page is not even opened. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new listings**. Give each schedule / task its own key (e.g. `iphone-de`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every listing again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: the proxy this Actor needs is included in the price. On the Apify free plan the included proxy is not available: add your own proxy URLs, or the run stops at once with a message.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel. eBay watches the pace: raising this makes blocks more likely, not the run faster.

## `maxRequestsPerMinute` (type: `integer`):

Global request budget per minute. With **Include description**, a listing page and its description count as ONE request here (the description is read together with its page): up to twice as many requests reach eBay. Lower it if the log shows eBay refusing requests.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute budget, this spreads the requests evenly instead of letting them go out in a burst — the description of a listing is spaced the same way.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request eBay turns away is also retried on a new proxy session up to 3 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "query": "iphone 13",
  "searchQueries": [],
  "keywordMatch": "allWords",
  "ebaySite": "ebay.de",
  "sellers": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "extractDetails": false,
  "includeDescription": false,
  "includePriceSummary": false,
  "includeSellerContact": false,
  "includeSellerReviews": false,
  "salesSellers": [],
  "maxSalesPerSeller": 200,
  "salesPeriod": "all",
  "condition": [],
  "buyingFormat": "all",
  "sellerType": "all",
  "itemLocation": "all",
  "freeShipping": false,
  "returnsAccepted": false,
  "sortBy": "bestMatch",
  "excludeKeywords": [],
  "titleMustMatchQuery": false,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 2,
  "maxRequestsPerMinute": 60,
  "minRequestIntervalMs": 1000,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

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

No description

## `priceSummary` (type: `string`):

With **Price summary per search** on: count, min, max, mean, median and percentiles of the prices of each search, per currency.

# 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 = {
    "query": "iphone 13",
    "ebaySite": "ebay.de",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/ebay-listings-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 = {
    "query": "iphone 13",
    "ebaySite": "ebay.de",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/ebay-listings-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 '{
  "query": "iphone 13",
  "ebaySite": "ebay.de",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/ebay-listings-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/ebay-listings-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/FF7WG4X4aoLpzUYbh/builds/IlwPFKFj8K2wpMaj1/openapi.json
