# Vivino Scraper & API: Wine Ratings and Prices in 22 Markets (`usefulapi/vivino-scraper`) Actor

Vivino scraper and unofficial Vivino API: wine ratings data and wine prices by any of 4,186 regions, 2,233 grapes or 747 styles, or look up your own wine list, in up to 10 of 22 markets per run, with price change monitoring. From USD 1.50 per 1,000.

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

## Pricing

from $1.50 / 1,000 wines

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

## Vivino Scraper and API: wine ratings and wine prices by region, grape, market or your own list

Get Vivino wine ratings data and wine prices from merchants as clean rows for Excel, CSV, JSON or your app. Filter by **any** region
(4,186 of them), grape (2,233), wine style (747), wine country, type, food pairing, price band and minimum rating, or
search by wine and producer name. Compare the same wines in **up to 10 markets in one run** (US, UK (GB), Germany,
France, Switzerland, Japan and 16 more), and schedule it with a **watch** to get only what changed since the last run: new wines, price
drops and rises, rating changes and wines that left the list.

Or **look up your own list of wines** by Vivino URL, wine ID or name: each wine comes back with its rating, the vintage's
rating spread, Vivino's rankings, critic scores, drinking window, alcohol, grapes, every vintage's rating if you want
them, and the price in each market.

USD 1.50 per 1,000 wines explored, USD 2.00 per 1,000 wines looked up. No reviews and no personal data: wine, rating and
price data only.

### Who it is for

- **Wine shops and importers:** watch what competitors' wines sell for in each market, and which wines are new or
  discounted, without opening Vivino every day.
- **Buyers and sommeliers:** build a shortlist of every Barolo, Napa Cabernet or Champagne above 4.2 stars under a price,
  with taste and food pairing notes.
- **Analysts and journalists:** price and rating data by region, grape or style for market studies and price indexes.
- **Developers:** an unofficial Vivino API you call from code, with the same columns on every row.

### What you get for each wine

One row per wine vintage per market, with one merchant offer (the one Vivino shows first in that market). A wine
appears once per market, even when several search terms find it:

| Group | Fields |
|---|---|
| **Wine** | name, wine, winery, year, nonVintage, wineType, country, countryCode, region, regionId, style, styleGrapes, isNatural, vintageId, wineId, vivinoUrl, imageUrl |
| **Ratings** | rating (this vintage's Vivino average), ratingsCount, wineRating and wineRatingsCount (all vintages of the wine) |
| **Price** (the merchant offer Vivino shows in that market) | price (per bottle), currency, discountedFrom, discountPercent, minimumBottles (the offer is sold by that many bottles), bottleMl, offerUrl (the merchant's page) |
| **Taste** | tasteBody, tasteTannin, tasteSweetness, tasteAcidity, tasteFizziness (Vivino's 1 to 5 scales), flavorGroups, flavorNotes, foodPairings |
| **Run** | market, rank (position in this run's reading order: Vivino's order, or price band by price band above about 2,000 wines), searchTerm, scrapedAt |
| **Changes** (with a watch) | change, previousPrice, priceChange, priceChangePercent, previousRating, previousSeenAt |

A rating that Vivino has not published yet (too few ratings) is `null`, not 0.

### Two ways to use it

| | Explore | Wine lookup |
|---|---|---|
| You give | filters (region, grape, style, country, type, food, price band, rating) and/or search terms | a list: Vivino URLs, wine IDs or names (with a year if you want one vintage) |
| You get | every wine on sale in your markets that fits, up to 10,000 per market and search | one row per wine per market, also for wines nobody sells there (from a URL or ID) |
| Extra fields | taste structure, flavour notes, food pairings | rating spread (1 to 5 stars), global / country / region / winery rank, critic scores, drinking window, alcohol, grapes, every vintage's rating (option) |
| Price | USD 1.50 per 1,000 wines | USD 2.00 per 1,000 wines found; not found, ambiguous or invalid lines are free |
| Speed | about 1,000 wines a minute | about 15 wines a minute per market |

Both work with markets, currency and the monitoring watch.

### Compared with the other Vivino tools on Apify (checked 17 Oct 2026)

| | This Actor | Most-used Vivino lookup tool | Most-used Vivino region tool |
|---|---|---|---|
| Price per 1,000 wines | USD 1.50 explore, USD 2.00 lookup | USD 4.00 (lower on paid Apify plans) | USD 5.00 (lower on paid plans) |
| Regions and grapes | all 4,186 regions and 2,233 grapes by name, with typo suggestions | by wine name or URL | 299 regions, 21 grapes |
| Markets in one run | up to 10 of 22 | one | one |
| Wines per run | up to 2,000 lookups, or 10,000 per market and search | up to 250 | up to 10,000 |
| Change monitoring | built in (new, price down or up, rating changed, removed) with a cheap "only changes" rate | no built-in comparison | no built-in comparison |
| Rankings, critic scores, rating spread, drinking window | yes (lookup) | no | no |
| Reviews and reviewer names | never collected | optional | no |

### Why this scraper

- **Every filter, by plain name.** Type "Barolo", "Napa Valley", "Pinot Noir", "Spanish Rioja Red" or "Shellfish": the
  names are matched to Vivino's own lists before the run starts. A typo stops the run at once with suggestions ("Did you
  mean: Brunello di Montalcino?"), so a typo costs nothing but the run start. Sub-regions are included (Napa Valley also
  gives Oakville, Rutherford and Stags Leap District).
- **Several markets side by side.** Vivino prices depend on where you buy. Pick US, GB, DE and FR and get each wine with
  its price in each market; set one currency (for example USD) to compare them directly.
- **Monitoring built in.** Name a watch and schedule the Actor (daily or weekly). Every row says what changed since the
  last run; with "Save only changes", unchanged wines are not saved and cost USD 0.20 per 1,000 instead of USD 1.50, so
  a daily watch of 1,000 wines costs about USD 0.20 a day when little changes.
- **Past Vivino's 2,000-wine list limit.** Vivino stops every list at about 2,000 wines. When you ask for more, the
  Actor splits the search into price bands that each fit, and reads them one after another, so a search for all
  4-star reds in the US can return up to 10,000 wines instead of 2,000 (5,000 tested). Every wine appears once.
- **About 1,000 wines a minute:** 50 per Vivino request, one request at a time.
- **No personal data.** No reviews, no reviewer names, no user pages: only wine, rating and price data.

### Input

```json
{
  "markets": ["US", "GB"],
  "regions": ["Barolo"],
  "minRating": 4.2,
  "maxPrice": 150,
  "currency": "USD",
  "maxResults": 500,
  "watch": "barolo-under-150"
}
```

| Field | Default | Notes |
|---|---|---|
| `wines` | | Lookup mode: Vivino URLs, wine IDs or names, one per line (up to 2,000). With a list, the filters below are not used |
| `includeAllVintages` | false | Lookup: add every vintage's year, rating and number of ratings to the row, free |
| `markets` | US | Ship-to countries: US, CA, GB, FR, DE, AT, CH, IT, ES, PT, NL, BE, LU, DK, SE, FI, CZ, AU, JP, SG, HK, BR. Up to 10 |
| `searchTerms` | | Wine or producer names, each searched on its own (Opus One, Sassicaia, Penfolds Grange). Up to 25 |
| `regions`, `countries`, `grapes`, `styles`, `foods` | | Names or Vivino ids. `countries` is where the wine is made (Italy or IT). "Central Valley, Chile" picks one of two regions with the same name |
| `wineTypes` | | red, white, sparkling, rose, dessert, fortified |
| `minRating` | | 1 to 5. Wines without a published rating are left out when set |
| `minPrice`, `maxPrice` | | Per bottle, in `currency`, or else in each market's own (US = USD, GB = GBP, CH = CHF, euro markets = EUR). With markets in different currencies, set `currency` |
| `currency` | each market's own | USD, EUR, GBP, CHF, CAD, AUD, JPY, SGD, HKD, DKK, SEK, CZK, BRL |
| `sortBy`, `sortOrder` | rating, desc | rating, ratings_count (popularity), price or discount |
| `maxResults` | 100 | Wines per market and per search term, up to 10,000 (above about 2,000 the search is read in price bands) |
| `watch` | | A name for monitoring; see below |
| `onlyChanges` | false | With a watch: save only new, removed and changed wines |

At least one filter, search term or wine is needed (Vivino does not list its whole catalogue at once).

#### Wine lookup example

```json
{
  "markets": ["US", "GB"],
  "wines": [
    "https://www.vivino.com/US/en/opus-one-opus-one/w/1911534?year=2015",
    "Sassicaia 2018",
    "Caymus Cabernet Sauvignon"
  ],
  "includeAllVintages": true
}
```

Each row says `lookupStatus`: `found` (billed), `year_not_found` (the wine exists but Vivino has no such year; the row
shows the vintage Vivino opens instead), `not_found`, `ambiguous` (a name like "Barolo" that many producers use: add the
producer) or `invalid`. Only `found` rows are billed. For names, `lookupNote` says which wine was taken ("matched by name:
Tenuta San Guido, Sassicaia"); a name is matched as a whole phrase, so "Chateau Margaux" never takes "Château du
Courneau Margaux". A Vivino URL is always exact and also works for wines that nobody sells in your market; a name uses
Vivino's search, which lists wines on sale in that market. Without a year, a name gives the newest vintage on sale.

### Output example

```json
{
  "market": "US",
  "rank": 1,
  "vintageId": 18745256,
  "wineId": 3151741,
  "name": "Schrader Cabernet Sauvignon CCS Beckstoffer To Kalon Vineyard 2009",
  "winery": "Schrader",
  "year": 2009,
  "wineType": "Red",
  "country": "United States",
  "region": "Oakville",
  "style": "Napa Valley Cabernet Sauvignon",
  "styleGrapes": ["Cabernet Sauvignon"],
  "rating": 4.9,
  "ratingsCount": 82,
  "wineRating": 4.7,
  "wineRatingsCount": 1239,
  "price": 1819,
  "currency": "USD",
  "minimumBottles": 1,
  "bottleMl": 750,
  "tasteBody": 4.53,
  "tasteTannin": 3.2,
  "flavorGroups": ["black fruit", "oak", "earth", "spices", "red fruit"],
  "foodPairings": ["Beef", "Lamb", "Game (deer, venison)", "Mature and hard cheese", "Poultry"],
  "vivinoUrl": "https://www.vivino.com/w/3151741?year=2009"
}
```

The dataset has four views: Overview, Taste and pairings, Merchant offer, and Changes since last run. The run summary
(key-value store, record `OUTPUT`) lists the filters as matched, the results per market and search, what was billed and
why a run stopped early, if it did.

### Monitoring: changes since the last run

1. Set `watch` to a name, for example `napa-cabs-us`.
2. Schedule the Actor (Schedules tab, for example every morning).
3. Each row gets `change`:

| change | Meaning |
|---|---|
| `baseline` | first run of the watch (or new filters): the starting point |
| `new` | not in the last run's results |
| `price_down`, `price_up` | the per-bottle price changed; see `previousPrice`, `priceChange`, `priceChangePercent` |
| `rating_changed` | same price, different Vivino rating; see `previousRating` |
| `unchanged` | same price and rating (a growing number of ratings alone is not a change) |
| `removed` | in the last run, not in this one: no longer offered in that market, or now outside your filters. Only reported when both runs read every result (not cut by `maxResults`) |

The last run's wines are kept in your own account, key-value store `vivino-wines-watch` (about 120 bytes a wine). Changing
the filters or the currency starts a new baseline. Several watches can run side by side with different names. A watch
keeps up to 50,000 wines. A `removed` row is billed like a saved wine and has only the name, ids, year and previous
price and rating filled in.

### Pricing

Pay per event, no monthly fee:

| Event | Price |
|---|---|
| Run start | USD 0.003 per run |
| Wine saved (one explore row) | USD 1.50 per 1,000 |
| Wine looked up (one lookup row, found) | USD 2.00 per 1,000 |
| Wine checked, unchanged, not saved ("Save only changes") | USD 0.20 per 1,000 |

Set a maximum cost per run and the Actor stops before it, keeping every row it saved. 1,000 wines cost USD 1.50; a daily
watch of 1,000 wines with "Save only changes" costs about USD 0.20 plus USD 1.50 per 1,000 changed wines. The first run
of a watch saves every wine (the baseline, USD 1.50 per 1,000); the lower rate applies from the second run.

### Good to know

- **Vivino lists the wines that a merchant sells in the market you pick**, each with one offer: the price Vivino shows
  first. A wine nobody sells in that market is not in its results.
- **`price` is per bottle.** Some merchants sell only by several bottles; `minimumBottles` says how many (for example 6
  or 12).
- **Prices are Vivino's**, in the currency you ask for; Vivino converts other currencies itself. In the US, Vivino's
  offers also depend on the state (wine shipping laws), so the US list can differ a little from what you see at home.
- **Ratings are Vivino's community averages** on a 1 to 5 scale. `rating` is for that vintage; `wineRating` covers all
  vintages of the wine.
- **The Actor reads Vivino slowly and politely** (one request at a time, at least 1.5 s apart) and never uses proxies to
  get around limits. If Vivino says to slow down three times in a row, the run stops and keeps what it saved.
- This Actor is not made by, endorsed by or affiliated with Vivino. You are responsible for how you use the data,
  including under Vivino's terms of service.

### FAQ

**How many wines can I get?** Up to 10,000 per market and search term in one run (about 1,000 a minute). Vivino's own
count for your filters is in the run summary (`recordsMatchedOnVivino`). Above about 2,000, the search is read in price
bands (cheapest band first, or dearest first when you sort by price, highest first), so the rows follow the bands rather
than one overall order; the summary says how many times a search was split (`priceBandSplits`).

**Can I look up one specific wine?** Yes: put its name in `searchTerms` (for example "Opus One" or "Sassicaia"); you get
the wines Vivino's search finds for that name that are on sale in your markets, every vintage on its own row, best
rated first. Other wines with similar names can appear. Search by the name only: a year in the search term does not
narrow it (use the `year` column).

**Why are some ratings null?** Vivino publishes a vintage's average only after enough people rated it; the row still has
`ratingsCount` and the wine's all-vintage `wineRating`.

**Do you collect reviews?** No. Reviews carry people's names and their own words, so this Actor leaves them out.

**Is there a Vivino API?** Vivino does not offer one for this data. This Actor works as an unofficial Vivino API: call it
with the Apify API or any Apify client (JavaScript, Python), or from Make, Zapier and n8n.

# Actor input Schema

## `markets` (type: `array`):

Where the wine is sold. Vivino shows each wine with the price of a merchant in that market, so the same wine has a different price (or none) per market. Pick several to compare prices side by side: one row per wine per market. Up to 10.

## `wines` (type: `array`):

Your own list of wines, one per line: a Vivino address (https://www.vivino.com/.../w/1911534?year=2015), a wine ID (1911534) or a name with an optional year (Opus One 2015, Chateau Margaux, Caymus Cabernet Sauvignon). Each wine gets its rating, the vintage's own rating and rating spread, Vivino's rankings, critic scores, drinking window, alcohol and grapes, plus the price in each market you picked. A Vivino address works for any wine, on sale or not; a name uses Vivino's search, which lists wines on sale in the market, and the row says which wine it took. Not found, ambiguous or invalid lines are saved and never billed. Up to 2,000.

## `includeAllVintages` (type: `boolean`):

With the wine lookup: add a column listing every vintage of the wine with its year, Vivino rating and number of ratings, at no extra cost.

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

Optional. Each term is searched on its own (Vivino's own search), for example Opus One, Sassicaia, Penfolds Grange. A wine appears once per market: if an earlier term already found it, a later term skips it. Combine with the filters below or use alone. Up to 25.

## `regions` (type: `array`):

Any of Vivino's 4,186 regions by name: Napa Valley, Barolo, Bordeaux, Rioja, Champagne, Mosel... Sub-regions are included (Napa Valley also gives Oakville and Rutherford). A name used in two countries takes both; write "Central Valley, Chile" for one. A typo stops the run before any request, with suggestions.

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

Where the wine is made, by name or code: Italy or IT, France, US, Portugal... (not the market you buy in).

## `grapes` (type: `array`):

Any of 2,233 grapes by name: Pinot Noir, Nebbiolo, Syrah, Chardonnay, Riesling...

## `wineTypes` (type: `array`):

Red, white, sparkling, rosé, dessert or fortified. Several = any of them.

## `styles` (type: `array`):

Vivino's 747 wine styles by name, for example Napa Valley Cabernet Sauvignon, Italian Barolo, Spanish Rioja Red, Champagne.

## `foods` (type: `array`):

Wines Vivino pairs with: Beef, Lamb, Pork, Poultry, Pasta, Shellfish, Spicy food, Mature and hard cheese...

## `minRating` (type: `number`):

From 1 to 5, for example 4 or 4.2. Wines without a published rating are left out when this is set.

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

Per bottle, in the currency below, or else in each market's own (US = USD, GB = GBP, CH = CHF, euro markets = EUR). Leave empty for no minimum.

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

Per bottle, same currency as the minimum. With several markets in different currencies, set the currency below. Leave empty for no maximum.

## `currency` (type: `string`):

Empty = each market's own currency. Set one (for example USD) to compare markets in a single currency (Vivino converts) or to use a price band across markets.

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

Vivino's order. maxResults keeps the first ones in this order.

## `sortOrder` (type: `string`):

Highest first or lowest first, in the order chosen above.

## `maxResults` (type: `integer`):

Each market (and each search term) gives up to this many wines. About 1,000 wines a minute. Up to 10,000.

## `watch` (type: `string`):

Give the search a name (for example napa-cabs) and schedule the run. Each run is compared with the previous run of the same watch: every row gets change = new, price_down, price_up, rating_changed, unchanged or removed, with the old price and the change in %. The last run's wines are kept in your account's key-value store vivino-wines-watch. Changing the filters or the currency starts a new baseline. A watch keeps up to 50,000 wines.

## `onlyChanges` (type: `boolean`):

With a watch: save only wines that are new, removed or changed in price or rating. Unchanged wines are not saved and are billed at USD 0.20 per 1,000 instead of USD 1.50. The first run of a watch saves every wine (the baseline).

## Actor input object example

```json
{
  "markets": [
    "US"
  ],
  "wines": [],
  "includeAllVintages": false,
  "searchTerms": [],
  "regions": [
    "Napa Valley"
  ],
  "wineTypes": [
    "red"
  ],
  "minRating": 4.2,
  "currency": "",
  "sortBy": "rating",
  "sortOrder": "desc",
  "maxResults": 100,
  "onlyChanges": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per wine vintage per market: rating, number of ratings, merchant price, region, style, taste and food pairings; with a watch, the change since the last run. Download as CSV, Excel or JSON.

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

Filters as resolved, results per market and search, billed events, changes found, Vivino requests and why the run stopped early (if it did).

# 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 = {
    "wines": [],
    "searchTerms": [],
    "regions": [
        "Napa Valley"
    ],
    "wineTypes": [
        "red"
    ],
    "minRating": 4.2
};

// Run the Actor and wait for it to finish
const run = await client.actor("usefulapi/vivino-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 = {
    "wines": [],
    "searchTerms": [],
    "regions": ["Napa Valley"],
    "wineTypes": ["red"],
    "minRating": 4.2,
}

# Run the Actor and wait for it to finish
run = client.actor("usefulapi/vivino-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 '{
  "wines": [],
  "searchTerms": [],
  "regions": [
    "Napa Valley"
  ],
  "wineTypes": [
    "red"
  ],
  "minRating": 4.2
}' |
apify call usefulapi/vivino-scraper --silent --output-dataset

```

## MCP server setup

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