如何用 Python 擷取 Vinted 刊登資料並比較各國價格
How to scrape Vinted listings and compare prices across countries with Python
這份教學示範如何用 Python 和 Apify 的 Vinted Scraper 擷取 Vinted 刊登資料,並比較德國與法國市場價格。測試以「levis 501」搜尋兩地各 25 個最新刊登,約 15 秒取得 50 個刊登;兩地總價中位數均為 26.95 EUR。
Vinted runs 26 separate marketplaces, and the same jacket can show up on vinted.de, vinted.fr and vinted.it at once. If you resell, track second-hand prices or build a deal alert, you want that data in a table instead of 40 open browser tabs.
This guide uses the Vinted Scraper on Apify. I ran it this morning with a small test: the query levis 501, 25 newest listings each from Germany and France, plus the country price comparison switched on. It finished in about 15 seconds and returned 50 listings and one comparison row. Every number below comes from that run.
What data you get
Each listing is one row. These are the fields I used most in the test run:
| Field | Example from the run | Notes |
|---|---|---|
title |
Jean Levi's 501 | as written by the seller |
price |
35 | item price in local currency |
buyerProtectionFee |
2.45 | Vinted's buyer fee |
totalPrice |
37.45 | what a buyer actually pays before shipping |
priceEur, totalPriceEur
|
35, 37.45 | converted to EUR for cross-country work |
brand, size, condition
|
Levi's, EU 38, Très bon état | condition comes in the marketplace language |
favouriteCount |
1 | a rough demand signal |
sellerIsBusiness |
false | private seller vs Vinted Pro |
country, marketplace
|
fr, vinted.fr | where the listing was found |
photoUrls |
list of image URLs | |
url, id
|
link to the listing | |
recordType |
item |
country-comparison for summary rows |
Turn on Listing details and you also get the full description, all photos, category path, colour, material, shipping price and sold/reserved status. Seller profiles adds seller country, rating, review count, items sold and followers. Both cost extra per record, so leave them off until you need them.
The comparison row is a separate record. For my query it held min, 25th percentile, median, average, 75th percentile and max price per country, the cheapest country and the link to the cheapest listing.
What the test run showed
A few things stood out in the 50 rows:
- Median total price (item plus buyer fee) was 26.95 EUR on both sites. The cheapest listing cost 8.05 EUR on both.
- 19 of the 25 listing IDs from vinted.de were also in the vinted.fr results. Vinted shows cross-border listings on EU sites, so "the German market" and "the French market" overlap a lot.
- 44 listings came from private sellers and 6 from business accounts.
- 41 of 50 had zero favourites. These were the newest listings, so that is expected.
- 42 titles contained "501". The other 8 were other Levi's models (504, unlabeled jeans), because Vinted search is fuzzy.
The overlap is the practical lesson. If you want to compare real local prices, use the Seller countries filter or turn on seller profiles, so the comparison is grouped by where the seller is located instead of which domain the listing appeared on. The README says the same, and my run confirmed it.
Option 1: no code
- Open the Vinted Scraper page and click Try for free. You need a free Apify account.
- The easiest input is a URL. Set your filters on any Vinted site in the browser (brand, size, price, condition), copy the address bar and paste it into Vinted URLs. Category, brand, single listing and seller wardrobe links work too.
- Or type keywords into Search queries, one per line, and pick the Countries. Each query runs in every selected country.
- Set Max listings per search. I used 25.
0means everything, and the actor splits the search into price ranges to get past Vinted's 960-result cap. - Optional: tick Compare prices between countries if you picked two or more countries.
- Click Start, then export the dataset as CSV, Excel or JSON.
Main input options
- Search queries and Vinted URLs: what to scrape. You can mix both.
- Countries or All 26 countries: which marketplaces to search.
-
Sort by:
newest_first(default),relevance,price_low_to_high,price_high_to_low. - Categories, Brands, Sizes, Condition, Colours, Material IDs, Min/Max price: the same filters as on the website. Names or IDs both work; sizes behave best together with a category.
-
Exclude words in title and Title must contain: cleans up fuzzy search. Excluded listings are free. In my run,
titleMustInclude: ["501"]would have dropped the 8 off-model rows. - Seller type, Seller countries, Min favourites: filter by private vs business, seller location and demand.
- Listing details and Seller profiles: paid enrichment, described above.
- Only new listings, Also return price drops, Also detect sold / removed listings, Monitor name: monitoring mode, covered below.
Option 2: Python with apify-client and pandas
Install the two packages:
pip install apify-client pandas
Put your Apify API token in an environment variable called APIFY_TOKEN (Console, Settings, API & Integrations). Then:
import os
from apify_client import ApifyClient
import pandas as pd
client = ApifyClient(os.environ["APIFY_TOKEN"])
run_input = {
"searchQueries": ["levis 501"],
"countries": ["de", "fr"],
"maxItemsPerSearch": 25,
"sortBy": "newest_first",
"compareCountries": True,
}
run = client.actor("liveclaude/vinted-scraper").call(run_input=run_input)
items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
listings = pd.DataFrame([i for i in items if i.get("recordType") == "item"])
comparison = [i for i in items if i.get("recordType") == "country-comparison"]
# price summary per marketplace
print(
listings.groupby("marketplace")["totalPriceEur"]
.describe()[["count", "min", "50%", "max"]]
)
# how many listings appear on both sites
de_ids = set(listings.loc[listings["country"] == "de", "id"])
fr_ids = set(listings.loc[listings["country"] == "fr", "id"])
print("Shared listings:", len(de_ids & fr_ids))
# ten cheapest listings
cols = ["marketplace", "title", "size", "condition", "totalPriceEur", "url"]
print(listings.sort_values("totalPriceEur")[cols].head(10))
for row in comparison:
for c in row["countries"]:
print(c["marketplace"], "median", c["medianPriceEur"], "EUR")
listings.to_csv("vinted_levis_501.csv", index=False)
With my input this printed a median of 26.95 EUR for both marketplaces and 19 shared listings. Your numbers will differ because Vinted listings change every minute.
Two small notes. The condition column is localized ("Sehr gut" on vinted.de, "Très bon état" on vinted.fr), so map it to one language before you group by it. And filter on recordType as shown, because the comparison row has a different shape from the listing rows.
Scheduling, monitoring and integrations
The part I would use day to day is monitoring. Switch on Only new listings, give the run a Monitor name, and create a schedule in Apify Console (every 15 minutes or every hour). Each run then returns only listings it has not seen before. Every record gets a listingStatus of new, price-drop, sold or removed. Price drops include the previous price and the drop percentage. Sold and removed items include first seen date, last seen date and days on market, which is useful sell-through data if you resell.
Already seen listings are not charged, so a monitor that finds 5 new items costs a fraction of a cent.
From there you can push results to Google Sheets, Slack, Make, Zapier, n8n or a webhook through the Integrations tab. The actor can also be called from AI agents through the Apify MCP server.
Pricing per 1,000 results
Pay per event, proxies included. Current prices from the actor page:
| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| Listing | $2.00 | $1.20 | $0.80 | $0.50 |
| Listing details (optional) | $2.00 | $1.50 | $1.00 | $0.80 |
| Seller profile (optional, once per seller) | $1.50 | $1.00 | $0.80 | $0.60 |
A country comparison row costs about $0.01 each. My test charged 50 listings plus 1 comparison row, which is roughly $0.11 on the Free plan. Listings removed by your title or seller filters are free, and you can set a maximum cost per run so it stops at your limit.
Responsible use
The actor reads public pages only. It does not log in and does not need cookies. Vinted listings belong to real people, most of them private sellers, so keep personal data out of your pipeline unless you have a clear legal basis under GDPR. For price research you rarely need anything beyond price, brand, size, condition and country. I left seller IDs and seller profiles out of the screenshots and the code above for that reason. Keep request volume sensible and read Vinted's terms before you build anything commercial on top of the data.
This tutorial was written with AI assistance and checked by the author. All numbers come from a real run of the scraper.
來源:DEV Community · dev.to

