# eBay Store Scraper (`codingfrontend/ebay-store-scraper`) Actor

Extract public product listings and store details from eBay Stores.

- **URL**: https://apify.com/codingfrontend/ebay-store-scraper.md
- **Developed by:** [Coding Frontned](https://apify.com/codingfrontend) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 does eBay Store Scraper do?

eBay Store Scraper reads public [eBay](https://www.ebay.com/) Store, seller-listing, item, and search pages over ordinary direct HTTPS. It normalizes listing identity, pricing, condition, shipping, seller/store context, public ratings, and eBay-hosted media. It does not sign in, solve CAPTCHAs, bypass access controls, or collect private account data.

### Why use eBay Store Scraper?

Use it for marketplace catalog monitoring, resale research, price comparisons, store inventory snapshots, and downstream product discovery. It accepts multiple source URLs, follows same-route next-page links within a bounded per-source page budget, deduplicates by listing ID/URL, applies text/price/condition filters, and can sort the bounded collected set. The Actor also writes an `OUTPUT_SUMMARY` key-value record for run-level counts; it does not mix operational counters into normal listing rows.

### What data can eBay Store Scraper extract?

| Group | Fields |
| --- | --- |
| Identity | `productId`, `productTitle`, `productUrl`, `storeName`, `storeUrl`, `sellerUsername`, `sellerUrl` |
| Commercial | `price`, `priceFormatted`, `currency`, `originalPrice`, `shippingCost`, `shippingText`, `condition`, `availability`, `buyingFormat`, `itemLocation`, `soldCount` |
| Media and quality | `imageUrl`, `additionalImageUrls`, `rating`, `reviewCount`, `description`, `category` |
| Provenance | `searchUrl`, `pageUrl`, legacy `sourceUrl`, `pageNumber`/`pageNum`, `position`, `scrapedAt` |
| Diagnostics | When enabled, typed `{ "recordType", "diagnosticType", "url", "error", "errorCode", "scrapedAt" }` rows for blocks, failures, empty pages, or invalid fixtures |

### How to scrape eBay Stores

1. Open the Actor and paste one or more public eBay Store or search URLs into the **eBay source URLs** field.
2. Set `maxItems` for the global normal-record limit and `maxPages` for the per-source page limit.
3. Optionally choose `keyword`, `minPrice`, `maxPrice`, `condition`, and `sortBy`.
4. Enable or disable media and diagnostics as needed, then start the run.
5. Download the dataset from the Output tab and inspect `OUTPUT_SUMMARY` for coverage and access status.

Custom source URLs control where pages are collected. `maxItems` is global across all sources; `maxPages` is applied independently to each source. When `sortBy` is not `source`, all allowed pages are collected before sorting, so the run can cost more than a source-order run. Duplicate source URLs are removed before crawling.

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

Cost depends on the number of source pages, response size, retries, and the number of normal rows. This implementation uses one sequential HTTP request at a time. Increasing `maxPages`, enabling retries, or fetching several sources increases compute and target traffic. It has no browser rendering or paid proxy requirement. Use a small `maxItems`/`maxPages` first and respect eBay rate limits and terms.

### Input

See the input tab for the complete configuration. Supported fields include `startUrls` (array of `{ "url": "..." }`, with legacy string entries accepted), `maxItems` (default `50`, `1–500`), `maxProducts` (legacy alias), `maxPages` (default `1`, `1–20`), `startPage`, `keyword`, `minPrice`, `maxPrice`, `condition`, `sortBy` (`source`, `price_asc`, `price_desc`, `title`), `deduplicate` (default `true`), `includeMedia` (default `true`), `includeDiagnostics` (default `true`), `timeoutMs` (default `20000`, `3000–120000`), `requestTimeoutMs`, `requestTimeoutSecs`, `requestDelayMs` (default `0`, max `10000`), `maxRequestRetries` (default `0`, max `2`), `maxConcurrency` (currently `1`), `userAgent`, and the local-QA aliases `fixturePath`/`fixtureFile`.

All URLs must use an exact eBay marketplace hostname and HTTPS. Fixture paths must remain under the Actor directory. `proxyConfiguration` is intentionally not accepted because this Actor uses the native fetch transport and does not claim proxy routing.

#### Quick run

```json
{"startUrls":[{"url":"https://www.ebay.com/str/example-tools"}],"maxItems":10,"maxPages":1}
```

#### Filters and sorting

```json
{"startUrls":[{"url":"https://www.ebay.com/str/example-tools"}],"keyword":"drill","minPrice":20,"maxPrice":150,"condition":"New","sortBy":"price_asc","maxItems":10}
```

#### Multiple sources and pagination

```json
{"startUrls":[{"url":"https://www.ebay.com/str/example-tools"},{"url":"https://www.ebay.com/str/example-parts"}],"maxPages":2,"maxItems":25,"deduplicate":true}
```

#### Developer options

```json
{"startUrls":[{"url":"https://www.ebay.com/str/example-tools"}],"maxItems":5,"requestDelayMs":250,"maxRequestRetries":1,"timeoutMs":30000,"maxConcurrency":1}
```

#### Fixture-backed local QA

```json
{"fixturePath":"test/fixtures/store-page.html","startUrls":[{"url":"https://www.ebay.com/str/example-tools"}],"maxItems":2,"includeDiagnostics":true}
```

### Output

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

Normal listing example (shortened media):

```json
{"productId":"123456789012","productTitle":"Example cordless drill kit","productUrl":"https://www.ebay.com/itm/123456789012","price":89.99,"priceFormatted":"$89.99","currency":"USD","condition":"New","shippingText":"Free shipping","imageUrl":"https://i.ebayimg.com/images/g/example.jpg","additionalImageUrls":["https://i.ebayimg.com/images/g/example-side.jpg"],"pageNumber":1,"searchUrl":"https://www.ebay.com/str/example-tools","sourceUrl":"https://www.ebay.com/str/example-tools","sourceDomain":"www.ebay.com","scrapedAt":"2026-01-01T00:00:00.000Z"}
```

Diagnostic example:

```json
{"recordType":"diagnostic","diagnosticType":"access_blocked","url":"https://www.ebay.com/str/example-tools","error":"eBay returned a CAPTCHA or security challenge.","errorCode":"ACCESS_BLOCKED","scrapedAt":"2026-01-01T00:00:00.000Z"}
```

The `OUTPUT_SUMMARY` key-value record contains status, sources, pages, requests, retries, filtered and duplicate counts, normal/diagnostic counts, block counts, fixture mode, and completion time. A diagnostic row is not a successful listing and does not count toward `maxItems`. Missing source values are omitted rather than fabricated. Only eBay-hosted image hosts are retained.

### Tips and advanced options

Start with one public URL and `maxPages: 1`. For price or title sorting, the Actor must collect the bounded page set first. A detail/item URL can yield one source-backed listing; a Store/search URL may yield many. If a page is blocked, lower request volume and use the target's normal public route; do not try to bypass the challenge. Native fetch is used, so no proxy is silently implied.

### FAQ, support, and responsible use

HTTP errors, challenges, malformed fixtures, and empty pages produce bounded diagnostics when `includeDiagnostics` is enabled. If the run returns no normal rows, inspect `OUTPUT_SUMMARY` and the run log rather than treating diagnostics as data. Report reproducible issues in the Actor Issues tab with the run ID and summary.

Our Actors are ethical and do not extract private user data such as email addresses, gender, or location. They only extract what users have chosen to share publicly. Results could still contain personal data protected by GDPR and other laws; use a legitimate purpose and obtain legal advice when unsure. Follow eBay's terms, robots guidance, rate limits, and applicable law. This Actor is not affiliated with eBay.

### Local validation

From the Actor directory:

```bash
npm install
npm test
npm run lint
npm run validate
npm run check
apify validate-schema
apify run --purge --input-file test/inputs/default.json
```

# Actor input Schema

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

One or more public HTTPS eBay Store, seller listing, item, or search URLs. Legacy string entries remain accepted by the runtime.

## `sourceUrls` (type: `array`):

Compatibility alias for startUrls.

## `urls` (type: `array`):

Compatibility alias for startUrls.

## `url` (type: `string`):

Compatibility alias for one start URL.

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

Global maximum of normal product records across all sources and pages.

## `maxPages` (type: `integer`):

Maximum pages fetched for each source URL. Page links are followed only on the same eBay route.

## `pages` (type: `integer`):

Compatibility alias for maxPages.

## `startPage` (type: `integer`):

Optional one-based page number used when the source route supports a page query parameter.

## `maxProducts` (type: `integer`):

Compatibility alias for maxItems; maxItems takes precedence when both are supplied.

## `keyword` (type: `string`):

Case-insensitive text filter over title, description, category, store, and seller fields.

## `searchQuery` (type: `string`):

Compatibility alias for keyword.

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

Keep records with a parsed price at or above this amount.

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

Keep records with a parsed price at or below this amount.

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

Optional exact condition filter, such as New, Used, or Open Box.

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

source preserves source order; other values sort the bounded collected set globally.

## `deduplicate` (type: `boolean`):

Deduplicate globally by listing ID, then canonical URL.

## `includeMedia` (type: `boolean`):

Include only eBay-hosted listing image URLs when enabled.

## `includeDiagnostics` (type: `boolean`):

Emit minimal diagnostic rows for blocks, request failures, empty pages, and invalid fixtures. Diagnostics do not count toward maxItems.

## `timeoutMs` (type: `integer`):

Maximum time for each public page request.

## `requestTimeoutMs` (type: `integer`):

Compatibility alias for timeoutMs; timeoutMs takes precedence.

## `requestTimeoutSecs` (type: `integer`):

Compatibility alias for timeoutMs in seconds; do not combine with a different timeout value.

## `requestDelayMs` (type: `integer`):

Respectful delay between sequential page requests.

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

Bounded retries for transient 429/5xx or transport failures. Blocks are not retried indefinitely.

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

This Actor processes pages in order and currently accepts only 1.

## `userAgent` (type: `string`):

Ordinary user-agent sent to public eBay pages; do not use it to evade access controls.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.ebay.com/str/"
    }
  ],
  "maxItems": 50,
  "maxPages": 1,
  "startPage": 1,
  "sortBy": "source",
  "deduplicate": true,
  "includeMedia": true,
  "includeDiagnostics": true,
  "timeoutMs": 20000,
  "requestDelayMs": 0,
  "maxRequestRetries": 0,
  "maxConcurrency": 1,
  "userAgent": "Mozilla/5.0 (compatible; EbayStoreScraper/1.0)"
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("codingfrontend/ebay-store-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("codingfrontend/ebay-store-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 '{}' |
apify call codingfrontend/ebay-store-scraper --silent --output-dataset

```

## MCP server setup

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