# Marketplace Arbitrage Score 📈 (resale margin vs eBay comps) (`tagadanar/marketplace-arbitrage-score`) Actor

Score the resale margin on any marketplace listing. Matches Craigslist or Subito listings to eBay price comps and returns the spread: what you'd clear after fees vs the buy price. Asking-price comps by default; add your eBay session to unlock real sold comps. No API key, platform usage included.

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

## Pricing

from $1.40 / 1,000 listing scoreds

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?

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

## Marketplace Arbitrage Score 📈

**Score the resale margin on any marketplace listing.** Give it a product (or a
marketplace search URL) and it pulls the listings, matches each one to **eBay
price comps**, and tells you the spread: what you'd clear reselling on eBay after
fees, versus the buy price. Buy-low / sell-high sourcing, in one run.

It generalises the deal-score idea (asking price vs a market benchmark) from
property to **resellable goods** — the benchmark here is the median eBay comp for
the *same* item, matched title-by-title.

### What you get

For every marketplace listing (a `recordType: "listing"` row):

| field | meaning |
|---|---|
| `listingPrice` / `currency` | the buy price on the marketplace |
| `compValue` | benchmark eBay comp price, in the listing's currency |
| `compBasis` | **`sold`** (real sold prices — needs your eBay cookie) or **`asking`** (live listing prices — the default) |
| `netResale` | `compValue × (1 − fees%)` — what you clear after selling fees |
| `spread` | `netResale − listingPrice` |
| `arbitrageScore` | resale **ROI %** = `spread / buyPrice × 100` (positive = profit) |
| `arbitrageLabel` | Strong flip / Good flip / Thin margin / Around break-even / Underwater |
| `confidence` | high / medium / low (from comp count, price spread, match quality, FX) |
| `matchQuality` | how well the listing matched its comps (strong / weak / none) |

Plus one `recordType: "summary"` row per search, carrying the comp basis and the
aggregate score (how many listings, how many profitable, best/median spread).

### Sold vs asking comps (important)

Since **July 2026, eBay shows *sold* prices only to signed-in visitors.** So:

- **Without a cookie (default):** comps are eBay **live asking prices**, always
  labeled `compBasis: "asking"`. Asking prices run higher than realized sales, so
  the score is optimistic — confidence is capped at *medium* to say so.
- **With your eBay cookie:** comps are **real sold prices** (`compBasis: "sold"`)
  — the number resellers actually want. Paste your signed-in eBay session into
  **eBay sign-in cookies**: either the JSON export of a cookie extension like
  Cookie-Editor, or the raw `Cookie:` header from your browser's DevTools. It is
  stored encrypted and never logged.

The actor **never labels a price as sold unless you provided a cookie.**

### Input

| field | required | notes |
|---|---|---|
| `source` | – | `craigslist` (US, USD) or `subito` (Italy, EUR). Default `craigslist`. |
| `query` | one of query/URLs | product searches, e.g. `["nintendo switch", "airpods pro"]` |
| `listingUrls` | one of query/URLs | marketplace search-page URLs, pasted from your browser |
| `location` | – | Craigslist city subdomain (e.g. `sfbay`, `newyork`) or Subito region slug |
| `ebayCookie` | – | your signed-in eBay session — unlocks **sold** comps |
| `feesPct` | – | selling fees deducted from the comp (default 13, eBay's ~final value fee) |
| `maxItems` | – | total listings to score (default 25) |

#### Example

```json
{
  "source": "craigslist",
  "query": ["nintendo switch"],
  "location": "newyork",
  "feesPct": 13,
  "maxItems": 25
}
```

### How the match works

The eBay comps are fetched **once per search** and each marketplace listing is
matched — by title tokens, weighting model/capacity numbers ("13", "128gb",
"oled") — to the *subset* of comps describing the same good. So a single "nintendo
switch" search correctly benchmarks an OLED console against OLED comps and a
Joy-Con pair against Joy-Con comps, without a separate eBay lookup per listing.
Prices in a different currency than the comp are converted with a static,
approximate FX rate and flagged `fxApplied`.

### Pricing

All-in pricing — **platform usage (proxies, compute) is included**, no API key,
no separate proxy bill. Per-search summary rows are free.

| Event | Price | When |
| --- | --- | --- |
| Actor start | $0.001 | Flat, once per run |
| eBay comps fetched | $0.025 | Once per search whose eBay comp set was obtained (never when eBay was blocked or empty) |
| Listing scored | $2.00 per 1,000 | Per marketplace listing delivered, scored or explicitly unscored |

The comp fetch is one fixed lookup per search whatever `maxItems` is, so scoring
25 listings costs about the same as scoring 5; set `maxItems` to what you will
actually read.

### Notes

- Not affiliated with eBay, Craigslist or Subito. Respect each site's terms.
- Asking-price comps are an estimate of resale value, not a guarantee; sold comps
  (with your cookie) are the realistic figure.

# Actor input Schema

## `source` (type: `string`):

Which marketplace to source listings from. Its listings are matched to eBay price comps to score the resale margin.

## `query` (type: `array`):

One product search per entry, e.g. <code>nintendo switch oled</code>, <code>airpods pro</code>. Each is searched on the chosen marketplace AND on eBay for price comps; every marketplace listing is then scored for resale margin. Leave empty if you paste listing/search URLs below.

## `listingUrls` (type: `array`):

Paste marketplace search-page URLs (craigslist.org or subito.it) instead of, or in addition to, the keywords above. The eBay comp query is derived from the listings' titles.

## `location` (type: `string`):

For Craigslist, the city subdomain to search (e.g. <code>sfbay</code>, <code>newyork</code>, <code>losangeles</code>) — defaults to <code>newyork</code>. For Subito, an Italian region slug (e.g. <code>lombardia</code>). Ignored when you paste URLs that already carry a location.

## `ebayCookie` (type: `string`):

Optional. Since July 2026 eBay shows SOLD prices only to signed-in visitors. Paste your own signed-in eBay session to score against real SOLD comps: the JSON export of a cookie extension like Cookie-Editor, or the raw Cookie header from DevTools. Stored encrypted, never logged. Leave empty to score against clearly-labeled live ASKING-price comps (the default).

## `feesPct` (type: `integer`):

Selling fees deducted from the eBay comp before computing the spread (eBay final value fee is ~13%). The net resale = comp × (1 − fees%).

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

Total marketplace listings to score across all searches. You are charged per listing row delivered.

## Actor input object example

```json
{
  "source": "craigslist",
  "query": [
    "nintendo switch"
  ],
  "feesPct": 13,
  "maxItems": 10
}
```

# Actor output Schema

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

One record per marketplace listing (recordType "listing", with its arbitrage score) plus one comps/score summary per search (recordType "summary").

# 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": [
        "nintendo switch"
    ],
    "feesPct": 13,
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/marketplace-arbitrage-score").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": ["nintendo switch"],
    "feesPct": 13,
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/marketplace-arbitrage-score").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": [
    "nintendo switch"
  ],
  "feesPct": 13,
  "maxItems": 10
}' |
apify call tagadanar/marketplace-arbitrage-score --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tagadanar/marketplace-arbitrage-score"
        }
    }
}

```

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/q8clIPljsbOQo3CdV/builds/9OCyMwuZqdtH9Ifj5/openapi.json
