# eBay Cross-Market Price Finder - Buy Abroad, Net Margin (API) (`bruco3/ebay-cross-market-finder`) Actor

Compare what a product costs on one eBay marketplace (with shipping to you) against what it sells for on another, and get the net margin after eBay fees, currency conversion and import costs. Official eBay Browse API, no scraping. Schedule it for only new opportunities.

- **URL**: https://apify.com/bruco3/ebay-cross-market-finder.md
- **Developed by:** [Luca Pietrini](https://apify.com/bruco3) (community)
- **Categories:** E-commerce, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $17.00 / 1,000 opportunity founds

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

## eBay Cross-Market Price Finder — buy low on one eBay site, know what it sells for on another

The same product is often listed at very different prices on eBay.de, eBay.it, eBay.co.uk, eBay.com or eBay.fr. This Actor puts the two sides next to each other for any product you name: the cheapest **buyable** listings on a *source* marketplace (price **plus shipping to your country**) against the **current asking prices** for the same product on a *destination* marketplace — and computes the **net margin** after eBay selling fees, currency conversion (ECB rates) and import costs across the EU border.

Built on the **official eBay Browse API**, not on scraping: it does not break when eBay changes its pages, and it respects eBay's terms.

### What you get

One row per product with a positive opportunity, best margin first:

```json
{
  "query": "Bosch GSR 12V-35",
  "productKey": "title:12v-35 akkuschrauber bosch gsr",
  "confidence": "medium",
  "netMargin": 31.06,
  "netMarginPercent": 29.9,
  "currency": "EUR",
  "buy": {
    "marketplace": "EBAY_DE", "title": "Bosch GSR 12V-35 Professional Akkuschrauber Solo",
    "price": 98.89, "shippingToDestination": 4.99, "landed": 103.88, "currency": "EUR",
    "landedInDestinationCurrency": 103.88, "condition": "New", "epid": null,
    "sellerCountry": "DE", "sellerType": "BUSINESS", "sellerFeedbackPercent": 99.6,
    "url": "https://www.ebay.de/itm/…"
  },
  "sell": {
    "marketplace": "EBAY_IT",
    "comparables": { "count": 7, "epidMatches": 0, "min": 129.0, "p25": 135.9, "median": 139.9, "max": 189.0,
                     "examples": [{ "title": "Bosch Professional GSR 12V-35 …", "url": "https://www.ebay.it/itm/…" }] },
    "suggestedPrice": 134.54
  },
  "costs": {
    "sellPriceUsed": 139.9, "sellingFees": 0.35, "feePercentAssumed": 0.0, "fixedFeeAssumed": 0.35, "sellerTypeAssumed": "private",
    "importCosts": 0.0, "importPercentApplied": 0.0, "buyTotal": 103.88, "fxDate": "2026-09-21"
  },
  "checkedAt": "2026-09-22T09:40:12+00:00"
}
```

Every number that is an **assumption** (fee %, fixed fee, import %, FX date) is written in the row, so you can judge it — and override it in the input.

### How the matching works

Most eBay listings carry no product code, so titles decide:

1. **Exact match** when both listings share eBay's product id (`epid`) — `confidence: high` with 3+ matches.
2. Otherwise **title matching**: normalised tokens, marketing filler removed, similarity score, and two hard rules — **model numbers must agree** (`GSR 12V-35` never matches `GSR 18V-60`) and **accessories are excluded** (a listing that says *passend für / compatible / ricambio / brushes / charger / case* when yours does not). Listings far cheaper than yours are dropped too: the cheapest "match" for a drill is usually its carbon brushes.
3. The reference sell price is the **median** of comparables when there are 3 or more (the minimum otherwise); a **suggested listing price** just under the first quartile is included.

### Input

| Option | What it does |
|---|---|
| **Products to search** | one query per line, brand + model |
| **Buy on / Sell on** | any two of eBay DE, IT, FR, ES, NL, AT, BE, IE, PL, GB, US, CA, AU, CH |
| **Condition** | New / Used / Any — compared like with like |
| **Minimum net margin** (10) and **%** (15) | what counts as an opportunity |
| **Minimum comparables** (3) | how many similar destination listings make a reference price trustworthy |
| **You sell as** private / business | selling-fee assumption (private sellers pay no final value fee on European sites; business ~12.9%; US/CA/AU charge everyone) |
| Overrides | fee %, import % (automatic: 25% when the item crosses the EU border, 0% inside) |
| **Only new since last run** | remembers delivered listings; schedule it and get only new opportunities |
| Advanced | pages per marketplace (200 listings each), max results, max API calls per run, **your own eBay keys** |

### Pricing and quota

Pay per event: **one event per opportunity delivered** and a small one per eBay search page. A two-product check costs a few cents.

The Actor uses the official eBay API under its own keys, which eBay caps at 5,000 calls a day for *all* users together. The Actor keeps a shared daily counter and stops cleanly when it is reached. If you run it heavily, paste **your own eBay App ID and Cert ID** (free at [developer.ebay.com](https://developer.ebay.com)) into the input: your runs then use your quota only.

### What it is not

- It does not know **sold** prices (eBay's Marketplace Insights API is closed to new developers). Reference prices are current *asking* prices; the `comparables.count` tells you how crowded the market is.
- It does not buy or list anything. It gives you the numbers and the links.
- Import costs are an estimate; check duties for your category when the item crosses a customs border.

### Legal

Data is retrieved through the eBay Browse API under the eBay API License Agreement, at call time, and is not stored beyond your own dataset. Seller usernames are not included in the output.

### Related

- **[SEC Form D Funding Leads](https://apify.com/bruco3/sec-form-d-funding-leads)** — another "only new since last run" feed on an official source.
- **[Feed Monitor](https://apify.com/bruco3/feed-monitor)** — new items from RSS/Atom/JSON feeds.

### Feedback

A marketplace or a fee rule you need? Open an issue on the **Issues** tab. If it paid for itself, a short review helps others find it.

### Changelog

- **0.1** — initial release.

# Actor input Schema

## `queries` (type: `array`):

One search per line, as you would type it on eBay: brand + model works best (<code>Bosch GSR 12V-35</code>, <code>Garmin Fenix 7 Sapphire</code>, <code>Lego 75192</code>).

## `sourceMarketplace` (type: `string`):

Where to look for cheap listings. Prices include shipping to the destination country.

## `destinationMarketplace` (type: `string`):

Where the product would be resold; current asking prices there set the reference.

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

Compare like with like: new listings against new, used against used.

## `minNetMargin` (type: `integer`):

Only opportunities whose net result (after fees, shipping, conversion and import costs) is at least this amount.

## `minNetMarginPercent` (type: `integer`):

Net result as a percentage of the total buying cost.

## `minComparables` (type: `integer`):

How many similar listings must exist on the destination marketplace before the reference price counts as real. With 3+ the median is used; exact product-code (EPID) matches bypass this rule.

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

In the source marketplace's currency. Skips accessories and fragments.

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

In the source marketplace's currency.

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

Sets the eBay selling fees assumed on the destination: private sellers pay no final value fee on the European sites, business sellers about 12.9%; US/CA/AU charge everyone. Every row states the assumption.

## `feePercent` (type: `integer`):

Leave empty to use the table for your marketplace and seller type.

## `importCostPercent` (type: `integer`):

Applied to the landed buying price when the item crosses the EU border (e.g. UK or US seller, EU buyer). Empty = automatic: 25% across the EU border, 0% inside.

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

Remembers delivered source listings in a named key-value store. Turn on and schedule the Actor to be told only about listings you have not seen.

## `stateStoreName` (type: `string`):

Named key-value store used by 'only new'.

## `titleSimilarity` (type: `string`):

0.2-0.9. Lower finds more comparables (riskier), higher is stricter. Model numbers must always agree; accessories are always excluded.

## `sourcePages` (type: `integer`):

More pages = more candidates and more eBay API calls.

## `destinationPages` (type: `integer`):

More pages = better reference prices for popular products.

## `maxResults` (type: `integer`):

<code>0</code> = no limit.

## `maxApiCalls` (type: `integer`):

Each search page is one call. The Actor shares eBay's daily quota among all its users; heavy users should provide their own keys below.

## `ebayAppId` (type: `string`):

Bring your own eBay developer keys (free at developer.ebay.com) to use your own 5,000 calls/day quota instead of the shared one.

## `ebayCertId` (type: `string`):

The client secret matching the App ID above. Stored encrypted.

## Actor input object example

```json
{
  "queries": [
    "Bosch GSR 12V-35",
    "Makita DDF083"
  ],
  "sourceMarketplace": "EBAY_DE",
  "destinationMarketplace": "EBAY_IT",
  "condition": "NEW",
  "minNetMargin": 10,
  "minNetMarginPercent": 15,
  "minComparables": 3,
  "sellerType": "private",
  "onlyNew": false,
  "stateStoreName": "ebay-cross-market-state",
  "titleSimilarity": "0.45",
  "sourcePages": 1,
  "destinationPages": 1,
  "maxResults": 0,
  "maxApiCalls": 60
}
```

# Actor output Schema

## `opportunities` (type: `string`):

No description

## `summary` (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 = {
    "queries": [
        "Bosch GSR 12V-35",
        "Makita DDF083"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bruco3/ebay-cross-market-finder").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 = { "queries": [
        "Bosch GSR 12V-35",
        "Makita DDF083",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("bruco3/ebay-cross-market-finder").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 '{
  "queries": [
    "Bosch GSR 12V-35",
    "Makita DDF083"
  ]
}' |
apify call bruco3/ebay-cross-market-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bruco3/ebay-cross-market-finder"
        }
    }
}
```

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/kdNSHzJTzhDWZWqdO/builds/B8R7ULj7UllcVzDaX/openapi.json
