# eBay Scraper (`mlg14/ebay-scraper`) Actor

Scrape public eBay search listings across eight marketplaces. Export prices, shipping, condition, seller feedback, auction details, images, and listing links.

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

## Pricing

$1.00 / 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.

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

## eBay Scraper

Scrape eBay search listings by keyword and export eBay product data to CSV, JSON, or Excel. This eBay search API alternative collects public listing prices, shipping, conditions, seller feedback, auction details, and images across eight marketplaces.

Each dataset row represents one listing seen in a search result. Search several keywords in one run, apply marketplace filters, and retain the listing ID and collection time so later exports can be compared. The actor reads public search pages and does not require a buyer or seller account.

### What data can you extract from eBay?

The output is flat: each field is a top-level key in the dataset. Values that are absent from a particular search card are `null`, except `images`, which is an array. A listing can have a price range, a current auction price, or a fixed price. Interpret `price` alongside `priceMax`, `listingType`, and `shippingCost`.

| Field | Description | Example |
|---|---|---|
| `type` | Record type | `"product"` |
| `itemId` | Public listing identifier | `"358322153036"` |
| `title` | Listing headline | `"Wireless RGB Optical Gaming Mouse…"` |
| `price` | First displayed item price | `15.99` |
| `priceString` | First price with its display symbol | `"$15.99"` |
| `priceMax` | Upper end of a displayed range | `null` |
| `listPriceString` | Struck-through reference price | `null` |
| `marketplace` | Selected marketplace | `"US"` |
| `marketplaceDomain` | Search domain | `"www.ebay.com"` |
| `currency` | Marketplace currency context | `"USD"` |
| `shippingCost` | Displayed shipping message | `"+$9.24 delivery"` |
| `shippingPrice` | Numeric shipping amount, if clear | `9.24` |
| `totalPrice` | First price plus numeric shipping | `25.23` |
| `returnPolicy` | Returns text shown in results | `"Free returns"` |
| `coupon` | Public coupon message | `null` |
| `discountText` | Displayed percentage discount text | `null` |
| `condition` | Item condition shown below title | `"Brand New"` |
| `listingType` | Auction or fixed-price label | `"Buy It Now"` |
| `bidCount` | Current bids on an auction | `null` |
| `timeLeft` | Displayed time remaining | `null` |
| `bestOffer` | Whether Best Offer is shown | `false` |
| `soldCount` | Displayed number sold | `"339+"` |
| `sellerName` | Public seller name | populated when shown |
| `sellerFeedbackPercent` | Positive feedback display | `"98.6%"` |
| `sellerFeedbackCount` | Feedback-count display | `"765"` |
| `isSponsored` | Promotion flag in search data | `true` |
| `categoryId` | Public leaf category identifier | `"23160"` |
| `resultRank` | Zero-based rank on its search page | `1` |
| `itemLocation` | Displayed location text | `"Located in United States"` |
| `thumbnail` | Primary image URL | image URL |
| `images` | Image URLs present on the card | one URL in most rows |
| `url` | Direct listing link | `"https://www.ebay.com/itm/358322153036"` |
| `searchQuery` | Keyword that produced the row | `"wireless mouse"` |
| `scrapedAt` | UTC collection time | `"2026-09-26T13:32:02.839Z"` |

The numeric shipping fields help calculate a comparable first-item delivered price. They do not include tax, import fees, quantity discounts, or options selected after opening the listing. For a price range, `totalPrice` uses the first displayed price; inspect `priceMax` before treating that value as a complete offer.

### How to scrape eBay

1. Enter one or more product keywords in `searchQueries`. Use a concrete phrase such as `wireless mouse` to keep results relevant.
2. Choose the marketplace. `US` searches ebay.com; the other choices use their corresponding country domains and currency context.
3. Set `maxProductsPerSearch` and `maxSearchPages`. Add condition, listing type, price, or sort filters when you need a narrower set.
4. Run the actor and open its default dataset. Review several rows, including shipping and condition, before using the export for comparisons.
5. Download the dataset as JSON, CSV, or Excel. Keep `itemId`, `searchQuery`, and `scrapedAt` if you plan to merge later runs.

A keyword starts a separate search. The actor removes duplicate listing IDs within the run, so overlapping keywords may produce fewer rows than the sum of their individual limits. The order of keywords affects which query is recorded for a listing that appears in more than one search.

### Input

| Name | Type | Default | Description |
|---|---|---|---|
| `searchQueries` | array of strings | required | One or more search phrases. |
| `marketplace` | string | `US` | `US`, `UK`, `DE`, `FR`, `IT`, `ES`, `CA`, or `AU`. |
| `maxProductsPerSearch` | integer | `100` | Per-keyword result cap. |
| `maxSearchPages` | integer | `5` | Per-keyword page cap, up to 20. |
| `maxItems` | integer | `0` | Total dataset cap; zero means no total cap. |
| `sort` | string | `best_match` | Best match, ending soonest, newly listed, or price with shipping in either direction. |
| `condition` | array | `[]` | New, open box, refurbished, used, or for parts; empty includes all. |
| `listingType` | string | `all` | All, auction, or Buy It Now. |
| `minPrice` | integer | unset | Minimum item price in the marketplace currency. |
| `maxPrice` | integer | unset | Maximum item price in the marketplace currency. |
| `maxRequestRetries` | integer | `5` | Browser attempts per search page when access fails. |

