# Vinted Scraper & New Listing Alerts - Prices, Brands, Sizes (`lukehunter/vinted-scraper`) Actor

Scrape Vinted search results: listing title, brand, size, condition, price (incl. buyer protection), favourites and image. Turn on new-listing alerts and run on a schedule to get only newly posted items matching your search. No login, no seller/member data collected.

- **URL**: https://apify.com/lukehunter/vinted-scraper.md
- **Developed by:** [Luke Hunter](https://apify.com/lukehunter) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 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?

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 & New Listing Alerts - Prices, Brands, Sizes

**For a vinted price tracker, reselling research, or bulk vinted listings data across any Vinted country.** Give it search terms (or your own Vinted catalog URLs) and it returns every item listing on the results page(s) - title, brand, size, condition, price (including buyer protection), favourites and image - read straight from Vinted's own public search pages. No login, no session, no seller data. Turn on **new-listing alerts** mode (`onlyNewSinceLastRun`) and run it on a schedule so resellers get new listings matching a saved search - brand, size, price range - the moment they appear.

Pay-per-result: **$0.001 per item — 1,000 items = $1.**

### Quick start (1 minute)

1. Open the **Input** tab and enter one or more search terms, e.g. `jacket`.
2. Pick the **Vinted country** to search (defaults to the UK).
3. Click **Start**. Export the resulting dataset to CSV/Excel/JSON, or pull it through the API shown below.

```json
{
  "searchTerms": ["jacket"],
  "country": "uk",
  "maxItems": 20
}
```

That prefilled example finishes in well under a minute and costs $0.04.

### How it works

Vinted's own catalog search page (`/catalog?search_text=...`) is server-rendered HTML - no login or session needed to view it, and no public JSON API exists for search (Vinted's `/api/v2/catalog/items` endpoint requires a signed-in browser session, so this Actor never uses it). This Actor:

1. Checks the target domain's `robots.txt` for the exact path it is about to read (`/catalog`), and skips that search (reporting why, in the run's status message) if it is disallowed.
2. Pages through the search results, stopping on the first page with zero items - the real end of the results.
3. Parses each listing card into one flat dataset row: title, brand, size, condition, price, price including buyer protection, favourites count and image.
4. Reads Vinted politely: about one request every 3 seconds, and honestly reporting - never disguising or evading - a block, a challenge page (e.g. a bot-check interstitial), or a search with genuinely no results.

### Use cases

- **Vinted price tracker**: run a search on a schedule and compare `price`/`totalPriceWithFees` over time for a brand, item type or your own listings' competitors.
- **Reselling research**: see what similar items are actually listed and sold for - brand, size, condition and price together - before pricing your own listing.
- **Vinted listings data**: export a whole search's results (title, brand, size, condition, price, favourites) for spreadsheet analysis.

### New-listing alerts: get only new items

