# eBay Seller Inventory Monitor (`apt_marble/ebay-seller-inventory-monitor`) Actor

Watch any eBay seller's live listings and see exactly what changed since the last run: new items, price moves and removals, plus the full current inventory as clean rows. Choose the eBay site, keep the same seller list, and schedule it to build a running change history per seller.

- **URL**: https://apify.com/apt\_marble/ebay-seller-inventory-monitor.md
- **Developed by:** [Hamza](https://apify.com/apt_marble) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 inventory items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## eBay Seller Inventory Monitor

Watch any eBay seller's live listings and find out exactly what changed since the last run — new items added, prices moved up or down, and items taken down — while also getting the seller's full current inventory as clean, structured rows. Built for anyone who needs to keep a close eye on a shop over time: resellers tracking a competitor's every move, brands policing unauthorised sellers, sourcing teams spotting fresh stock the moment it goes live, and analysts building a running history of a shop's pricing and assortment. Give it a seller, put it on a schedule, and each run tells you what moved.

### What you can do with it

- **Track a competitor's shop** — see every new listing, every price move and every takedown between runs, with the before-and-after prices already worked out.
- **Get alerted to fresh stock** the moment a seller lists it, so you can react to new inventory before anyone else does.
- **Watch pricing over time** — schedule it daily or hourly and build your own history of how a seller prices their catalogue.
- **Police your brand** by monitoring the sellers who carry your products and catching new listings as they appear.
- **Snapshot a full inventory** on demand — pull every live item a seller currently has, as one row each, for a catalogue audit or a stock count.
- **Feed a dashboard** with a steady stream of change events per seller, each stamped with when it was first seen and when it was detected.

### What you get

Two kinds of rows. Every run outputs the seller's current inventory (one row per live item), and — from the second run onward — a change event for each thing that moved. Abridged samples.

A current-inventory row:

```json
{
  "type": "inventory_item",
  "seller": "discountcomputerdepot",
  "marketplace": "US",
  "itemId": "336747884909",
  "title": "Columbia C300Ball USA BOWLING BALL",
  "condition": "Pre-Owned",
  "price": 49.90,
  "currency": "USD",
  "buyingFormat": "BUY_IT_NOW",
  "freeShipping": true,
  "location": "United States",
  "listedAt": "2026-08-17T16:27:00",
  "listedAtText": "Aug-17 16:27",
  "imageUrl": "https://i.ebayimg.com/images/g/abcAAOSw/s-l500.webp",
  "url": "https://www.ebay.com/itm/336747884909",
  "firstSeenAt": "2026-08-10T09:00:00.000Z",
  "capturedAt": "2026-08-18T12:00:00.000Z"
}
```

A change event, when a price moves:

```json
{
  "type": "price_change",
  "seller": "discountcomputerdepot",
  "marketplace": "US",
  "itemId": "336747884909",
  "title": "Columbia C300Ball USA BOWLING BALL",
  "url": "https://www.ebay.com/itm/336747884909",
  "previousPrice": 54.90,
  "currentPrice": 49.90,
  "priceChange": -5,
  "currency": "USD",
  "listedAt": "2026-08-17T16:27:00",
  "firstSeenAt": "2026-08-10T09:00:00.000Z",
  "lastSeenAt": "2026-08-18T12:00:00.000Z",
  "detectedAt": "2026-08-18T12:00:00.000Z"
}
```

The `type` field tells the two apart: `inventory_item` for a current listing, and `new_listing`, `price_change` or `removed` for a change event.

### Input reference

| Setting | Type | Default | What it does |
| --- | --- | --- | --- |
| Sellers to monitor | list of text | — | The sellers to watch. Use eBay usernames, or links to their profile or store pages — mixed in the same list is fine. Keep the same list between runs so changes can be compared. Entries that are not eBay sellers are reported and skipped. **Required.** |
| eBay site | choice | `US` | Which country's eBay site to read. Prices come back in that site's own currency, and each site keeps its own change history per seller. |
| Maximum items per seller | whole number | `1000` | How many of each seller's newest live items to cover. To detect removed items reliably, set this above the seller's full inventory size. Maximum 5000. |
| Output the full current inventory | true/false | `true` | Output every currently listed item as its own row on every run, alongside any change events. Turn off to get change events only. |
| Parallel sellers | whole number | `4` | How many sellers to work on at the same time. Leave at 4 unless you have a reason. Maximum 10. |

### Output fields

**Current-inventory rows** (`type` = `inventory_item`)

| Field | Type | Description |
| --- | --- | --- |
| `type` | text | `inventory_item` for a current live listing. |
| `seller` | text | The seller this row belongs to, as you entered it. |
| `marketplace` | text | The eBay site the row was collected from. |
| `itemId` | text | eBay's item number. |
| `title` | text | Listing title as shown to shoppers. |
| `condition` | text | Item condition, when eBay states one. |
| `subtitle` | text | The seller's subtitle line, when present. |
| `price` | number | Listed price. For a price range this is the low end. |
| `priceTo` | number | The high end of a listed price range, when the listing shows one. |
| `currency` | text | Currency of the price, read from the eBay site itself. |
| `originalPrice` | number | The struck-through was-price, when the listing shows a markdown. |
| `buyingFormat` | text | `BUY_IT_NOW` or `AUCTION`. |
| `bestOffer` | true/false | Whether the listing accepts offers. |
| `bids` | number | Bid count on auction listings. |
| `timeLeft` | text | Time remaining, when eBay shows a countdown. |
| `shippingCost` | number | Delivery cost, or 0 when free. |
| `freeShipping` | true/false | Whether delivery is free. |
| `freeReturns` | true/false | Whether the listing offers free returns. |
| `location` | text | Where the item is located. |
| `newListing` | true/false | Whether eBay flags the item as newly listed. |
| `listedAt` | text | When the item was listed, in eBay's own display-local clock. |
| `listedAtText` | text | The listing time exactly as eBay rendered it. |
| `imageUrl` | text | Main image. |
| `url` | text | Clean listing link. |
| `firstSeenAt` | text | When this actor first saw the item for this seller. |
| `capturedAt` | text | When this row was collected. |

**Change events** (`type` = `new_listing`, `price_change` or `removed`)

| Field | Type | Description |
| --- | --- | --- |
| `type` | text | `new_listing`, `price_change`, or `removed`. |
| `seller` | text | The seller this change belongs to. |
| `marketplace` | text | The eBay site the change was seen on. |
| `itemId` | text | eBay's item number. |
| `title` | text | Listing title. |
| `url` | text | Clean listing link. |
| `previousPrice` | number | The price on the previous run. Empty for a brand-new listing. |
| `currentPrice` | number | The price now. Empty for a removed item. |
| `priceChange` | number | Current minus previous, for a repricing. |
| `currency` | text | Currency of the prices. |
| `listedAt` | text | When the item was listed. |
| `firstSeenAt` | text | When this actor first saw the item. |
| `lastSeenAt` | text | The last run this item was still live. |
| `detectedAt` | text | When this change was detected. |

### Pricing

You pay per result, with no monthly minimum. There are two kinds of result.

| What you are charged for | Price |
| --- | --- |
| Inventory item — one current live listing added to your dataset | **$0.60 per 1,000** |
| Inventory change detected — one new listing, price move or removal | **$3.00 per 1,000** |

Change events are priced above plain inventory rows because they are the answer this actor exists to give you: what actually moved, worked out for you, instead of two full inventories to compare by hand. The first run for each seller records a starting point and produces no change events — so you are never charged for "changes" against a shop you have never looked at before.

**Worked example.** You watch 20 sellers with about 300 live items each, on a daily schedule. Each run outputs roughly 6,000 inventory rows (6,000 × $0.0006 = **$3.60**). On a typical day a handful of items move per seller — say 200 changes across all 20 (200 × $0.003 = **$0.60**). That is about **$4.20 a day**. If you only care about what changed, turn off the full-inventory output and pay for the change events alone.

### Limits & what this actor cannot do

- **The first run for a seller is a starting point, not a report of changes.** It records what the seller has live right now so later runs have something to compare against. Change events begin on the second run.
- To be sure an item is really gone rather than just missing from one run, the actor waits until it stays absent across consecutive complete runs before reporting it removed — so a takedown may show up a run later than it happened.
- Removals are only judged when a run covers the seller's whole live inventory. If a run stops at the maximum-items limit, that run reports new items and price moves but does not decide anything was removed. Set the maximum above the seller's inventory size to catch removals reliably.
- It reports a seller's public **live** listings only — items currently for sale. Ended, sold and hidden listings are outside what this actor reads.
- Prices, bids and stock are a snapshot at the moment of collection and keep changing afterwards.
- Prices come back in the selected eBay site's own currency. Watching the same seller on two different sites keeps two separate histories, and a move between them is never mistaken for a price change.
- A seller with nothing currently listed and a username that does not exist look the same — both come back with no live items — so an empty result is not proof a seller is real but idle.
- On listings that take offers, and on auctions, the price shown is the listed price, not a hidden accepted or winning amount.
- Speed depends on the size of the job and on eBay's own response times; no fixed throughput is promised.
- eBay's terms govern automated access. You are responsible for using the data lawfully and in line with the source site's terms, and for handling any personal data in line with applicable privacy law.

### FAQ

**Do I need an eBay account?**
No. The actor reads only what eBay shows the public.

**Does it need my login or password?**
No. There is nothing to connect and nothing to configure — paste the sellers you want to watch and press start.

**Can I schedule it?**
Yes, and that is the point. Schedule it hourly, daily or weekly from the Apify console. Each run remembers the last one, so from the second run onward you get a clean list of exactly what changed.

**Why did my first run show no changes?**
Because there was nothing to compare it to yet. The first run for each seller records a starting point; changes are reported from the next run onward.

**How do I make sure removed items are caught?**
Set the maximum items per seller above the seller's full inventory size, so every run sees the whole shop. Removals are only decided when a run covers the entire live inventory.

**Is the data complete?**
It covers everything a seller has listed publicly and live. Sold, ended and hidden listings are not part of what this actor reports, and it says so rather than guessing.

# Actor input Schema

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

eBay seller usernames, or links to their profile or store pages. Keep the same list between runs so changes can be detected.

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

Which country's eBay site to read. Prices come back in that site's own currency, and each site keeps its own change history per seller.

## `maxItemsPerSeller` (type: `integer`):

How many of each seller's newest live items to cover. To detect removed items reliably, set this above the seller's full inventory size.

## `emitSnapshot` (type: `boolean`):

Output every currently listed item as its own row on every run, alongside any change events. Turn off to get change events only.

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

How many sellers to work on at the same time. Leave at 4 unless you have a reason.

## Actor input object example

```json
{
  "sellers": [
    "discountcomputerdepot"
  ],
  "marketplace": "US",
  "maxItemsPerSeller": 200,
  "emitSnapshot": true,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

Every inventory row and change event this run produced.

## `runSummary` (type: `string`):

What this run collected, what changed, and anything it could not read.

# 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 = {
    "sellers": [
        "discountcomputerdepot"
    ],
    "marketplace": "US",
    "maxItemsPerSeller": 200,
    "emitSnapshot": true,
    "maxConcurrency": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("apt_marble/ebay-seller-inventory-monitor").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 = {
    "sellers": ["discountcomputerdepot"],
    "marketplace": "US",
    "maxItemsPerSeller": 200,
    "emitSnapshot": True,
    "maxConcurrency": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("apt_marble/ebay-seller-inventory-monitor").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 '{
  "sellers": [
    "discountcomputerdepot"
  ],
  "marketplace": "US",
  "maxItemsPerSeller": 200,
  "emitSnapshot": true,
  "maxConcurrency": 4
}' |
apify call apt_marble/ebay-seller-inventory-monitor --silent --output-dataset

```

## MCP server setup

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

```

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/zmpJBhGBuYjkL0jaG/builds/Sv3zQW0lGdO02qIF2/openapi.json
