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

Extract detailed wine reviews from Vivino.com with precision. Scrape ratings, user profiles, tasting notes, language data, and timestamps across multiple pages — perfect for wine researchers, retailers, and sentiment analysis projects.

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

## Pricing

from $1.50 / 1,000 results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Vivino Reviews Scraper: Harvest Wine Review Data at Scale

***

### What Is Vivino.com?

Vivino.com is the world's largest wine social network and marketplace, hosting millions of wine reviews, ratings, and user-generated tasting notes. With over 10 million wines cataloged and a vibrant community of wine enthusiasts, Vivino represents an invaluable source of consumer sentiment, regional trends, and vintage-specific feedback. Manually collecting review data is impractical — the **Vivino Reviews Scraper** automates extraction of structured review records, enabling bulk analysis and competitive intelligence.

***

### Overview

The **Vivino Reviews Scraper** extracts detailed review records from individual Vivino wine product pages, capturing ratings, user profiles, tasting notes, and metadata in a structured format. It is designed for:

- **Wine retailers & distributors** analyzing customer sentiment by vintage or region
- **Researchers** studying wine appreciation trends and review patterns
- **Data analysts** building datasets for sentiment or rating prediction models
- **Aggregators** feeding wine review data into comparison or recommendation platforms

Key strengths include flexible filtering by star rating, sorting by helpfulness or recency, pagination support for large review sets, and robust URL failure handling.

***

### Input Format

The scraper accepts a JSON configuration object to target specific wine products and refine results:

```json
{
  "urls": [
    "https://www.vivino.com/en/san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria/w/11890?year=2020&price_id=42539229#all_reviews"
  ],
  "page": 2,
  "rating": "5",
  "sort_by": "latest_reviews",
  "ignore_url_failures": true,
  "max_items_per_url": 200
}
```

| Field | Type | Description |
|---|---|---|
| `urls` | Array | Direct Vivino product page URLs (include the `#all_reviews` anchor). Paste one or multiple wine product links. |
| `page` | Integer | Starting page number for review pagination (default: `1`). Useful for resuming interrupted runs or targeting specific review batches. |
| `rating` | String | Filter reviews by star rating: `""` (any), `"5"` (5-star), `"4"` (4-star), ..., `"1"` (1-star). Leave empty to include all ratings. |
| `sort_by` | String | Sort order: `"reviews"` (most helpful first) or `"latest_reviews"` (newest first). Helps prioritize recent or community-validated feedback. |
| `ignore_url_failures` | Boolean | If `true`, the scraper continues if individual URLs fail; if `false`, it halts. Recommended: `true` for bulk runs. |
| `max_items_per_url` | Integer | Maximum reviews per product URL (e.g., `200`). Limits volume and runtime. Vivino pages typically contain 10–30 reviews per page. |

> **Pro tip:** Use `sort_by: "latest_reviews"` to capture fresh consumer sentiment; use `"reviews"` to find the most-discussed feedback.

***

### Output Format

#### Example Output Record