Turn on `onlyNewSinceLastRun` and put this Actor on a **schedule** to get a genuine **Vinted new-listing alert**: every run after the first delivers (and charges for) only items it hasn't delivered before for that exact search. It's the same wedge as [Wellfound Jobs Scraper](https://apify.com/lukehunter/wellfound-jobs-scraper)'s job-alerts mode, applied to reselling.

1. Set your search as usual — a search term with `priceFrom`/`priceTo` (a brand or size can go in `searchTerms` too, e.g. `"nike jacket medium"`), or a pasted `startUrls` catalog link with brand/size/price filters already baked in — plus:

```json
{
  "searchTerms": ["nike jacket"],
  "country": "uk",
  "priceFrom": 10,
  "priceTo": 40,
  "onlyNewSinceLastRun": true,
  "maxItems": 100
}
```

2. Click **Schedule** on the run page (or create one under **Schedules** in the Apify Console) — every 30-60 minutes works well for a fast-moving search.
3. **The first scheduled run is a baseline**: it delivers every item currently listed (it's all new to you) and remembers it — you're charged normally for that run. Every run after that only delivers items it hasn't seen before for this exact search.
4. Add a **Webhook** under the schedule's **Integrations** for `ACTOR.RUN.SUCCEEDED`, pointing at Apify's own Slack/email integration (or a Zapier/Make webhook step) so you see new matching listings the moment a run finds them.

The run's status message tells you what happened: `"First run for 1 search: 40 item(s) delivered and remembered; next runs return only new ones."` on the baseline, then `"3 new item(s) since last run across 1 search (37 already seen)."` on later runs. A run that finds nothing new still **succeeds** with an empty dataset — that's the point of the mode, not a failure.

Each `searchTerms` entry and each `startUrls` entry is tracked as its **own, independent watch** (not one watch for the whole run), keyed on that search's own terms/country/price/sort (or its exact pasted URL) — so you can run several saved searches (different brands, sizes, price bands) in one Actor task without their seen-history mixing. `stateStoreName` only needs changing if you want to isolate or reset a watch's memory, or run several Actor tasks against the same account without them sharing state.

### Input

```json
{
  "searchTerms": ["jacket"],
  "startUrls": [],
  "country": "uk",
  "priceFrom": null,
  "priceTo": null,
  "sortBy": "relevance",
  "maxPagesPerSearch": 1,
  "maxItems": 60,
  "onlyNewSinceLastRun": false,
  "stateStoreName": "vinted-scraper-seen-items"
}
```

| Field | Type | Default | Description |
|---|---|---:|---|
| `searchTerms` | string\[] | *(none)* | Words to search for, e.g. `"jacket"`. Searched on the domain set by `country`. Up to 50 terms per run. |
| `startUrls` | string\[] | *(none)* | Full Vinted catalog URLs to scrape instead of (or alongside) search terms, e.g. `https://www.vinted.co.uk/catalog?search_text=jacket&price_to=20`. Any filters already in the URL are kept; only pagination is added. Must be a `vinted.*` URL. Up to 50 per run. At least one of `searchTerms` or `startUrls` is required. |
| `country` | string | `"uk"` | Which Vinted domain to search on for `searchTerms` (ignored for `startUrls`, which use their own domain). One of: `uk`, `fr`, `de`, `es`, `it`, `nl`, `be`, `pl`, `us`, `au`, `at`, `cz`, `dk`, `ee`, `fi`, `gr`, `hr`, `hu`, `ie`, `lt`, `lu`, `lv`, `pt`, `ro`, `se`, `si`, `sk`. |
| `priceFrom` | integer | *(none)* | Only include listings priced at or above this amount, in the country's own currency. |
| `priceTo` | integer | *(none)* | Only include listings priced at or below this amount. |
| `sortBy` | `"relevance"` | `"newest"` | `"price_low"` | `"price_high"` | `"relevance"` | How Vinted orders the results. |
| `maxPagesPerSearch` | integer | 1 | 1–20. How many result pages to fetch per search term/start URL. Vinted shows about 96 items per page. |
| `maxItems` | integer | 60 | 1–5,000. Hard cap on rows delivered across the whole run — your cost cap. |
| `onlyNewSinceLastRun` | boolean | `false` | New-listing alerts mode — see above. Delivers and charges only items not delivered by a previous run of the same search. |
| `stateStoreName` | string | `vinted-scraper-seen-items` | Name of the store that remembers what every alert-mode search has already delivered. Change it only to isolate several Actor tasks or reset a watch. |

### Output fields

| Category | Fields |
|---|---|
| Identity | `itemId`, `url` |
| Listing | `title`, `brand`, `size`, `condition` |
| Price | `price`, `currency`, `totalPriceWithFees` |
| Engagement | `favouritesCount` |
| Media | `imageUrl` |
| Search context | `country`, `searchTerm`, `page`, `position`, `scrapedAt` |

Missing values are returned as `null`. Nothing is invented.

### Output example

```json
{
  "itemId": "10156138130",
  "url": "https://www.vinted.co.uk/items/10156138130-fat-face-teddy-fleece-age-45",
  "title": "Fat face teddy fleece age 4/5",
  "brand": "FatFace",
  "size": "5 years / 110 cm",
  "condition": "Very good",
  "price": 4,
  "currency": "GBP",
  "totalPriceWithFees": 4.62,
  "favouritesCount": 0,
  "imageUrl": "https://images1.vinted.net/t/02_024e5_kxdcgDrGSSp2hJYWN1hXEwpV/310x430/28e5250f.webp?s=6b5663cff047d9d187bc4a4d2468793ff128e470",
  "country": "uk",
  "searchTerm": "jacket",
  "page": 1,
  "position": 1,
  "scrapedAt": "2026-09-27T00:00:00.000Z"
}
```

### Use it as an API

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("lukehunter/vinted-scraper").call(
    run_input={
        "searchTerms": ["jacket", "coat"],
        "country": "uk",
        "maxItems": 200,
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["price"], item["currency"])
```

### Pricing and cost control

Pay per delivered listing.

**$0.001 per item — 1,000 items = $1.**

| Rows delivered | Cost |
|---:|---:|
| 20 | $0.02 |
| 1,000 | $1.00 |
| 10,000 | $10.00 |

There is no charge for starting a run, and no charge for a search that is skipped, blocked, or produces no results. `maxItems` gives you a hard upper bound on cost.

### Limitations

- **No seller/member data, by design.** This Actor only ever collects listing (item) fields - title, brand, size, condition, price, favourites count, image. It never collects seller usernames, profile links, avatars or any other member data, and never fetches a `/member/` page (Vinted's own `robots.txt` disallows it, and this Actor would not fetch it even if it didn't).
- **Search results pages only.** This Actor reads Vinted's catalog search pages, not individual item detail pages - so it does not collect a listing's full description, all photos, or the seller's shipping/return terms.
- **No login, no session, no Vinted API.** Vinted's own JSON search API needs a signed-in browser session; this Actor never uses it and never logs in on your behalf.
- A minority of requests may be met with a bot-check/challenge page. When that happens, this Actor reports it honestly (per search, in the run's status message) and stops that search rather than attempting to evade it - you are not charged for a blocked search.
- Prices reflect the listing at scrape time; a seller can change or remove a listing at any moment.
- This is an independent tool, not affiliated with, endorsed by, or connected to Vinted. You are responsible for using the collected data in accordance with Vinted's terms and applicable law.

### FAQ

#### Does this collect seller information?

No, never. Only listing (item) fields - see "Limitations" above.

#### Can I filter by price?

Yes - set `priceFrom` and/or `priceTo` in the country's own currency.

#### Can I use my own Vinted search URL, with filters I've already set (brand, size, etc.)?

Yes - paste it into `startUrls`. Every filter already in the URL is kept; this Actor only adds pagination.

#### Why is `currency` sometimes different from what I expected?

`currency` is set from the `country` you searched (or, for a `startUrls` entry, the domain in that URL) - e.g. `uk` → GBP, `fr` → EUR. It is not read from the page itself.

#### How do I get alerted to new listings instead of the same items every time?

Set `onlyNewSinceLastRun: true` and put the Actor on a schedule — see "New-listing alerts" above. The first scheduled run delivers everything (and remembers it); later runs only deliver what's new. Each search term or start URL keeps its own history, so several saved searches (different brands, sizes, price bands) never mix up each other's alerts.

### Related Actors

Other data tools from the same developer, built to the same standard: official or public sources, hard cost caps, and honest documentation of limits.

- **[Walmart Category Scraper](https://apify.com/lukehunter/walmart-category-scraper)**: product names, prices, was-prices and ratings from Walmart category pages.
- **[Shopify Store Products Scraper](https://apify.com/lukehunter/shopify-store-products-scraper)**: full product catalogues from any Shopify store, with prices, sale prices, variants and stock.
- **[AliExpress Search Scraper](https://apify.com/lukehunter/aliexpress-scraper)**: AliExpress search results with prices, discounts, ratings and sold counts, by keyword.
- **[Google Play App Scraper](https://apify.com/lukehunter/google-play-scraper)**: ratings, installs, developer contact info and pricing for any Google Play app.
- **[Apple App Store Reviews Scraper](https://apify.com/lukehunter/app-store-reviews-scraper)**: Apple App Store reviews for any iOS app, across countries, with rating, version and date.
- **[Spotify Scraper](https://apify.com/lukehunter/spotify-scraper)**: play counts, monthly listeners and playlist track lists for any public Spotify artist, playlist, album or track.
- **[Hospital Price Transparency Enforcement Leads](https://apify.com/lukehunter/hospital-price-transparency-enforcement-leads)**: hospitals with recent CMS price transparency warning notices, CAP requests and CMP notices.
- **[Hospital Ownership Change Radar](https://apify.com/lukehunter/hospital-chow-radar)**: hospitals that just changed owner, with buyer, seller and effective date from CMS filings.

# Actor input Schema

## `searchTerms` (type: `array`):

Words to search for on Vinted, e.g. "jacket". Each term is searched on the domain set by "country" below. Maximum 50 terms per run.

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

Full Vinted catalog search URLs to scrape instead of (or alongside) search terms, e.g. "https://www.vinted.co.uk/catalog?search\_text=jacket\&price\_to=20". Any filters already in the URL (brand, size, price, etc.) are kept; only pagination is added. Must be a vinted.\* URL. Maximum 50 per run.

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

Which Vinted domain to search on for the "searchTerms" above (ignored for "startUrls", which use their own domain).

## `priceFrom` (type: `integer`):

Only include listings priced at or above this amount, in the country's own currency. Leave empty for no minimum.

## `priceTo` (type: `integer`):

Only include listings priced at or below this amount, in the country's own currency. Leave empty for no maximum.

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

Choose how Vinted orders each search result page before the Actor paginates it.

## `maxPagesPerSearch` (type: `integer`):

How many catalog pages to fetch for each search term or start URL, 1-20, default 1. Vinted shows about 96 items per page.

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

Hard cap on the number of rows delivered across all searches, 1-5000, default 60. You are charged $0.001 per delivered row, so this is your cost cap.

## `onlyNewSinceLastRun` (type: `boolean`):

Turn this on and run the Actor on a schedule to get only listings you haven't seen before: items already delivered on a previous run for the same search (search term/URL, country, price range, sort) are skipped and never charged again. The first run for a given search delivers everything (it's all new) and remembers it; later runs only deliver what's new since then. Each search term or start URL is tracked as its own watch. Off by default so a one-off run always gets the full current results.

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

Only used when "New-listing alerts" is on. Name of the key-value store that remembers which items each search has already delivered, so it persists across scheduled runs. Leave as the default unless you're running several Actor tasks whose alert history must not share this store. Letters, numbers and hyphens only.

## Actor input object example

```json
{
  "searchTerms": [
    "jacket"
  ],
  "startUrls": [],
  "country": "uk",
  "sortBy": "relevance",
  "maxPagesPerSearch": 1,
  "maxItems": 20,
  "onlyNewSinceLastRun": false,
  "stateStoreName": "vinted-scraper-seen-items"
}
```

# Actor output Schema

## `items` (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 = {
    "searchTerms": [
        "jacket"
    ],
    "startUrls": [],
    "country": "uk",
    "sortBy": "relevance",
    "maxPagesPerSearch": 1,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("lukehunter/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 = {
    "searchTerms": ["jacket"],
    "startUrls": [],
    "country": "uk",
    "sortBy": "relevance",
    "maxPagesPerSearch": 1,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("lukehunter/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 '{
  "searchTerms": [
    "jacket"
  ],
  "startUrls": [],
  "country": "uk",
  "sortBy": "relevance",
  "maxPagesPerSearch": 1,
  "maxItems": 20
}' |
apify call lukehunter/vinted-scraper --silent --output-dataset

```

## MCP server setup

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