Example input for a bounded first run:

```json
{
  "searchQueries": ["wireless mouse"],
  "marketplace": "US",
  "maxProductsPerSearch": 40,
  "maxSearchPages": 1,
  "sort": "best_match"
}
```

`maxProductsPerSearch` limits items saved from each keyword. `maxSearchPages` limits pages opened, even when the item cap is higher. For example, a one-page run cannot obtain 200 unique listings from a page that displays at most 60. Use `maxItems` when you need a single ceiling across a batch of searches.

Filters are combined in the search URL. A narrow price range plus a condition and listing-type filter can return very few results. If that happens, remove filters one at a time and inspect the public result count. Refurbished includes the displayed refurbished grades, rather than only one grade. The price filter applies to the listing price in the selected marketplace; it is not a ceiling on `totalPrice` after delivery.

### Output example

This shortened record comes from a successful 40-item US search for `wireless mouse` on September 26, 2026. It retains the values used for price comparison; the full dataset row also contains the other fields listed above.

```json
{
  "type": "product",
  "itemId": "358322153036",
  "title": "Wireless RGB Optical Gaming Mouse – LED Backlit OEM Mouse for Laptop & Tablet",
  "price": 15.99,
  "priceString": "$15.99",
  "marketplace": "US",
  "marketplaceDomain": "www.ebay.com",
  "currency": "USD",
  "shippingCost": "+$9.24 delivery",
  "shippingPrice": 9.24,
  "totalPrice": 25.23,
  "condition": "Brand New",
  "listingType": "Buy It Now",
  "isSponsored": true,
  "url": "https://www.ebay.com/itm/358322153036",
  "searchQuery": "wireless mouse",
  "scrapedAt": "2026-09-26T13:32:02.839Z"
}
```

Treat this as a snapshot. Sellers can revise prices, delivery terms, availability, or listing text after collection. Open the `url` to verify a specific offer before purchasing or changing a price in another system.

### Use cases

- **Price monitoring:** Search the same phrase on a schedule, join snapshots by `itemId`, and compare `price`, `shippingPrice`, and `totalPrice` over time.
- **Resale research:** Build a shortlist by condition and price, then inspect the listing page for item details and fees that search cards do not show.
- **Auction watchlists:** Restrict the search to auctions, sort by ending soonest, and review the current bid and remaining time. A bid price can change until an auction ends.
- **Marketplace comparison:** Run equivalent keywords in separate marketplace runs. Keep the marketplace and currency fields, and perform any currency conversion outside the actor.
- **Seller analysis:** Group listings by the public seller name, then inspect feedback displays and offered prices. Search-result feedback is a display value rather than an independent assessment.
- **Catalog discovery:** Collect titles, images, conditions, and category identifiers to understand which public listings appear for a phrase.

These workflows use active search listings. A displayed price is an asking or current auction price, not evidence of a completed sale. The result set can also include promoted listings, which are flagged when the embedded search data supplies that signal.

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

The actor is configured at **$1 per 1,000 saved products**, or **$0.001 per result**. The number of pages opened is not itself the billing unit. Check the actor's current pricing panel before starting a large run because pricing can change. The following examples cover result charges at that rate:

| Saved products | Result charge |
|---:|---:|
| 40 | $0.04 |
| 1,000 | $1.00 |
| 5,000 | $5.00 |

A search that returns fewer products than its limit charges for the products actually saved. Repeated scheduled runs produce separate datasets and separate result charges. Platform account limits and any applicable account charges are shown in your Apify account. Set `maxItems` to make a batch's result ceiling explicit.

### Tips for best results

Start with one keyword and one page. Confirm that the search returns the expected item category and price range, then increase limits. Specific phrases reduce irrelevant matches; broad phrases are useful for discovery but tend to mix conditions, brands, and accessory types. A result's title alone does not establish compatibility or completeness.

Use the condition and listing-type filters for comparisons that require like-for-like offers. New and used items can differ sharply in price. Auctions and fixed-price listings also have different meanings: an auction's current amount may increase, while a fixed-price listing may have a Best Offer option. If you need a delivered-price comparison, prefer rows with a numeric `shippingPrice` and read the shipping message for qualifiers.

To monitor an assortment, send multiple search phrases in `searchQueries`. Use one run for a consistent snapshot, then schedule the same input again and compare rows by `itemId`. A listing that disappears from a later keyword result may still be active; search rank and filters can change. Verify its direct URL before inferring that it ended.

For deeper coverage, raise `maxSearchPages` gradually. Each page requests up to 60 listings and the actor stops at the smaller of its page and product limits. Very broad searches can expose a large number of result pages, but this actor caps each keyword at 20 pages. Split the research into more specific keywords, condition groups, or price bands when you need more coverage. Deduplicate by `itemId` when combining separate runs.

### Limits