```json
{
  "id": 357034454,
  "rating": 4.5,
  "note": "Maravilhoso!",
  "language": "tn",
  "created_at": "2026-05-16T22:26:42.000Z",
  "user": {
    "id": 21640127,
    "seo_name": "mateus.lupo",
    "alias": "Mateus Lupo",
    "is_featured": false,
    "is_premium": false,
    "visibility": "all",
    "image": {
      "location": "//images.vivino.com/avatars/5BlLfZPCRKOAkrDlgaybLQ.jpg",
      "variations": {
        "large": "//thumbs.vivino.com/avatars/5BlLfZPCRKOAkrDlgaybLQ_300x300.jpg",
        "small_square": "//thumbs.vivino.com/avatars/5BlLfZPCRKOAkrDlgaybLQ_50x50.jpg"
      }
    },
    "background_image": {
      "location": "//images.vivino.com/users/backgrounds/default_1.jpg",
      "variations": {
        "large": "//images.vivino.com/users/backgrounds/default_1_1200x400.jpg",
        "medium": "//images.vivino.com/users/backgrounds/default_1_600x200.jpg",
        "small": "//images.vivino.com/users/backgrounds/default_1_140x60.jpg"
      }
    },
    "language": "pt",
    "relationship": {
      "is_followed_by_me": false,
      "is_following_me": false,
      "follow_requested": false,
      "ignored_my_follow_request": false,
      "requested_to_follow_me": false,
      "follow_ignored_by_me": false,
      "is_blocked_by_me": false,
      "is_blocking_me": false
    },
    "statistics": {
      "followers_count": 14,
      "followings_count": 2,
      "ratings_count": 5179,
      "ratings_sum": 20193.3,
      "reviews_count": 5062,
      "purchase_order_count": 0
    }
  },
  "vintage": {
    "id": 1504641,
    "seo_name": "san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria-uv",
    "name": "San Marzano 60 Sessantanni Old Vines Primitivo di Manduria U.V.",
    "statistics": {
      "status": "Normal",
      "ratings_count": 117906,
      "ratings_average": 4.5,
      "labels_count": 4404,
      "reviews_count": 1662
    },
    "organic_certification_id": null,
    "certified_biodynamic": null,
    "image": {
      "location": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_480x640.png",
      "variations": {
        "bottle_large": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pb_x960.png",
        "bottle_medium": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pb_x600.png",
        "bottle_medium_square": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pb_600x600.png",
        "bottle_small": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pb_x300.png",
        "bottle_small_square": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pb_300x300.png",
        "label": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_480x640.png",
        "label_large": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_375x500.png",
        "label_medium": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_150x200.png",
        "label_medium_square": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_150x150.png",
        "label_small_square": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_80x80.png",
        "large": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_375x500.png",
        "medium": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_150x200.png",
        "medium_square": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_150x150.png",
        "small_square": "//images.vivino.com/thumbs/tLtS1VwaRxCL25zZ-j6pZg_pl_80x80.png"
      }
    },
    "wine": {
      "id": 11890,
      "name": "60 Sessantanni Old Vines Primitivo di Manduria",
      "seo_name": "sixty-sessantanni-old-vines-primitivo-di-manduria",
      "type_id": 1,
      "vintage_type": 0,
      "is_natural": false,
      "region": {
        "id": 2753,
        "name": "Primitivo di Manduria",
        "name_en": "",
        "seo_name": "primitivo-di-manduria",
        "country": {
          "code": "it",
          "name": "Italy",
          "native_name": "Italia",
          "seo_name": "italy",
          "currency": {
            "code": "EUR",
            "name": "Euros",
            "prefix": "€",
            "suffix": null
          },
          "regions_count": 565,
          "users_count": 4903445,
          "wines_count": 301208,
          "wineries_count": 44031,
          "most_used_grapes": [
            {
              "id": 16,
              "name": "Sangiovese",
              "seo_name": "sangiovese",
              "has_detailed_info": true,
              "wines_count": 125094,
              "parent_grape_id": null,
              "color": 5
            },
            {
              "id": 5,
              "name": "Chardonnay",
              "seo_name": "chardonnay",
              "has_detailed_info": true,
              "wines_count": 604208,
              "parent_grape_id": null,
              "color": 1
            },
            {
              "id": 10,
              "name": "Merlot",
              "seo_name": "merlot",
              "has_detailed_info": true,
              "wines_count": 566719,
              "parent_grape_id": null,
              "color": 5
            }
          ]
        },
        "parent_id": 548,
        "background_image": {
          "location": "//images.vivino.com/regions/backgrounds/4hk4tWhkSueipqpj6rBxqQ.jpeg",
          "variations": {
            "large": "//thumbs.vivino.com/region_backgrounds/4hk4tWhkSueipqpj6rBxqQ_1280x760.jpeg",
            "medium": "//thumbs.vivino.com/region_backgrounds/4hk4tWhkSueipqpj6rBxqQ_600x356.jpeg"
          }
        },
        "class": "VivinoAPI::Region",
        "statistics": {
          "wineries_count": 138,
          "wines_count": 1528,
          "sub_regions_count": 0,
          "parent_regions_count": 2
        }
      },
      "review_status": 2,
      "winery": {
        "id": 55648,
        "name": "San Marzano",
        "seo_name": "san-marzano",
        "status": 3,
        "review_status": "Completed",
        "dashboard_url": "https://analytics-pbl.vivino.com/dashboards-next/60",
        "background_image": {
          "location": "//images.vivino.com/wineries/backgrounds/HxEtPoUBQF2f3rLG7QoXzA.jpeg",
          "variations": {
            "large": "//thumbs.vivino.com/winery_backgrounds/HxEtPoUBQF2f3rLG7QoXzA_2560x1520.jpeg",
            "medium": "//thumbs.vivino.com/winery_backgrounds/HxEtPoUBQF2f3rLG7QoXzA_1280x760.jpeg",
            "small": "//thumbs.vivino.com/winery_backgrounds/HxEtPoUBQF2f3rLG7QoXzA_600x356.jpeg"
          }
        },
        "statistics": {
          "ratings_count": 509081,
          "ratings_average": 4.1,
          "labels_count": 3462764,
          "wines_count": 175
        }
      },
      "style": null,
      "has_valid_ratings": false
    },
    "year": "",
    "grapes": null,
    "has_valid_ratings": true
  },
  "activity": {
    "id": 929967228,
    "statistics": {
      "likes_count": 1,
      "comments_count": 1
    }
  },
  "tagged_note": "Maravilhoso!",
  "from_url": "https://www.vivino.com/en/san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria/w/11890?year=2020&price_id=42539229#all_reviews"
}
```

