# Vinted Scraper: Listings, Prices & Sold Items (`upright_inmate/vinted-scraper`) Actor

Scrape Vinted listings from 26 countries (vinted.ro, .fr, .de, .co.uk, .com...) by keyword or URL: prices, fees, brand, size, condition, photos, descriptions and seller ratings. No 960-result limit. Monitor new listings, price drops and sold items, and compare prices across countries.

- **URL**: https://apify.com/upright_inmate/vinted-scraper.md
- **Developed by:** [Ionut Radu](https://apify.com/upright_inmate) (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 $1.50 / 1,000 listings

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?

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

## Vinted Scraper: listings, prices & sold items

Scrape **Vinted** listings from **26 countries** (vinted.ro, vinted.fr, vinted.de, vinted.co.uk, vinted.com, vinted.it, vinted.es, vinted.pl, ...) by keyword or by any Vinted URL. Get prices with buyer fees, brand, size, condition, photos, descriptions and seller ratings, with **no 960-result limit**. Schedule it to get **new listings, price drops and sold items**, or **compare prices across countries** in EUR.

No Vinted account, cookies or coding needed. Export the results to JSON, CSV, Excel or Google Sheets, or connect them to Make, Zapier, n8n, Slack or your own app through the API.

### What can Vinted Scraper do?

- 🔎 **Search by keyword** in any Vinted country, with filters for price, condition, brand (by name), category, size, color and material.
- 🔗 **Scrape any Vinted URL**: a search page with your filters, a category or brand page, an item page, or a seller profile.
- ♾️ **Get every result, not just 960.** Vinted shows at most 960 results per search, so larger searches are automatically split into price ranges and merged without duplicates.
- 📄 **Item details** (optional): description, color, material, category, upload time, shipping price, all photos and availability.
- ⭐ **Seller profiles** (optional): rating, reviews, followers, active and sold listings, city, last login and verifications.
- 🔔 **Monitoring** for scheduled runs: flags new listings and price changes, and can save only new listings or price drops.
- 💸 **Sold-item detection**: finds listings that disappeared from your searches, checks their pages and reports them as sold or removed.
- 🌍 **Cross-country price comparison**: runs your keywords in up to 5 more countries and summarizes min, median, average and max prices in EUR.
- 🇷🇴 Romanian market first: vinted.ro is the default, and conditions are normalized to English codes (`very_good`, `new_with_tags`, ...) in every language.

### What data can you extract from Vinted?

| Listing | Item details (optional) | Seller profile (optional) | Monitoring |
|---|---|---|---|
| Title, URL, ID | Description | Username, profile URL | New listing (`isNew`) |
| Price, buyer protection fee, total price | Color, material | Rating (0-5), reviews | Previous price, price change (%) |
| Currency, discounted price | Category path and ID | Positive/neutral/negative reviews | Price dropped |
| Brand, size | Upload time | Followers, following | First seen |
| Condition (local + English code) | Shipping price | Active, sold and bought items | Sold / removed signals |
| Photos, favourites | Availability (active, reserved, sold) | City, country, last login | |
| Promoted flag, seller ID | Seller username, rating, badges | Holiday mode, verifications | |

### How to scrape Vinted

1. Click **Try for free** (or **Start**).
2. Enter one or more **search keywords** and pick the **country**, or paste **Vinted URLs** from your browser.
3. Optionally set filters, a limit, item details or seller profiles.
4. Click **Start** and download your data from the **Output** tab, or get it through the API.

To get alerts about new listings, price drops or sold items, see the [recipes](#recipes) below.

### Recipes

#### Search with filters

Search vinted.ro for new Nike Air Force 1 under 300 RON, newest first:

```json
{
    "searchQueries": ["nike air force 1"],
    "country": "ro",
    "sortBy": "newest_first",
    "maxPrice": 300,
    "conditions": ["new_with_tags", "new_without_tags"],
    "maxItemsPerSearch": 200
}
```

#### Scrape any Vinted URL

Paste a search with your filters, an item or a seller, from any country:

```json
{
    "startUrls": [
        { "url": "https://www.vinted.ro/catalog?search_text=zara&order=newest_first&price_to=50" },
        { "url": "https://www.vinted.fr/items/1234567890-robe-zara" },
        { "url": "https://www.vinted.de/member/12345678" }
    ],
    "includeItemDetails": true
}
```

#### New-listing alerts in Discord or Slack, every hour

1. Run this input once. The first run saves the current listings as the baseline:

   ```json
   {
       "searchQueries": ["levi's 501"],
       "country": "ro",
       "maxPrice": 150,
       "monitoringId": "levis-501-ro",
       "saveOnly": "new"
   }
   ```

2. Save it as a task and **schedule** it every hour. Each later run scans only the newest search pages and saves only listings created since the previous run.

3. In the task's **Integrations** tab, add the **Slack** integration, or a webhook on **Run succeeded** that posts to a [Discord channel webhook URL](https://support.discord.com/hc/en-us/articles/228383668) with this payload template:

   ```json
   { "content": "New Vinted listings: https://console.apify.com/view/runs/{{resource.id}}" }
   ```

Cost: $0.02 per run plus $0.0015 per new listing.

#### See what sells: daily sold-listing detection

Scan a specific search once a day; listings that disappear are checked on their page and saved as `soldSignal` results, with their last price:

```json
{
    "searchQueries": ["nike dunk low"],
    "country": "ro",
    "conditions": ["very_good", "new_without_tags"],
    "maxItemsPerSearch": 0,
    "monitoringId": "dunk-low-sold",
    "saveOnly": "new",
    "trackSoldItems": true
}
```

Sold detection scans the whole search on every run ($0.008 per search page), so keep the search narrow and run it daily rather than hourly.

#### Find the cheapest country for an item

Run the same keyword in up to 5 more countries. The **Country comparison** view shows the median price per country in EUR, the cheapest and most expensive country, and the spread between them:

```json
{
    "searchQueries": ["nike air force 1"],
    "country": "ro",
    "compareCountries": ["fr", "de", "pl", "it"],
    "maxItemsPerSearch": 300
}
```

#### Watch a seller's shop

Get a seller's profile and all their active listings. With a monitor, later runs save only their new listings, and listings that disappear are checked and reported as sold or removed:

```json
{
    "startUrls": [{ "url": "https://www.vinted.ro/member/12345678" }],
    "maxItemsPerSearch": 0,
    "monitoringId": "seller-12345678",
    "saveOnly": "new",
    "trackSoldItems": true
}
```

#### Use it from an AI assistant

Connect Claude, Cursor or any MCP client to the [Apify MCP server](https://mcp.apify.com/) with only this Actor as a tool:

```json
{
    "mcpServers": {
        "vinted": { "url": "https://mcp.apify.com?tools=upright_inmate/vinted-scraper" }
    }
}
```

Every result can also go to Google Sheets, Make, Zapier or n8n through the **Integrations** tab, or be downloaded as JSON, CSV or Excel.

### Output example

Each listing is one row in the dataset. The **Listings** view of the Output tab, from a search in 6 countries:

![Listings view in Apify Console: photo, title, price, total price with buyer protection, currency, brand, size, condition, favourites, link, country and keyword of each Vinted listing](https://raw.githubusercontent.com/raduionut90/vinted-scraper-assets/main/images/output-listings.png)

With **Include item details**, the **Item details** view adds the description, category path, color, material, upload time, availability and shipping price:

![Item details view in Apify Console: description, category, color, material, upload time, availability and shipping price of Vinted listings](https://raw.githubusercontent.com/raduionut90/vinted-scraper-assets/main/images/output-item-details.png)

With **Compare with countries**, the **Country comparison** view shows the cheapest and most expensive country and the spread of median prices in EUR; the `countries` field holds the count, min, median, average and max price for each country:

![Country comparison view in Apify Console: Nike Air Force 1 is cheapest in Italy and most expensive in Romania, with a 16.6 EUR (66%) spread of median prices](https://raw.githubusercontent.com/raduionut90/vinted-scraper-assets/main/images/output-country-comparison.png)

A listing in JSON, with item details and a seller profile:

```json
{
    "type": "listing",
    "id": 10145529051,
    "url": "https://www.vinted.ro/items/10145529051-nike-air-force-1",
    "title": "Nike Air force 1",
    "brand": "Nike",
    "size": "43",
    "condition": "Foarte bună",
    "conditionCode": "very_good",
    "price": 170.0,
    "currency": "RON",
    "serviceFee": 12.0,
    "totalPrice": 182.0,
    "favouriteCount": 9,
    "photos": ["https://images1.vinted.net/t/.../f800/bcc09a4d.webp"],
    "description": "Purtați ocazional...",
    "color": "Alb",
    "material": "Piele",
    "category": "Bărbați > Pantofi > Pantofi sport",
    "uploadedAgo": "acum 3 săptămâni",
    "availability": "active",
    "seller": {
        "id": 313360399,
        "login": "seller_login",
        "rating": 3.4,
        "feedbackCount": 5,
        "followersCount": 0,
        "itemCount": 23,
        "city": "Baia Mare",
        "profileUrl": "https://www.vinted.ro/member/313360399"
    },
    "country": "ro",
    "searchQuery": "nike air force 1",
    "scrapedAt": "2026-10-19T08:10:17+00:00"
}
```

Other result types in the same dataset (the `type` field):

- `seller`: the profile of a seller whose URL you entered.
- `soldSignal`: a monitored listing that was sold (`soldStatus: "sold"`) or removed (`"likely_sold"`), with its last price and when it was first and last seen.
- `countryPriceSummary`: for each keyword, the count, min, median, average and max price per country, in local currency and EUR, with the cheapest and most expensive country.

The Output tab has ready-made views: **Listings**, **Item details**, **New listings & price changes**, **Sellers**, **Sold listings** and **Country comparison**. The **Run summary** record shows how many listings each search found, how it was split into price ranges, and any failed pages.

### How much does it cost to scrape Vinted?

This Actor uses **pay-per-event** pricing: you pay only for results, and platform usage and proxies are included.

| Event | Price |
|---|---|
| Listing | $1.50 per 1,000 |
| Listing with item details (instead of Listing) | $4.50 per 1,000 |
| Seller profile (each seller once per run) | $3.00 per 1,000 |
| Monitored search (per search, per run) | $0.02 |
| Scanned search page (price-drop and sold monitoring that saves only some listings) | $0.008 |
| Country price comparison (per keyword) | $0.05 |

Examples:

- 1,000 listings from a search: **$1.50**
- 1,000 listings with item details and seller profiles (all different sellers): **$7.50**
- An hourly monitor of one search that saves 10 new listings per run: **$0.035 per run**, about $0.84 per day
- A daily price-drop monitor of a search with 40 result pages that saves 5 price drops: **$0.35 per run**
- One keyword in 3 countries, 100 listings each, with a comparison: **$0.50**

Set **Max results in total** or a maximum cost per run to keep every run within budget. On the free Apify plan, runs save up to 100 results.

### Tips

- **Getting all results:** set **Max listings per search** to `0`. Searches with more than 960 results are split into price ranges automatically; see the Run summary for the ranges used.
- **Monitoring and complete scrapes use the "newest first" order.** Vinted's relevance order changes between page loads, which would make listings appear and disappear at random.
- **New-listing alerts are incremental:** with **Save only: Only new listings** (and no sold detection), runs after the first stop at the first search page without new listings, usually after 1–2 pages.
- **Price drops and sold detection scan the whole search** on every run, because any listing can change. Keep these searches specific (keyword + filters) and schedule them less often; each scanned page is charged when not all listings are saved.
- **Sold-item detection** needs complete searches: use `maxItemsPerSearch: 0`. A listing is checked after it is missing for **Missing runs before checking** runs (default 2).
- **Filters not in the form?** Set them on the Vinted website and paste the URL. Every filter in the URL is kept.
- **Brands** can be names: "Nike" is matched to Vinted's brand ID automatically.

### FAQ

**Is it legal to scrape Vinted?**
This Actor collects only publicly visible listing and profile data, the same as any visitor sees, and doesn't log in. It never collects private data such as e-mails, phone numbers, real names or addresses. Seller usernames and locations are personal data under GDPR, so only collect them when you have a legitimate reason, and follow Vinted's terms. Vinted's robots.txt does not allow using its content to train AI models. If you're unsure, consult a lawyer.

**Do I need a proxy?**
The Actor uses Apify residential proxies by default, which are included in the price. Vinted limits how many pages one IP address can load, so blocked pages are retried automatically with a new IP. Datacenter proxies also work, but Vinted blocks them much more often, so runs take several times longer.

**Why do some listings show prices like 398.59 when I set a 400 minimum?**
Listings from sellers in other countries are shown converted to your local currency, so their converted price can be slightly outside your price filter.

**Why are view counts not included?**
Vinted no longer shows listing view counts publicly.

**Can it buy items or message sellers?**
No. The Actor only reads public data.

**Something doesn't work?**
Open an issue in the **Issues** tab with your run link. Feedback and feature requests are welcome.

# Changelog

This Actor's version history is a separate document: https://apify.com/upright_inmate/vinted-scraper/changelog.md

# Actor input Schema

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

What to search for, exactly as you would type it on Vinted, e.g. "nike air force 1" or "rochie zara". Each keyword is a separate search in the selected country. The filters below apply to these keywords.

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

Any Vinted URL from any country: a search or catalog page with your filters already applied (e.g. https://www.vinted.ro/catalog?search_text=zara\&order=newest_first), an item page (/items/...) for full item details, a brand page (/brand/...) or a seller profile (/member/...) to get the seller's profile and all their active listings. Filters in the URL are kept; the filter fields below do not apply to URLs.

## `country` (type: `string`):

The Vinted website to search the keywords on. Prices and price filters are in this country's currency. URLs always use the website they point to.

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

Order of the results. Choose "Newest first" for deal alerts. Monitoring runs and runs that scrape all listings (Max listings per search 0 or above 960) always use "Newest first", because Vinted's relevance order changes between page loads and would make listings appear and disappear at random.

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

Only listings priced at least this much, in the selected country's currency (e.g. RON for Romania). Leave empty for no minimum.

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

Only listings priced at most this much, in the selected country's currency. Leave empty for no maximum.

## `conditions` (type: `array`):

Only listings in these conditions. Leave empty for all conditions.

## `brands` (type: `array`):

Only listings of these brands. Use brand names (e.g. "Nike", "Zara") or Vinted brand IDs (e.g. 53). Names are matched to Vinted's brand list automatically.

## `categoryIds` (type: `array`):

Vinted category (catalog) IDs, e.g. 1242 for men's trainers. Find the ID in the URL of a Vinted category page (/catalog/1242-trainers). Easier: open the category on Vinted and paste the URL into Vinted URLs.

## `sizeIds` (type: `array`):

Vinted size IDs (the size_ids\[] values in a Vinted URL after you pick sizes on the website).

## `colorIds` (type: `array`):

Vinted color IDs (the color_ids\[] values in a Vinted URL after you pick colors on the website).

## `materialIds` (type: `array`):

Vinted material IDs (the material_ids\[] values in a Vinted URL after you pick materials on the website).

## `maxItemsPerSearch` (type: `integer`):

Maximum listings to scrape for each keyword, URL and seller. Set 0 for all listings. Vinted shows at most 960 results per search; above that the search is automatically split into price ranges, so you can get all listings.

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

Stop after saving this many results in total, across all searches. Useful to cap the cost of a run. Set 0 for no limit. On the free Apify plan, runs save at most 100 results.

## `includeItemDetails` (type: `boolean`):

Open each listing's page to add the description, color, material, category, upload time, shipping price, all photos, availability and the seller's login and rating. Slower, and charged as a detailed listing.

## `includeSellerDetails` (type: `boolean`):

Add each seller's public profile: rating, number of reviews (positive/neutral/negative), followers, active and sold listing counts, city, country, last login, holiday mode and verifications. Each seller is charged once per run.

## `monitoringId` (type: `string`):

Any name for this monitor, e.g. "nike-deals". Runs with the same ID and the same searches compare their results with the previous runs, and each listing gets isNew, firstSeenAt, previousPrice, priceChange and priceDropped fields. Leave empty to turn monitoring off.

## `saveOnly` (type: `string`):

Which listings to save in monitored runs. "Only new listings" scans just the newest search pages until a page has no new listing, so frequent runs stay cheap. Price drops and sold detection compare every listing, so they scan the whole search and each scanned page is charged. The first run of a monitor always saves everything as the baseline. Requires a Monitoring ID.

## `trackSoldItems` (type: `boolean`):

Detect listings that disappeared from your searches since earlier runs and check their pages: each sold or removed listing is saved as a soldSignal result. Needs a complete scan of each search, so set Max listings per search to 0 for large searches; when not all listings are saved, every scanned search page and checked listing page is charged. Requires a Monitoring ID.

## `missingRunsThreshold` (type: `integer`):

How many consecutive runs a listing must be missing from its search before its page is checked for a sale. 1 reports fastest; 2 avoids extra checks for listings that drop out of results only briefly.

## `compareCountries` (type: `array`):

Also run every search keyword in these countries (up to 5) and add one countryPriceSummary result per keyword with min, median, average and max prices per country, converted to EUR, plus the cheapest and most expensive country. Price filters are converted to each country's currency.

## `proxyConfiguration` (type: `object`):

Vinted limits how many pages one IP address can load, so the Actor uses Apify Proxy by default. Residential proxies are the most reliable.

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

Maximum pages loaded in parallel. Lower it if many requests fail.

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

How many times a failed page is retried before it is skipped (blocked requests are retried with a new IP on top of this).

## Actor input object example

```json
{
  "searchQueries": [
    "nike air force 1"
  ],
  "country": "ro",
  "sortBy": "relevance",
  "maxItemsPerSearch": 100,
  "maxItems": 0,
  "includeItemDetails": false,
  "includeSellerDetails": false,
  "saveOnly": "all",
  "trackSoldItems": false,
  "missingRunsThreshold": 2,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "maxConcurrency": 10,
  "maxRequestRetries": 5
}
```

# Actor output Schema

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

All results: listings, seller profiles, sold signals and country comparisons.

## `details` (type: `string`):

No description

## `monitoring` (type: `string`):

No description

## `sellers` (type: `string`):

No description

## `soldSignals` (type: `string`):

No description

## `countryComparison` (type: `string`):

No description

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

Counts per search: listings scanned, price ranges used to get past the 960-result limit, failed requests.

# 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": [
        "nike air force 1"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("upright_inmate/vinted-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 = {
    "searchQueries": ["nike air force 1"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("upright_inmate/vinted-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 '{
  "searchQueries": [
    "nike air force 1"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call upright_inmate/vinted-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,upright_inmate/vinted-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/HsRdgaAr3GWLVo0Fh/builds/AeC5bDgGEh2krY47C/openapi.json