The actor reads public **search result cards**, not individual item detail pages. Search cards usually expose one primary image. `images` may therefore contain only the same URL as `thumbnail`. Seller details, returns, coupons, sold counts, and discount text appear only when the search card supplies them. Empty optional fields are expected and should not be interpreted as negative claims about a listing.

The first numeric price in a range is stored in `price`, with the upper end in `priceMax` when displayed. Delivery amounts are added only when a clear numeric charge or free-delivery message is present. Import fees, taxes, local collection arrangements, and variation-specific prices require separate review. The `currency` field states the selected marketplace's currency context; inspect the displayed `priceString` where cross-border listings can be shown in a different display format.

Access to public search pages can be intermittent. The actor retries with a fresh session and escalates its connection when the initial route is blocked. A persistent block or a changed page structure can leave a query incomplete. The run logs identify failed pages; review the dataset count against your requested limits. A successful run means rows were saved and validated for the supplied input, not that every possible keyword or marketplace always yields the same fill rates.

The verified input collected 40 US listings and filled every required field in its dataset check. Other marketplaces and filter combinations are configured but were not part of that check. Localized labels may affect optional fields such as listing type, seller feedback, or item location. Use a small first run in the target marketplace before depending on those optional fields.

### Programmatic workflows

You can start a run with a structured input and retrieve its default dataset through the Apify API. Two practical requests are: “Search public US listings for wireless mice, return 40 results, and compare first price plus delivery,” and “Find auctions for vintage watches ending soonest, then show current bids and remaining time.” Use `itemId` as the stable key when a workflow joins results from separate snapshots.

For automated monitoring, schedule a recurring run and send its dataset to a spreadsheet or database. Store the run time alongside each row. If a downstream rule sends alerts, include the direct listing URL and the observed price so a reviewer can verify the offer. Avoid automatically treating a missing search result as a sale, since search rankings and item eligibility change.

### FAQ

**Do I need an eBay account?** No. The actor searches publicly visible listings and does not sign in. Private account pages and purchase history are outside its scope.

**Do I need to configure a proxy?** No separate proxy input is required. The actor handles its connection as part of the run. Temporary blocks may still require retries, and a persistent block can prevent a query from completing.

**How fast is a run?** Duration varies with page count, marketplace response, and retries. The verified 40-item run finished in about a minute, including startup. Use fewer pages and a smaller result cap for quick checks.

**Can I schedule and monitor searches?** Yes. Save an input and schedule repeated runs in Apify. Compare datasets by `itemId` and `scrapedAt`; inspect run logs when a snapshot is unexpectedly small.

**Can I export to a spreadsheet?** Yes. Download the default dataset as CSV or Excel, or send it to a connected spreadsheet workflow. Numeric `price`, `shippingPrice`, and `totalPrice` are suitable for sorting and calculations.

**Why is a field empty?** Search cards vary. Auctions may have bids and time remaining but no sold count; fixed-price listings often lack bid data. Some sellers or shipping terms are not displayed in every card. Optional fields remain `null` when unavailable.

**Can this collect sold prices or full item specifications?** No. It targets active keyword search results and does not open item detail pages. An asking price or current bid is not a completed-sale price.

**Is scraping public listings allowed?** Laws and site terms vary by place and use. Review the applicable terms and privacy rules, collect only data you need, and avoid misuse of public seller information. This actor does not access account-only pages.

### Integrations

Use the Apify API, schedules, webhooks, or supported automation integrations to start searches and move datasets into your reporting stack. JSON preserves the complete record; CSV and Excel are convenient for quick price comparisons. Keep timestamps and listing IDs when you merge runs, and use a downstream process for currency conversion or alerts.

### Support

Open an issue on the Issues tab with a run link, the marketplace, and a sanitized input. We reply within 24 hours and add fields on request.

# Actor input Schema

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

Search terms to run separately. Enter at least one keyword.

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

Marketplace domain and currency context for the search.

## `maxProductsPerSearch` (type: `integer`):

Maximum results to save for each keyword.

## `maxSearchPages` (type: `integer`):

Maximum search pages per keyword, with up to 60 listings on each page.

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

Stop after this many products across all searches. Zero means no total cap.

## `sort` (type: `string`):

How eBay orders search results.

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

Only include selected conditions. Leave empty for all.

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

Include all listings or only auction or fixed-price results.

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

Minimum listing price in the marketplace currency.

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

Maximum listing price in the marketplace currency.

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

Maximum browser attempts per search page when access fails.

## Actor input object example

```json
{
  "searchQueries": [
    "wireless mouse"
  ],
  "marketplace": "US",
  "maxProductsPerSearch": 100,
  "maxSearchPages": 5,
  "maxItems": 0,
  "sort": "best_match",
  "condition": [],
  "listingType": "all",
  "maxRequestRetries": 5
}
```

# Actor output Schema

## `products` (type: `string`):

All scraped listings in the default dataset.

# 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": [
        "wireless mouse"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/ebay-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": ["wireless mouse"] }

# Run the Actor and wait for it to finish
run = client.actor("mlg14/ebay-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": [
    "wireless mouse"
  ]
}' |
apify call mlg14/ebay-scraper --silent --output-dataset

```

## MCP server setup

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