Each review record returns 9 key fields capturing both review content and metadata:

#### Review Content & Ratings

| Field | Meaning |
|---|---|
| `ID` | Unique identifier for the review within Vivino's database |
| `Rating` | Star rating given by the reviewer (1–5 stars) |
| `Note` | Full text of the tasting review or comment |
| `Language` | Language code of the review (e.g., `en`, `fr`, `de`) |

#### Reviewer & Context

| Field | Meaning |
|---|---|
| `User` | Username or profile identifier of the reviewer |
| `Created At` | ISO timestamp when the review was posted |
| `Vintage` | Wine vintage year (e.g., `2020`) referenced in the review or product page |

#### Engagement & Classification

| Field | Meaning |
|---|---|
| `Activity` | Engagement metric (e.g., helpfulness count, number of upvotes received on the review) |
| `Tagged Note` | Community-applied tags or labels (e.g., `"fruity"`, `"bold"`, `"food_pairing"`) if available |

***

### How to Use

1. **Find wine URLs** — Browse Vivino.com and open a wine's detail page. Copy the full URL including the `#all_reviews` anchor (e.g., `https://www.vivino.com/en/.../w/12345#all_reviews`).

2. **Configure input** — Paste URLs into the `urls` array. Adjust `rating` and `sort_by` to focus on specific feedback (e.g., 5-star reviews sorted by latest).

3. **Set pagination** — Use `page: 1` to start from the first review page. Adjust `max_items_per_url` based on your data needs (e.g., `200` for comprehensive datasets).

4. **Enable resilience** — Set `ignore_url_failures: true` for bulk scraping to skip broken or region-restricted product pages.

5. **Run the scraper** — Execute the actor and monitor the run log for progress.

6. **Export results** — Download the dataset as JSON, CSV, or Excel for analysis.

**Troubleshooting:**

- If a URL returns zero reviews, verify the product has a reviews section and the URL is correctly formatted.
- Region-specific Vivino URLs (e.g., `.com/it`, `.com/de`) may have different review counts or accessibility.
- Large `max_items_per_url` values (>500) may increase runtime; consider running multiple smaller jobs.

***

### Use Cases & Business Value

- **Sentiment analysis:** Quantify customer opinions by vintage, region, or price point
- **Competitive benchmarking:** Compare review volumes and average ratings across similar wines
- **Trend research:** Identify emerging preferences (e.g., natural wines, organic) through tagged notes and language patterns
- **Market intelligence:** Monitor reviewer engagement and community reception for new releases
- **Quality control:** Correlate Vivino ratings with sales data to inform purchasing and stocking decisions

The Vivino Reviews Scraper transforms subjective review feedback into quantifiable datasets, unlocking insights that support product decisions, marketing strategies, and consumer understanding.

***

### Conclusion

The **Vivino Reviews Scraper** is a powerful tool for anyone needing structured wine review data at scale. With filtering, sorting, and pagination options built in, it delivers clean, multi-language review records ready for analytics, reporting, or integration into wine platforms. Unlock Vivino's rich review ecosystem and turn consumer feedback into actionable intelligence.

# Actor input Schema

## `urls` (type: `array`):

Add the URLs of the product details urls you want to scrape. You can paste URLs one by one, or use the Bulk edit section to add a prepared list.

## `sort_by` (type: `string`):

Select your option to sort reviews

## `rating` (type: `string`):

Select your option to filter reviews

## `page` (type: `integer`):

The page to start from

## `ignore_url_failures` (type: `boolean`):

If true, the scraper will continue running even if some URLs fail to be scraped.

## `max_items_per_url` (type: `integer`):

The maximum number of items to scrape per URL.

## Actor input object example

```json
{
  "urls": [
    "https://www.vivino.com/en/san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria/w/11890?year=2020&price_id=42539229#all_reviews"
  ],
  "page": 1,
  "ignore_url_failures": true,
  "max_items_per_url": 20
}
```

# 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 = {
    "urls": [
        "https://www.vivino.com/en/san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria/w/11890?year=2020&price_id=42539229#all_reviews"
    ],
    "page": 1,
    "ignore_url_failures": true,
    "max_items_per_url": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("stealth_mode/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 = {
    "urls": ["https://www.vivino.com/en/san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria/w/11890?year=2020&price_id=42539229#all_reviews"],
    "page": 1,
    "ignore_url_failures": True,
    "max_items_per_url": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("stealth_mode/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 '{
  "urls": [
    "https://www.vivino.com/en/san-marzano-sixty-sessantanni-old-vines-primitivo-di-manduria/w/11890?year=2020&price_id=42539229#all_reviews"
  ],
  "page": 1,
  "ignore_url_failures": true,
  "max_items_per_url": 20
}' |
apify call stealth_mode/vivino-reviews-scraper --silent --output-dataset

```

## MCP server setup

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