# Vivino Wine Reviews Scraper (`confidential_gnat/vivino-reviews-scraper`) Actor

Scrapes user reviews and tasting notes from Vivino (vivino.com), including the review text, star rating, vintage year, review language, like and comment counts, and the reviewer's name and profile statistics.

- **URL**: https://apify.com/confidential\_gnat/vivino-reviews-scraper.md
- **Developed by:** [ActorFlow](https://apify.com/confidential_gnat) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00001 / review (one row per review)

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 Wine Reviews Scraper

**Scrape user reviews and tasting notes from Vivino (vivino.com)** for any wine. This **Vivino reviews scraper** extracts the full review text, the reviewer's **star rating**, the vintage reviewed, the review language, like and comment counts, and the reviewer's name and profile statistics. Filter by language or minimum rating, then export to JSON, CSV or Excel — or call it as an **API**. Paste a Vivino wine link, press Start.

**Target website:** [vivino.com](https://www.vivino.com)

### ✨ Features of this Vivino reviews scraper

- **Two output formats** — choose one JSON result per wine (all its reviews in one `reviews` array, so multiple wines map cleanly to multiple results) or one flat row per review for spreadsheets and CSV
- **Full review text** — the complete tasting note as written, not a truncated preview
- **Star ratings** — Vivino's 1–5 rating for every review
- **Reviewer profiles** — display name, total ratings written and follower count, so you can weight credible reviewers
- **Engagement metrics** — like and comment counts per review
- **Language filter** — keep only reviews in the language you need
- **Rating filter** — keep only reviews at or above a star rating
- **Accepts any Vivino link** — wine URLs, vintage URLs and bare wine IDs all work
- **Pagination support** — walks through review pages until your limit is reached
- **Repeat-run caching** — name a cache project and scheduled runs return only reviews you have not collected before, so you never pay for the same data twice
- **No browser required** — runs on plain HTTP requests, which makes it fast and cheap

### 🚀 How to scrape Vivino reviews in 5 steps

1. [Sign up](https://apify.com/sign-up) for a free Apify account — includes **$5 monthly credit**.
2. Open the actor page and click **Try for free**.
3. Paste one or more Vivino wine URLs into **Wine URLs**.
4. Click **Start** and wait for the run to complete.
5. Download results from the **Output** tab in JSON, CSV, or Excel format.

You can also run this actor via the [Apify API](https://docs.apify.com/api/v2) or integrate it directly into your workflows using [Zapier](https://zapier.com/apps/apify), [Make](https://www.make.com/), or [n8n](https://n8n.io/).

### 💰 Pricing

This actor uses **pay-per-event** billing: you pay per review saved, and the price depends on the **Output format** you choose.

| Output format                       | Event charged                   | Price per review |
| ----------------------------------- | ------------------------------- | ---------------- |
| One item per wine (`PER_WINE`)      | Review (grouped per wine)       | $0.0018          |
| One row per review (`PER_REVIEW`)   | Review (one row per review)     | $0.002           |

- Grouped output is slightly cheaper per review, so it is the default.
- You are charged only for reviews actually saved. Reviews skipped by the cache, or removed by the language and rating filters, are free.
- New Apify accounts include **$5 of free monthly credit**.
- It runs on plain HTTP requests rather than a headless browser, so it costs significantly less to run than browser-based review scrapers.
- Residential proxies are used by default for reliable access. Switching to datacenter proxies or turning the proxy off in the input lowers run cost.

### 💸 Avoid paying for duplicate Vivino reviews with the cache

Scraping the same wines on a schedule normally returns the same reviews every time. Set **Cache project name** (`cacheProjectName`) to any name, for example `my-wine-monitor`, and the actor remembers every review it has already saved:

1. **First run** — collects reviews as usual and stores their IDs under that project name.
2. **Every later run** with the same name — skips reviews already collected, so the output holds **only new reviews**.
3. **Wines with nothing new** — no result is saved for them, so a quiet week produces an empty dataset instead of a repeat of last week's data.

Use one project name per monitoring job and reuse it on every run. Use a different name to start fresh. Pair it with [Apify Schedules](https://docs.apify.com/platform/schedules) to track how wines are received over time while paying only for new reviews.

Filters run before the cache, so a review excluded by `language` or `minRating` is not marked as seen. You can widen the filters later and still collect it.

### 🔧 Input configuration

| Field                | Type    | Required | Default                            | Description                                                        |
| -------------------- | ------- | -------- | ---------------------------------- | ------------------------------------------------------------------ |
| `startUrls`          | array   | —        | `https://www.vivino.com/w/1122095` | Vivino wine URLs, vintage URLs or bare wine IDs.                   |
| `maxItems`           | integer | —        | `50`                               | Maximum reviews **per wine**. Set to `0` for no limit.             |
| `language`           | string  | —        | —                                  | Two-letter code, e.g. `en`, `fr`, `it`. Empty keeps all languages. |
| `outputFormat`       | string  | —        | `PER_WINE`                         | `PER_WINE` saves one item per wine with all its reviews in a `reviews` array. `PER_REVIEW` saves one flat row per review. |
| `minRating`          | integer | —        | —                                  | Keep only reviews rated at least this highly (1–5).                |
| `cacheProjectName`   | string  | —        | —                                  | Name a project to remember scraped reviews across runs.            |
| `proxyConfiguration` | object  | —        | `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}` | Proxy settings. Residential proxies by default. |

**Supported input types:**

- Wine URL — `https://www.vivino.com/w/1122095`
- Localised wine URL — `https://www.vivino.com/en/domaine-merlet-merlot/w/6980968`
- Vintage URL — `https://www.vivino.com/wines/164943024` (resolved to its wine automatically)
- Bare wine ID — `1122095`

### 📦 Vivino reviews scraper output data

The output depends on the **Output format** input.

**One item per wine (`PER_WINE`, default)** — one result per input URL with the keys `wineId`, `wineUrl`, `wineName`, `reviewsCount` and `reviews`. `reviews` is an array of objects with `reviewId`, `vintageYear`, `rating`, `review`, `language`, `createdAt`, `likeCount`, `commentCount`, `userName`, `userId`, `userRatingsCount`, `userFollowersCount` and `userImage`.

**One row per review (`PER_REVIEW`)** — every review is its own flat result with the same review keys plus `wineId`, `wineUrl` and `wineName`. Best for CSV and Excel export.

The dataset ships with two views: **Overview**, one row per wine, and **Reviews (one row per review)**, a table of individual reviews.

**Sample output (`PER_WINE`):**

```json
[
    {
        "wineId": 1122095,
        "wineUrl": "https://www.vivino.com/w/1122095",
        "wineName": "Moët & Chandon Impérial Brut Champagne N.V.",
        "reviewsCount": 2,
        "reviews": [
            {
                "reviewId": 84847781,
                "vintageYear": "N.V.",
                "rating": 4.5,
                "review": "We needed some champagne for a recipe - and it’s a good job we did!",
                "language": "en",
                "createdAt": "2018-01-01T01:47:55.000Z",
                "likeCount": 217,
                "commentCount": 12,
                "userName": "Steve and Declan Carroll",
                "userId": 917135,
                "userRatingsCount": 1041,
                "userFollowersCount": 11131,
                "userImage": "https://images.vivino.com/avatars/GZyw78w4SSCef8FU7rrkOg.jpg"
            }
        ]
    }
]
```

### 🐍 How to scrape Vivino reviews with Python, JavaScript or the API

Run the actor programmatically with the official Apify clients. Replace `<YOUR_API_TOKEN>` with the token from your [Apify Console](https://console.apify.com/account/integrations).

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("<username>/vivino-reviews-scraper").call(run_input={
    "startUrls": [{"url": "https://www.vivino.com/w/1122095"}],
    "maxItems": 200,
    "language": "en",
})

for wine in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(wine["wineName"], wine["reviewsCount"])
    for review in wine["reviews"]:
        print(review["rating"], review["userName"], review["review"])
```

**JavaScript** (`npm install apify-client`):

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const run = await client.actor('<username>/vivino-reviews-scraper').call({
    startUrls: [{ url: 'https://www.vivino.com/w/1122095' }],
    maxItems: 200,
    language: 'en',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

**cURL** — start a run and wait for the dataset:

```bash
curl -X POST "https://api.apify.com/v2/acts/<username>~vivino-reviews-scraper/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"startUrls": [{"url": "https://www.vivino.com/w/1122095"}], "maxItems": 200}'
```

### 💡 What you can use Vivino review data for

- **Sentiment analysis** — run NLP over thousands of tasting notes for one wine
- **Tasting note mining** — find the descriptors drinkers actually use for a style
- **Product feedback** — see what buyers say about a wine you sell or make
- **Competitor benchmarking** — compare review sentiment across similar wines
- **Rating distribution analysis** — look past the average to how ratings actually spread
- **Influencer identification** — find highly followed reviewers writing in your category

Wineries, importers, retailers, market researchers and data scientists use this data across wine, hospitality and consumer research.

### ⚠️ Limitations & known issues

- **Reviews are user-generated content** — they carry display names and opinions. Treat them as personal data and check your obligations before republishing.
- **No vintage filter at source** — Vivino's review endpoint accepts a year parameter but ignores it, so the actor does not offer one. Every review carries its own `vintageYear`, so filter after the fact if you need a single vintage.
- **Very popular wines** — a wine with tens of thousands of reviews takes many pages; set a realistic `maxItems` unless you want the lot.
- **Language detection is Vivino's** — the `language` field comes from Vivino and is occasionally wrong for very short notes.
- **Rate limiting** — scraping many wines at high volume may be throttled; enable proxies if you hit limits.

### ❓ Frequently asked questions

#### Can I scrape Vivino reviews legally?

This actor only collects reviews that are already publicly visible on Vivino — no login, paywall, or private content is accessed. Scraping publicly available data is generally considered lawful (see *hiQ Labs v. LinkedIn* as precedent). Reviews are user-generated content containing display names and opinions, so they are personal data under the GDPR: you need a lawful basis to store them, and review text remains the author's. You are responsible for complying with Vivino's Terms of Service.

#### How many reviews can I scrape from one wine?

`maxItems` limits results **per wine**, so five wines with `maxItems: 200` returns up to 1,000 reviews. Set it to `0` to take every review a wine has.

#### Can I scrape reviews for a specific vintage?

Not at source — Vivino's endpoint ignores its own year parameter, which is why this actor does not offer a vintage filter that would not work. Each review does carry a `vintageYear`, so filter the dataset afterwards.

#### What is the difference between a wine URL and a vintage URL?

`/w/{id}` identifies the wine across all its vintages; `/wines/{id}` identifies one vintage. They carry different IDs, and reviews are served per wine — so if you paste a vintage URL the actor resolves it to its wine automatically and logs which one it used.

#### Do I need a proxy to scrape vivino.com?

The actor uses Apify residential proxies by default, which gives the most reliable access, especially when scraping many wines in one run. Vivino also responds without a proxy, so you can switch to datacenter proxies or turn the proxy off in the input to lower cost.

#### How do I scrape Vivino reviews with Python?

Install `apify-client`, then call the actor with your wine URLs and iterate the dataset — see the Python example above. Each review comes back as flat JSON ready for pandas or an NLP pipeline.

#### Can I run this Vivino reviews scraper on a schedule?

Yes. Use [Apify Schedules](https://docs.apify.com/platform/schedules) to re-run it, and set `cacheProjectName` so each run returns only reviews you have not collected before. That keeps scheduled runs from returning, and billing you for, the same reviews again.

#### How do I avoid paying for the same Vivino reviews twice?

Set `cacheProjectName` to the same value on every run. The actor stores the IDs of reviews it has saved and skips them next time, so repeat runs return only new reviews.

#### How is the Vivino review output structured?

One dataset item per wine you enter. Each item holds the wine's `wineName`, `wineUrl` and `reviewsCount`, plus a `reviews` array with every review. Enter five wine URLs and you get five items. If you need one row per review for a spreadsheet, flatten the `reviews` array after export.

#### Can I get one row per review instead of one item per wine?

Yes. Set **Output format** to `PER_REVIEW` and every review is saved as its own flat row. The default, `PER_WINE`, keeps each wine's reviews together in one JSON object.

#### What output formats are supported?

JSON, CSV, Excel, XML and RSS, either from the **Output** tab or through the Apify API.

### 🔗 Other actors you may find useful

- [Vivino Wine Scraper](https://apify.com/confidential_gnat/vivino-wine-scraper) — extract wines, ratings, prices, regions, grapes and taste profiles from Vivino.
- [Church Finder Scraper](https://apify.com/confidential_gnat/churchfinder-scraper) — find and extract church listings and details.
- [Gametime Events Scraper](https://apify.com/confidential_gnat/gametime-events-scraper) — scrape live event and ticket data from Gametime.
- [INCIDecoder Scraper](https://apify.com/confidential_gnat/incidecoder-scraper) — extract cosmetic ingredient data from INCIDecoder.
- [Whois.com Scraper](https://apify.com/confidential_gnat/whois-com) — look up domain registration and ownership data.
- [Cars & Bids Cheapest Listings Scraper](https://apify.com/confidential_gnat/cheapest-carsandbids-scraper) — find the cheapest car auctions on Cars & Bids.

### 💬 Support & contact

If you encounter any issues or have questions, please [open an issue](https://apify.com/confidential_gnat/vivino-reviews-scraper/issues/open).

You can also find more of our actors on the [Actor Flow](https://apify.com/confidential_gnat).

# Actor input Schema

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

Vivino wine URLs to scrape reviews for. Accepts wine URLs (https://www.vivino.com/w/1122095), vintage URLs (https://www.vivino.com/wines/164942645) and bare wine IDs. Vintage URLs are resolved to their wine automatically.

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

Maximum number of reviews to scrape per wine. Set to 0 for no limit — popular wines have tens of thousands.

## `outputFormat` (type: `string`):

Choose how reviews are saved. One item per wine keeps all of a wine's reviews together in a single JSON object, so each input URL gets its own result. One row per review saves every review as its own flat item, which suits spreadsheets and CSV export.

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

Only keep reviews written in this language, as a two-letter code such as en, fr, it. Leave empty to keep every language.

## `minRating` (type: `integer`):

Only keep reviews with at least this star rating (1–5). Leave empty to keep all reviews.

## `cacheProjectName` (type: `string`):

Optional. Reuse the same name on every run to skip reviews you have already collected, so scheduled runs return only new reviews and you do not pay for duplicates.

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

Proxy settings. Residential proxies are used by default for the most reliable access to Vivino. You can switch to datacenter proxies or turn the proxy off to lower run cost.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.vivino.com/w/1122095"
    }
  ],
  "maxItems": 50,
  "outputFormat": "PER_WINE",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "startUrls": [
        {
            "url": "https://www.vivino.com/w/1122095"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("confidential_gnat/vivino-reviews-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 = {
    "startUrls": [{ "url": "https://www.vivino.com/w/1122095" }],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("confidential_gnat/vivino-reviews-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 '{
  "startUrls": [
    {
      "url": "https://www.vivino.com/w/1122095"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call confidential_gnat/vivino-reviews-scraper --silent --output-dataset

```

## MCP server setup

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