# Vivino Scraper: Wine Prices, Ratings and Price Monitor (`kamerozkan/vivino-scraper`) Actor

Scrape Vivino wines by wine type, grape, origin country, price range and minimum rating. Get ratings, market prices, offer counts, taste profile and food pairings per wine, and track price changes between runs. Plain HTTP, fast and low cost.

- **URL**: https://apify.com/kamerozkan/vivino-scraper.md
- **Developed by:** [Kamer Ozkan](https://apify.com/kamerozkan) (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 $2.00 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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: Wine Prices, Ratings and Price Monitor

Vivino scraper for wine prices and ratings: find wines on Vivino by wine type, grape, origin country, price range and minimum rating, and get the Vivino rating, ratings count, market price, taste profile and food pairings of every wine. Schedule it to monitor wine price changes between runs.

### What does Vivino Scraper do?

It runs the same search as the Vivino Explore page, with the filters you choose, and returns one clean row per wine vintage: name, winery, year, wine type, country, region, style, grapes, Vivino rating and ratings count (for the vintage and for the wine across all vintages), the current market price with currency and bottle size, the number of shop offers, the taste structure (acidity, intensity, sweetness, tannin), top flavor notes, food pairings, bottle image and Vivino link.

Prices on Vivino depend on the country you shop from. Pick a **Market** (US, GB, DE, FR, IT, NL, DK, CH, CA, AU and more) and the actor reads Vivino from that country, so you get the shop prices a buyer there sees, in the market currency.

With **Track price changes between runs** on (the default), the actor remembers the price of every wine for your filters. Schedule the same input every day or week and each row tells you the previous price, the price change and the change in percent, and marks wines that are new in the results. Turn on **Only output wines whose price changed or that are new** to pay only for the changes.

No login, no Vivino account and no API key are needed. Proxy is included in the price.

### Who is it for?

- **Wine importers and distributors** scanning a region or grape for highly rated wines in a price band before choosing what to import.
- **Wine shops and online retailers** checking market prices and ratings of the wines they stock, and watching competitors' price moves.
- **Sommeliers and wine buyers** building lists of the best rated wines per grape, country and budget.
- **Price comparison and wine app builders** who need Vivino ratings and market prices as structured data.
- **Analysts** studying rating and price distributions per region, style and vintage.

### What data can you get?

| Field | Example |
|---|---|
| `name` | Schrader Cabernet Sauvignon CCS Beckstoffer To Kalon Vineyard 2009 |
| `wine`, `year`, `winery` | Cabernet Sauvignon CCS Beckstoffer To Kalon Vineyard, 2009, Schrader |
| `wineType` | red, white, sparkling, rose, dessert or fortified |
| `country`, `countryCode`, `region` | United States, us, Oakville |
| `style`, `grapes` | Napa Valley Cabernet Sauvignon, \["Cabernet Sauvignon"] |
| `rating`, `ratingsCount` | 4.9, 82 (this vintage) |
| `wineRating`, `wineRatingsCount` | 4.7, 1239 (the wine across all vintages) |
| `price`, `currency` | 1819, USD |
| `bottleSize`, `bottleVolumeMl` | Bottle (0.75l), 750 |
| `offersCount` | Number of shop offers Vivino lists |
| `discountedFrom`, `discountPercent` | Filled when a shop runs a discount |
| `body`, `acidity`, `intensity`, `sweetness`, `tannin` | Very full-bodied, 3.33, 4.53, 1.83, 3.2 |
| `flavors` | \["blackberry", "cassis", "oak", "vanilla", ...] |
| `foodPairings` | \["Beef", "Lamb", "Game (deer, venison)"] |
| `market` | us (the country whose shop prices you see) |
| `previousPrice`, `priceChange`, `priceChangePercent`, `isNew` | 1819, 0, 0, false |
| `vintageId`, `wineId`, `url`, `imageUrl` | Vivino ids, wine page link and bottle image |
| `checkedAt` | 2026-10-17T20:56:24+00:00 |

### How much does it cost?

You pay only for wines: **$2.50 per 1,000 wines** on the Free plan, with lower prices on paid Apify plans. There is no extra charge per search page, per filter or for the proxy.

Worked example: a wine shop monitors 300 wines (French and Italian reds rated 4.0+ between $20 and $60) once a week. That is 300 x 4 = 1,200 wines a month, about **$3.00 per month**. With **Only output wines whose price changed or that are new** on, unchanged wines are skipped and not charged.

Set "Max wines" or a maximum cost per run to cap spending.

### How to use it

1. Click **Try for free**.
2. Pick the **Market** whose shop prices you want (for example US or GB).
3. Choose wine types, grapes (Vivino names such as "Cabernet Sauvignon", "Pinot Noir", "Chardonnay") and origin countries, or leave them empty for all.
4. Set a price range and a minimum Vivino rating, and how to sort.
5. Click **Start**, then download the results as JSON, CSV or Excel, or read them with the API.
6. To monitor prices, save the input as a task and add a schedule. Keep the same filters, because prices are compared per exact filter set.

### Input example

```json
{
  "market": "GB",
  "wineTypes": ["white", "sparkling"],
  "grapes": ["Chardonnay"],
  "originCountries": ["fr"],
  "priceMin": 20,
  "priceMax": 60,
  "minRating": "4",
  "sortBy": "price",
  "maxItems": 60,
  "trackPriceChanges": true
}
```

### Output example

Real row from a run on 2026-10-17 (second run of the same filters, so the price change fields are filled):

```json
{
  "vintageId": 18745256,
  "wineId": 3151741,
  "name": "Schrader Cabernet Sauvignon CCS Beckstoffer To Kalon Vineyard 2009",
  "wine": "Cabernet Sauvignon CCS Beckstoffer To Kalon Vineyard",
  "year": 2009,
  "winery": "Schrader",
  "wineType": "red",
  "country": "United States",
  "countryCode": "us",
  "region": "Oakville",
  "style": "Napa Valley Cabernet Sauvignon",
  "grapes": ["Cabernet Sauvignon"],
  "rating": 4.9,
  "ratingsCount": 82,
  "wineRating": 4.7,
  "wineRatingsCount": 1239,
  "price": 1819,
  "currency": "USD",
  "discountedFrom": null,
  "discountPercent": null,
  "bottleSize": "Bottle (0.75l)",
  "bottleVolumeMl": 750,
  "offersCount": 1,
  "body": "Very full-bodied",
  "acidity": 3.33,
  "intensity": 4.53,
  "sweetness": 1.83,
  "tannin": 3.2,
  "flavors": ["blackberry", "cassis", "blueberry", "oak", "vanilla", "chocolate"],
  "foodPairings": ["Beef", "Lamb", "Game (deer, venison)", "Mature and hard cheese", "Poultry"],
  "isNatural": false,
  "imageUrl": "https://images.vivino.com/thumbs/_jt3dPPrSZKfVmV6J8YlLg_pb_x600.png",
  "url": "https://www.vivino.com/w/3151741?year=2009",
  "market": "us",
  "previousPrice": 1819,
  "priceChange": 0,
  "priceChangePercent": 0,
  "isNew": false,
  "checkedAt": "2026-10-17T20:56:24+00:00"
}
```

The OUTPUT record of the run shows the market used, how many wines matched the filters on Vivino and the filters themselves.

### Integrations and API

Run it from your code with the Apify API or the `apify-client` package, schedule it in Apify, or connect it to Make, n8n, Zapier, Google Sheets or a webhook (for example a Slack message when `priceChangePercent` drops below -10).

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kamerozkan/vivino-scraper").call(run_input={
    "market": "US",
    "wineTypes": ["red"],
    "grapes": ["Pinot Noir"],
    "originCountries": ["fr", "us"],
    "priceMin": 20,
    "priceMax": 80,
    "minRating": "4",
    "maxItems": 200,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["rating"], item["price"], item["currency"], item["priceChange"])
