Wine-Searcher Scraper - Wine Prices, Scores, Offers & LWIN
Pricing
from $1.70 / 1,000 wine results
Wine-Searcher Scraper - Wine Prices, Scores, Offers & LWIN
Look up wines on wine-searcher.com by name, URL, or LWIN code. Returns 30+ fields, including critic scores, prices, grape, region, appellation, producer, label image, user ratings, food pairing, live offer counts, cheapest merchant offer, and optional critic review breakdown.
Pricing
from $1.70 / 1,000 wine results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
2
Bookmarked
45
Total users
10
Monthly active users
4.4 hours
Issues response
8 hours ago
Last modified
Categories
Share
Wine-Searcher Scraper: Scores, Prices & Popularity
Wine-Searcher Scraper turns Wine-Searcher into a clean data feed. Give it a list of wine names, Wine-Searcher links, or LWIN codes (or mix all three with auto-detect) and it returns critic scores, average and market prices, grape, region, appellation, producer, label image, and merchant offer counts as structured JSON, CSV, or Excel, or straight into your app through the API.
Why This Scraper?
- Three input styles, one list. Wine names, Wine-Searcher URLs, or LWIN codes (LWIN7 / 11 / 16 / 18). Auto-detect routes each item automatically, so a mixed list just works.
- A rich per-wine record. 30+ fields, including critic score, average price, grape, region, appellation, producer, description, and label image.
- Optional merchant offers. Turn on offer extraction for the cheapest live offer, merchant name and link, the full worldwide offers list, and the number of offers and merchants.
- Optional critic review breakdown. Turn on review collection for a per-critic reviewer name, score, and tasting note for each wine.
- Price-spread stats already computed. With merchant offers turned on, highest and median price are normalised to one standard 750ml bottle, so a case offer or a magnum never skews the comparison for you.
- Currency follows your market. The proxy country you choose sets the price-currency context, so results match the market you care about.
- Fails loudly, not silently. When Wine-Searcher cannot be reached at all, the run stops with a clear message instead of quietly returning an empty dataset.
Use Cases
- Wine merchants and retailers: benchmark your prices against average and cheapest market prices for the same vintage.
- Sommeliers and collectors: look up critic scores, tasting notes, and provenance details before buying or listing a bottle.
- Cellar and portfolio valuation: resolve a list of LWIN codes to current average and market prices for a valuation report.
- Market analysts: track price spread across regions and currencies for a set of wines over time.
- Auction houses and wine funds: verify critic scores and merchant offer counts before quoting a lot.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
wineName | "2015 Sample Wine, Pomerol, France" |
vintage | 2015 |
appellation | "Pomerol, France" |
region / grapeVariety | "Pomerol" / "Merlot" |
style / beverageType | "Red - Savoury and Classic" / "Wine" |
producer | "Sample Producer" |
description | "Short producer or wine description text." |
score / scoreBestRating / criticReviewsCount | 97 / 100 / 20 |
criticReviews | per-critic name, score, and tasting note (when review collection is on) |
avgPrice / avgPriceCurrency | 5076 / "EUR" |
cheapestPriceAmount / cheapestPriceCurrency | 3400.00 / "EUR" |
cheapestPriceMerchant | "Sample Merchant" |
status | "ok" (only found wines are pushed and billed; failed or not-found lookups are reported in the log, never pushed) |
inputValue / inputType | the name, URL or LWIN you gave, and how it was read |
criticScores | scores only as {critic name: score}, always included; tasting notes need review collection |
cheapestPriceEur / cheapestPriceConverted / targetCurrency | cheapest offer in euros and in your chosen display currency (ECB daily rates; display only, empty when offers are off or the currency has no rate) |
offersPages | 1 when offers were fetched (every offer is read from one page) |
offers | full merchant offers list (when offer extraction is on) |
offersCount / merchantCount | 13 / 11 |
highestPriceAmount / medianPriceAmount | 4500.00 / 3800.00, per standard 750ml bottle |
labelImageUrl | Wine-Searcher label image link |
wineSearcherUrl / searchLocation | Wine-Searcher link for the wine / "France" |
producer and wineryName carry the same value; appellation and origin carry the same value. Both pairs are kept for compatibility with either field name. Output tabs: Overview (one row per wine), Offers (one row per merchant offer), Critic reviews (one row per review), and Changes (incremental status, changed fields, first and last seen). Offers and reviews also stay nested on each wine row. When a run ends, a Run summary record (key OUTPUT in the key-value store) lists how many wines were requested, found, missed and pushed, per input type.
The full offers array (every merchant, price, and link) and the complete criticReviews breakdown are always kept in the Apify dataset.
Not exposed by Wine-Searcher in the page data this actor reads, so they are not returned: wine popularity and popularity rank, a winery page URL. Failed lookups produce no row, so there is no error field on rows.
How to Use
- Pick an input type: auto-detect (recommended for mixed lists), wine names, Wine-Searcher URLs, or LWIN codes.
- Paste your list into the matching field.
- Turn on Fetch merchant offers and/or Fetch critic reviews if you want that extra depth, and set Max wines to control run size and cost.
- Click Start, then download the dataset as JSON, CSV, or Excel, or read it through the API.
Look up by wine name (auto-detected):
{"inputType": "auto","wineNames": ["Petrus 2015", "Dom Perignon 2013"],"maxItems": 20}
Look up by Wine-Searcher URL, with offers and reviews:
{"inputType": "urls","urls": ["https://www.wine-searcher.com/find/sassicaia/2019"],"fetchOffers": true,"fetchReviews": true}
Pin a different currency market (United Kingdom / GBP):
{"inputType": "auto","wineNames": ["Sassicaia 2019"],"proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"], "apifyProxyCountry": "GB" }}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/wine-searcher-scraper").call(run_input={"inputType": "wineNames", "wineNames": ["Petrus 2015"]})for wine in client.dataset(run["defaultDatasetId"]).iterate_items():print(wine["wineName"], wine["score"], wine["avgPrice"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/wine-searcher-scraper').call({ inputType: 'wineNames', wineNames: ['Petrus 2015'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets, or webhooks from the Integrations tab.
Resume & recurring updates
Resume from a previous run (resumeFromRunId) is a one-off delta: give it a previous run or dataset ID and this run skips wines already collected there, looking up only the rest of your list. Useful for finishing a large list across several runs without re-paying for wines you already have.
Incremental mode (incrementalMode) is for a wine list you run on a schedule (daily/weekly) to track changes over time - critic score moved, price shifted, a merchant added or dropped an offer. Every wine is classified:
changeType | Meaning |
|---|---|
NEW | Never seen under this State key before. |
UPDATED | Something changed since last time - changedFields names which top-level fields. |
UNCHANGED | Identical to last time. Suppressed (not pushed, not billed) unless emitUnchanged is on. |
REAPPEARED | Was EXPIRED, now found again. |
EXPIRED | Tracked before, not found this run. Only reported when emitExpired is on AND this run completed a full scan of your list (no Resume, no cap, no connection ceiling cut it short, no lookup blocked). |
State is kept in a separate key-value store, keyed by stateKey (or an auto-derived hash of your exact wine list when left empty) - it never re-visits wine-searcher.com, so checking state costs no extra proxy spend. What is compared: every output field, including critic score, prices and currency, each offer's merchant, price and unit, each critic review's author, score and note, region, appellation, description and the label image path. What is never compared (still written to every row): scrapedAt, the rate-driven cheapestPriceEur, cheapestPriceConverted and targetCurrency, each offer's priceValidUntil, the order of offers and criticReviews, and the host and query part of labelImageUrl (rotating image servers). Add your own exclusions with Ignore fields when detecting changes (incremental mode only) (ignoreFieldsForChanges): a field name such as description, or a dotted path into a list such as offers.merchantUrl. Ignored fields never turn a wine into UPDATED and never appear in changedFields. Adding fields to your ignore list does not mark already-tracked wines as changed.
⚠️ The auto-derived key is built from your wine list itself, so editing the list (adding or removing a wine) also changes the auto key and starts a fresh baseline - convenient if you always re-run the identical list, but it means emitExpired can never report a wine you removed as EXPIRED under the auto key. If you intend to grow/shrink your tracked list over time and still want removed wines reported, set your own fixed stateKey so every run shares one baseline regardless of list edits.
Track changes on a recurring list:
{"inputType": "auto","wineNames": ["Petrus 2015", "Opus One 2019"],"incrementalMode": true,"emitExpired": true}
Long runs (large lists) also survive a platform migration or a manual Resurrect automatically: progress is checkpointed periodically, so a resumed attempt of the same run does not re-look-up (or re-charge for) wines it already extracted.
Send results into your apps (MCP connectors)
Optionally pipe every result into the tools you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape; the Apify dataset is never changed.
- Authorize a connector once under Apify, Settings, API & Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. For Notion, also set
notionParentPageUrlto the page under which item pages should be created. - Run the actor. Results are written to the connector after the dataset is saved.
Each wine becomes one entry with a title and its key fields flattened to plain text; Notion gets one page per wine, other connectors get a best-effort write or digest depending on what that connector supports. The complete record always stays in the Apify dataset. Leaving the field empty skips this entirely.
URL mode
With Input type set to Wine-Searcher URLs and the URLs field left untouched, the actor now scrapes one example of each supported link shape (two wines) instead of nothing. Clear the field and paste your own links to scrape those instead. If you supply wine names or LWIN codes and leave the URLs field untouched, the example links are ignored.
| Link shape | Example |
|---|---|
| Wine page (name and vintage) | https://www.wine-searcher.com/find/petrus/2015 |
| LWIN page | https://www.wine-searcher.com/find/lwin11316442021 |
Any other Wine-Searcher link (search, merchant, region, producer pages) or a non-Wine-Searcher link is skipped with a clear warning in the log naming the link; paste a wine name or LWIN code instead. A wine name or link with no matching page is listed in the log as not found.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
inputType | string | auto | auto, wineNames, urls, or lwins. Auto-detect routes each item by its shape. |
wineNames | array | (none) | Full wine names, ideally with vintage year. Up to 1000 items. |
urls | array | one example of each supported shape | Direct Wine-Searcher find links (see the table below). Up to 1000 items. |
lwins | array | (none) | LWIN codes (LWIN7 / 11 / 16 / 18), numeric or string. Up to 1000 items. |
fetchOffers | boolean | false | Also extract the cheapest merchant offer, the full offers list, merchant count, and the per-bottle highest and median prices. |
fetchReviews | boolean | false | Also collect the per-critic review breakdown (reviewer name and score) for each wine. |
targetCurrency | string | USD | Only with Fetch merchant offers: also report the cheapest offer in this currency (cheapestPriceConverted, ECB daily rates; display only, never a filter). |
maxReviewsPerWine | integer | 20 | Only with Fetch critic reviews: keep at most this many critic reviews per wine. |
resumeFromRunId | string | (none) | Run or dataset ID of a previous run: wines already collected there are skipped. |
incrementalMode | boolean | false | Track a recurring list and classify each wine as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. |
stateKey | string | (auto) | Incremental mode: name of the saved baseline. Empty derives it from your wine list. |
emitUnchanged | boolean | false | Incremental mode: also push (and bill) unchanged wines. |
emitExpired | boolean | false | Incremental mode: report wines tracked before but not found this run. |
ignoreFieldsForChanges | array | (none) | Incremental mode only: extra fields (or dotted paths such as offers.merchantUrl) left out when deciding whether a wine changed. |
concurrency | integer | 3 | Deprecated and ignored. Lookup parallelism is managed automatically. |
maxItems | integer | 20 | Process at most this many wines from your list. 0 means no limit. |
proxy | object | Residential, France | Residential is the default and prices in your chosen country's currency (France / EUR by default). A datacenter proxy also works but exits in the US only, so prices come back in that market's currency. The actor retries on fresh connections and, if the default connection is unavailable, on a backup connection. |
mcpConnectors | array | (none) | Optional connectors to send a summary of each result to, once authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which item pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"inputValue": "Petrus 2015","inputType": "wineNames","wineSearcherUrl": "https://www.wine-searcher.com/find/sample/2015","wineName": "2015 Sample Wine, Pomerol, France","vintage": 2015,"appellation": "Pomerol, France","region": "Pomerol","origin": "Pomerol, France","grapeVariety": "Merlot","producer": "Sample Producer","beverageType": "Wine","style": "Red - Savoury and Classic","description": "Short producer or wine description text.","labelImageUrl": "https://www.wine-searcher.com/images/labels/00/00/000000000.jpg","score": 97,"scoreBestRating": 100,"criticReviewsCount": 20,"criticReviews": [{ "author": "Sample Critic", "score": 95, "bestRating": 100, "tastingNote": "Tasted January 2018." }],"avgPrice": 5076,"avgPriceCurrency": "EUR","cheapestPriceAmount": 3400.0,"cheapestPriceCurrency": "EUR","cheapestPriceMerchant": "Sample Merchant","cheapestPriceMerchantUrl": "https://www.wine-searcher.com/out/0000","bottlesPerUnit": 1,"offers": [{ "price": 3400.0, "priceCurrency": "EUR", "merchant": "Sample Merchant", "merchantUrl": "https://www.wine-searcher.com/out/0000", "unitDescription": "Bottle (750ml)", "bottlesPerUnit": 1, "availability": "InStock", "itemCondition": "NewCondition", "priceValidUntil": "2026-12-31" }],"offersCount": 13,"highestPriceAmount": 4500.0,"highestPriceCurrency": "EUR","medianPriceAmount": 3800.0,"merchantCount": 11,"wineryName": "Sample Producer","searchLocation": "France","scrapedAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
Wine-Searcher shows a bot-protection page ("Access to this page has been denied") to a new connection; the actor handles that check automatically before reading each wine, and clearance is intermittent per connection, so an occasional slow or refused lookup is normal and is retried on a fresh connection.
- Residential (default). The default proxy is Apify Residential pinned to France, which sets the price currency to EUR. Residential proxy access needs a paid Apify plan; the Free plan does not include it. Change the proxy country to price a different regional currency.
- Datacenter. If you choose a datacenter proxy group the actor uses it, and it works for reading wine pages, but datacenter exits are in the US only, so prices follow that market's currency instead of the French default. A datacenter run never falls back to a residential proxy you did not select.
- Your own proxy URLs. Custom proxy URLs are used as given, with no backup connection.
Messages you may see in the log or run status:
- Backup connection in use: "Served over the backup connection (the default connection was unavailable)."
- Residential unavailable on your plan (warning): "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs."
- Run failed, connection refused: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required: https://apify.com/pricing. If you entered your own proxy URLs, check that their credentials are valid."
- Run failed, residential unavailable and the backup could not load pages: "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Wine-Searcher pages. Upgrade at https://apify.com/pricing or supply your own proxy URLs, then try again."
FAQ
How much does it cost?
You pay per wine returned. Turning on Fetch merchant offers or Fetch critic reviews adds a small extra charge for the additional data pulled per wine, billed per enriched wine and per review captured; leaving both off keeps a run to the base per-record price. The Pricing tab shows the current rates. The extra charge is the detail-enrichment event: one unit per wine row delivered with offers on, plus one unit per critic review delivered (capped by Max reviews per wine, default 20), charged right after each row is saved. Rows that incremental mode suppresses as unchanged are never charged. Use Max wines to cap the cost of any run.
Is it legal to scrape Wine-Searcher?
This actor collects only publicly available price and rating data. You are responsible for how you use it: follow Wine-Searcher's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Prices and offer counts change constantly and reflect a live snapshot at the time of the run.
Can I run this on a schedule to track price changes?
Yes. Add the actor to a Schedule from the Schedules tab to run it automatically, for example daily. Turn on Incremental mode (see Resume & recurring updates above) to get only new and changed wines on each scheduled run.
Why don't the highest and median prices match what I see in the offers list?
highestPriceAmount and medianPriceAmount are normalised to one standard 750ml bottle for a fair comparison across merchants: a case offer is divided by its bottle count, and non-750ml formats such as magnums or half bottles are left out of the comparison. cheapestPriceAmount is untouched and always shows the lowest listed offer exactly as a merchant lists it. Wine-Searcher does not publish a specials, was-price, or discount field, so the spread between merchants reflects different merchants, formats, and stock, not a markdown.
Why did my run fail instead of returning an empty dataset?
A run fails when it returns no wines at all and at least one lookup could not be reached, for example because every connection attempt was refused. That is a connection problem, not a real answer, so it is reported as a failure rather than a silent empty dataset. If at least one wine is returned, or every lookup was read but simply had no matching page on Wine-Searcher (a misspelled name, a bad URL, or an unknown LWIN code), the run succeeds; unmatched items are logged as not found and are not written to the dataset.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear, or Airtable.
🔗 Want more wine and drinks data?
Pair this actor with these related scrapers from the same team:
| 🍷 Vivino Wine Scraper From $1.2/1K. Scrape Vivino.com for wine ratings, prices, taste profiles, food pairings... | 🍷 Dan Murphy’s Scraper Scrape Dan Murphy’s products by category, keyword, or specials. Extract 45+ fields... |
| 🍷 Untappd Beer, Brewery and Check-in Scraper Scrape Untappd beers, breweries, venues and check-ins by keyword, brewery, Top Rated... | 🥦 Lidl.es Products, Weekly Offers, Prices & Reviews Scraper Scrape Lidl.es grocery and non-food products across weekly offers, tools, home, garden... |
| 🥦 REWE.de Scraper Scrape REWE Germany (rewe.de) grocery products: current price, was-price and discount... | 🥦 ResQ Club Scraper Scrape ResQ Club surplus food offers in Finland, Sweden and Estonia: name, price, current... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.