# EU Second-Hand Marketplaces Scraper: Vinted, OLX & More (`euroscrape/eu-marketplace-deals`) Actor

Search the top second-hand marketplaces of 18 European countries at once: Kleinanzeigen, Vinted, OLX, Marktplaats, Subito, Wallapop, willhaben, Blocket, DBA, FINN… Prices in €, deal score vs. the European market, cheapest country, resale margin and new-listing alerts.

- **URL**: https://apify.com/euroscrape/eu-marketplace-deals.md
- **Developed by:** [EuroScrape](https://apify.com/euroscrape) (community)
- **Categories:** E-commerce, Automation, Business
- **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 delivereds

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

## EU Second-Hand Marketplaces Scraper: Vinted, OLX & More

**Type a product once, for example `nintendo switch oled` or `iphone 13 128gb`, and search the biggest second-hand marketplace of 18 European countries at the same time.** Every price is converted to euros and compared with the rest of Europe, so you instantly see:

- 🏷️ **The real market price** of each listing, from the most similar listings across all countries, with a **0–100 deal score**.
- 🌍 **The price in each country**: median, cheapest listing, cheapest and most expensive country, and the price spread between them.
- 💱 **The resale margin**: what a listing would sell for in the most expensive country.
- 🔔 **New listings and price drops**: schedule it and get only what's new, on Telegram, Discord, Slack or a webhook.

| Country | Marketplace | Country | Marketplace |
|---|---|---|---|
| 🇩🇪 Germany | Kleinanzeigen | 🇵🇱 Poland | OLX |
| 🇦🇹 Austria | willhaben | 🇷🇴 Romania | OLX |
| 🇳🇱 Netherlands | Marktplaats | 🇧🇬 Bulgaria | OLX |
| 🇧🇪 Belgium | 2dehands / 2ememain | 🇨🇿 Czechia | Bazoš |
| 🇮🇹 Italy | Subito | 🇸🇰 Slovakia | Bazoš |
| 🇪🇸 Spain | Wallapop | 🇭🇺 Hungary | Jófogás |
| 🇫🇷 France | Vinted | 🇸🇪 Sweden | Blocket |
| 🇵🇹 Portugal | OLX | 🇩🇰 Denmark | DBA |
| 🇫🇮 Finland | Tori | 🇳🇴 Norway | FINN |

Optionally add **Vinted** in 15 more countries (`includeVinted: true`).

### ✨ Why this Actor

| | |
|---|---|
| 🌍 **One search, 18 countries** | Other scrapers cover one marketplace. Here, one input returns comparable data from 18 marketplace sites, in one dataset with the same fields everywhere. |
| 💶 **Everything in euros** | PLN, CZK, HUF, SEK, DKK, NOK and RON prices are converted with the European Central Bank reference rates of the day. Your min/max price filters are in euros too. |
| 🎯 **Clean comparisons** | Accessories sold alone (cases, chargers, games, controllers, spare parts), "wanted" ads and broken items are recognized in **16 languages** and kept out of the price statistics. "iPhone 13 Pro" doesn't pollute an "iphone 13" search, and "Switch Lite" doesn't pollute "switch oled". |
| 📊 **A market price per listing** | Each listing is compared with its most similar listings across Europe (same model, same storage, same edition), not with a global average. |
| 🚩 **Suspicious prices flagged** | A console at 40% of the market price is flagged `suspiciously_low` (scam, part or typo?) instead of being sold to you as the deal of the year. |
| 💸 **Fair price** | You pay per listing delivered. The market summary per search is free. |

### 🎯 Use cases

- **Resellers and flippers**: find what's cheap in one country and sells higher in another (`potentialMarginEur`, `bestResaleCountry`).
- **Deal hunters**: get alerted within minutes when a listing appears well below the market price anywhere in Europe.
- **Price research and pricing teams**: real second-hand prices per country for any product: consoles, phones, cameras, bikes, tools, designer items…
- **Refurbishers and buy-back services**: benchmark your buy and sell prices against the private market in each country.

### 🚀 Examples

**Where is a Nintendo Switch OLED cheapest?**

```json
{ "searchQueries": ["nintendo switch oled"], "maxItemsPerMarketplace": 50 }
```

**Deal alerts: new iPhones 13 under 350 € at least 20% below market, every 15 minutes (schedule the Actor):**

```json
{
  "searchQueries": ["iphone 13 128gb"],
  "countries": ["DE", "NL", "BE", "PL", "IT"],
  "sortBy": "newest",
  "maxPrice": 350,
  "minDealScore": 70,
  "monitorName": "iphone13-deals",
  "telegramBotToken": "123456:ABC…",
  "telegramChatId": "123456789"
}
```

### 📦 Output

Two kinds of items: one `listing` per listing, and one free `marketSummary` per search.

**A listing** (real data, 30 Sept 2026):

```json
{
  "type": "listing",
  "query": "nintendo switch oled",
  "marketplace": "OLX Poland",
  "country": "PL",
  "title": "Nintendo Switch Oled 64gb",
  "price": 650,
  "currency": "PLN",
  "priceEur": 148.9,
  "condition": "Używane",
  "conditionNormalized": "used",
  "location": "Warszawa, Mazowieckie",
  "postedAt": "2026-09-29T16:36:22.000Z",
  "sellerType": "private",
  "marketPriceEur": 240,
  "marketConfidence": "high",
  "comparablesCount": 8,
  "priceVsMarketPct": -38,
  "dealScore": 88,
  "countryMedianEur": 183.26,
  "europeMedianEur": 229.92,
  "bestResaleCountry": "DK",
  "bestResaleMedianEur": 275.37,
  "potentialMarginEur": 126.47,
  "priceAnomaly": null,
  "url": "https://www.olx.pl/d/oferta/…"
}
```

**The market summary** (same search, 720 listings in 18 countries):

```json
{
  "type": "marketSummary",
  "query": "nintendo switch oled",
  "europeMedianEur": 229.92,
  "comparedListings": 674,
  "cheapestCountry": "ES",
  "mostExpensiveCountry": "DK",
  "spreadPct": 53,
  "countries": [
    { "country": "ES", "medianEur": 180, "p25Eur": 170, "p75Eur": 200, "minEur": 140, "comparedListings": 39 },
    { "country": "FR", "medianEur": 180, "p25Eur": 170, "p75Eur": 200, "minEur": 120, "comparedListings": 39 },
    { "country": "PL", "medianEur": 183.26, "p25Eur": 171.81, "p75Eur": 217.63, "minEur": 114.54, "comparedListings": 35 },
    "…",
    { "country": "NO", "medianEur": 263.49, "p25Eur": 229.92, "p75Eur": 285.1, "minEur": 183.01, "comparedListings": 38 },
    { "country": "DK", "medianEur": 275.37, "p25Eur": 254.17, "p75Eur": 321.05, "minEur": 160.53, "comparedListings": 40 }
  ],
  "topDeals": [ { "title": "Nintendo Switch OLED Zelda Tears of the Kingdom konsol", "country": "SE", "priceEur": 106, "marketPriceEur": 250, "dealScore": 100, "url": "…" } ],
  "exchangeRates": { "source": "ECB", "date": "2026-09-29" }
}
```

The dataset has three ready-made views: **Listings**, **Deals & resale margin** (best deals first) and **Market summary per country**.

### 🧮 How the numbers are computed

- **Market price** (`marketPriceEur`): weighted median of the 8 to 10 most similar listings across all countries (title similarity that ignores common words in 14 languages, so a German and a Polish listing of the same model are compared). `marketConfidence` is `high` when those listings are close and consistent.
- **Deal score**: 50 = market price, 70 ≈ 20% below, 90 ≈ 40% below, 100 = far below.
- **Country medians** use only real offers with a price: no accessories sold alone, no broken items, no "wanted" ads, and no outliers (below 30% or above 300% of the European median). A country is marked `reliable` from 5 compared listings. The cheapest and most expensive countries need at least 3.
- **Resale margin** (`potentialMarginEur`) = median price in the most expensive country − this listing's price. It does **not** include shipping, marketplace fees or taxes: check them before buying to resell.

### 💰 Pricing

Pay per event:

| Event | Price |
|---|---|
| Run start | $0.003 |
| Listing delivered | $0.002 (**$2 per 1,000 listings**) |
| Market summary per search | free |

Apify subscribers pay less: −10% (Starter), −20% (Scale), −30% (Business).

Example: one search in all 18 countries with 50 listings per marketplace ≈ 850 listings ≈ **$1.70**. Set a **maximum cost per run** in the run options and the Actor stops cleanly when it's reached.

### ❓ FAQ

**Why is France only on Vinted?** Leboncoin blocks automated access, so France uses Vinted, which has a large second-hand electronics and games catalog.

**Vinted listings have no date or city?** Vinted doesn't show them in search results. Condition, brand, seller type and the price including the buyer protection fee are included.

**A marketplace was unavailable?** Marketplaces are sometimes slow or temporarily limit traffic. The run still succeeds with the others, and the market summary lists the status of each marketplace. Nothing is charged for what wasn't delivered.

**How does monitoring work?** Set a `monitorName` and schedule the Actor (for example every 15 minutes). The first run saves the current listings as a baseline and doesn't send alerts. Each next run returns only new listings and price drops, and sends up to `maxNotifications` alerts, best deals first.

**Is it legal?** The Actor only reads publicly available listings, at a moderate pace, and does not collect seller names or contact details. You are responsible for how you use the data under the terms of each marketplace and the GDPR.

### ⭐ Your feedback

If this Actor saves you time, a short review on Apify Store helps other users find it. Missing a field, a country or a filter? Say it in your review: the most requested features are added first.

### 🔗 More from EuroScrape

- [Vinted Scraper: 26 Countries, Deals, Alerts & Seller Data](https://apify.com/euroscrape/vinted-scraper): search Vinted across 26 countries, prices with buyer fees, seller ratings, cheapest-country comparison and instant alerts on new listings.
- [Google Hotels Scraper: Prices from Every Booking Site](https://apify.com/euroscrape/google-hotels-prices): hotel prices for any destination and dates, with the price on every booking site, rate parity, price calendars and alerts.
- [Kleinanzeigen Scraper: Deal Finder & Price-Drop Alerts](https://apify.com/euroscrape/kleinanzeigen-scraper): German classifieds with view counts, full seller details and instant alerts.
- [Website Tech Stack Detector: 280+ Technologies, Leads & Signals](https://apify.com/euroscrape/website-intelligence): 280+ technologies, company identity, contacts and sales signals for any website.
- [Impressum & Legal Notice Scraper (EU)](https://apify.com/euroscrape/company-identity): legal identity, registry numbers and VAT IDs from any website, registry-verified.
- [French Companies Scraper (SIRENE)](https://apify.com/euroscrape/france-companies): every French company by activity, area and size, with verified websites and emails.
- [UK Companies House Scraper](https://apify.com/euroscrape/uk-companies): UK companies by SIC code and location, with directors, websites and emails.
- [EU Public Tenders Scraper: TED, BOAMP & Awards](https://apify.com/euroscrape/eu-public-tenders): open tenders and contract awards from all of Europe (TED) and France (BOAMP, DECP), with winners per lot, values in € and daily alerts.
- [App Store Reviews Scraper + Google Play Reviews](https://apify.com/euroscrape/app-reviews): reviews from both stores in 58 countries, rating by version and country, alerts on new negative reviews.
- [Google Flights Scraper: Cheapest Dates, Prices & Price History](https://apify.com/euroscrape/google-flights-prices): flight prices for any route and dates, cheapest day to fly, typical price range, CO2 and price-drop alerts.
- [EU VAT Number Validator (VIES): Bulk Check, Proof & Alerts](https://apify.com/euroscrape/vat-validator): validate VAT numbers in bulk against the EU's official registry, with consultation proof for tax audits and alerts when a customer's number becomes invalid.
- [France Real Estate Sold Prices (DVF): €/m², Sales & Trends](https://apify.com/euroscrape/france-property-prices): every property sale registered by the French State — real prices, €/m², addresses, GPS, market trends per city and alerts on new sales.

# Actor input Schema

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

One or more products, e.g. "nintendo switch oled", "iphone 13 128gb", "dyson v11". Be specific: model names and numbers (13, 128gb, ps5) must appear in the listing title.

## `countries` (type: `array`):

Countries to search, each on its biggest second-hand marketplace. Leave empty for all 18.

## `includeVinted` (type: `boolean`):

Adds Vinted (clothes, electronics, games, home) next to each country's main marketplace. France always uses Vinted.

## `maxItemsPerMarketplace` (type: `integer`):

Per search and per marketplace. 50 is enough for reliable country prices; raise it to collect more deals.

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

'Newest first' is best for monitoring; 'Most relevant' gives the best price comparison.

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

In euros. Converted to the local currency of each marketplace (PLN, CZK, HUF, SEK, DKK, NOK, RON).

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

In euros, converted like the minimum price.

## `excludeKeywords` (type: `array`):

Listings whose title contains one of these words are skipped, e.g. "lite", "refurbished".

## `excludeAccessories` (type: `boolean`):

Removes cases, chargers, cables, games, controllers, spare parts… sold for the product (detected in 16 languages). Bundles like "console + case" are kept.

## `excludeDefective` (type: `boolean`):

Removes listings marked as defective or for parts (they are always excluded from price statistics).

## `maxAgeDays` (type: `integer`):

Optional. Listings without a date (Vinted) are kept.

## `minDealScore` (type: `integer`):

0–100. 50 = at market price, 70 = about 20% below, 90 = about 40% below the European market price of similar listings.

## `strictMatch` (type: `boolean`):

Keep only listings whose title matches your search (recommended: marketplaces also return loosely related items).

## `includeMarketSummary` (type: `boolean`):

One extra dataset item per search (free): median price per country in €, cheapest and most expensive country, price spread and top deals.

## `monitorName` (type: `string`):

Give your search a name and schedule the Actor: each run then returns only NEW listings and price drops since the previous run. The first run saves the current listings as a baseline.

## `alertOn` (type: `string`):

With a monitoring name.

## `telegramBotToken` (type: `string`):

Optional: get each listing on Telegram (create a bot with @BotFather).

## `telegramChatId` (type: `string`):

Your chat or group ID.

## `discordWebhookUrl` (type: `string`):

Optional.

## `slackWebhookUrl` (type: `string`):

Optional.

## `webhookUrl` (type: `string`):

Optional: one POST with all new listings as JSON (Make, Zapier, n8n…).

## `maxNotifications` (type: `integer`):

Best deals first.

## Actor input object example

```json
{
  "searchQueries": [
    "nintendo switch oled"
  ],
  "countries": [
    "DE",
    "FR",
    "IT",
    "ES",
    "NL",
    "PL"
  ],
  "includeVinted": false,
  "maxItemsPerMarketplace": 20,
  "sortBy": "relevance",
  "excludeAccessories": true,
  "excludeDefective": false,
  "strictMatch": true,
  "includeMarketSummary": true,
  "alertOn": "new_and_price_drops",
  "maxNotifications": 30
}
```

# Actor output Schema

## `overview` (type: `string`):

All listings with € prices and deal scores.

## `deals` (type: `string`):

Best deals first, with the resale margin in the most expensive country.

## `summary` (type: `string`):

Median price per country for each search.

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

Counters for this run (items found, output, errors).

# 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": [
        "nintendo switch oled"
    ],
    "countries": [
        "DE",
        "FR",
        "IT",
        "ES",
        "NL",
        "PL"
    ],
    "maxItemsPerMarketplace": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("euroscrape/eu-marketplace-deals").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": ["nintendo switch oled"],
    "countries": [
        "DE",
        "FR",
        "IT",
        "ES",
        "NL",
        "PL",
    ],
    "maxItemsPerMarketplace": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("euroscrape/eu-marketplace-deals").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": [
    "nintendo switch oled"
  ],
  "countries": [
    "DE",
    "FR",
    "IT",
    "ES",
    "NL",
    "PL"
  ],
  "maxItemsPerMarketplace": 20
}' |
apify call euroscrape/eu-marketplace-deals --silent --output-dataset

```

## MCP server setup

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

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/ISuZNrpzAegb4sYaf/builds/WSxGhKxNpWeHaOjBD/openapi.json