```

### FAQ

**Which price do I get?** The price Vivino shows a buyer in the chosen market: the cheapest listed shop offer for a standard bottle, in the market currency. `offersCount` tells you how many offers Vivino lists.

**Why do the results differ from vivino.com in my browser?** Vivino shows prices and availability per country. Make sure the **Market** matches the country you compare with.

**How many wines can I get?** Up to the number of wines that match your filters on Vivino (shown in the OUTPUT record). Narrow the filters or raise "Max wines" as needed.

**How does it know the previous price?** It stores the last prices for your exact filters in a key-value store in your own Apify account. Change the filters and it starts a new history.

**Can I look up specific wines by name or URL?** Not yet: this version discovers wines through filters. Open an issue if you need name or URL lookup and it will be added.

**Is it legal to collect this data?** It collects public wine listing data only: wine names, wineries (businesses), ratings and prices. No user reviews or personal data. You are responsible for how you use it.

### Support and feedback

- Found a bug or missing a field? Open an issue on the **Issues** tab of this Actor with your run link. We reply within
  48 hours and ship most fixes within a few days.
- Have an idea for a feature? Issues are the fastest way to get it built.
- If the Actor saves you time, a short review on this page helps other users find it.

# Actor input Schema

## `market` (type: `string`):

Vivino shows the prices of shops that sell in this country. Two-letter code, for example US, GB, DE, FR, IT, NL, DK, CH, CA, AU. Requests go through Apify Proxy in this country.

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

Leave empty for all types.

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

Vivino grape names, for example "Cabernet Sauvignon", "Pinot Noir", "Chardonnay", "Shiraz", "Nebbiolo". Leave empty for all grapes.

## `originCountries` (type: `array`):

Where the wine is made, as two-letter codes, for example "fr", "it", "es", "us", "ar", "au". Leave empty for all countries.

## `priceMin` (type: `integer`):

In the market currency. Leave empty for no minimum.

## `priceMax` (type: `integer`):

In the market currency. Leave empty for no maximum.

## `minRating` (type: `string`):

Only wines rated at least this average (1 to 5), for example 3.5 or 4.0.

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

Order of the results. Price sorts lowest first.

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

Three-letter currency code for prices, for example USD, EUR, GBP. Empty uses the market currency.

## `trackPriceChanges` (type: `boolean`):

Remember each wine's price for these filters and report previousPrice, priceChange, priceChangePercent and isNew. Run on a schedule for a price history.

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

After the first run, output (and charge) only new wines and wines with a different price.

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

Stop after this many wines. You are charged per wine, so this also caps the cost of the run.

## `language` (type: `string`):

Language for style and food names, for example en, de, fr, es, it.

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

Apify Proxy is used by default: residential exits in the market country, included in the price per wine. Leave as is unless you know you need something else.

## Actor input object example

```json
{
  "market": "US",
  "wineTypes": [
    "red"
  ],
  "grapes": [
    "Cabernet Sauvignon"
  ],
  "originCountries": [
    "us"
  ],
  "priceMin": 15,
  "priceMax": 50,
  "minRating": "3.5",
  "sortBy": "rating",
  "trackPriceChanges": true,
  "onlyChanges": false,
  "maxItems": 100,
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per result in the default dataset.

# 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 = {
    "wineTypes": [
        "red"
    ],
    "grapes": [
        "Cabernet Sauvignon"
    ],
    "originCountries": [
        "us"
    ],
    "priceMin": 15,
    "priceMax": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kamerozkan/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 = {
    "wineTypes": ["red"],
    "grapes": ["Cabernet Sauvignon"],
    "originCountries": ["us"],
    "priceMin": 15,
    "priceMax": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kamerozkan/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 '{
  "wineTypes": [
    "red"
  ],
  "grapes": [
    "Cabernet Sauvignon"
  ],
  "originCountries": [
    "us"
  ],
  "priceMin": 15,
  "priceMax": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kamerozkan/vivino-scraper --silent --output-dataset

```

## MCP server setup

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