# Zoover Reviews Scraper — Hotel Guest Reviews & Ratings (`kestrel/zoover-reviews-scraper`) Actor

Every Zoover.nl guest review of any hotel, campsite or apartment: the 1-10 score, title, full Dutch review text, per-aspect scores, travel party, travel date, reviewer and the owner's reply. Give Zoover accommodation URLs or ids. No browser, no login. Pay per review.

- **URL**: https://apify.com/kestrel/zoover-reviews-scraper.md
- **Developed by:** [Tedj MEABIOU](https://apify.com/kestrel) (community)
- **Categories:** Travel, AI, Automation
- **Stats:** 2 total users, 1 monthly users, 94.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 review rows

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

## Zoover Reviews Scraper — hotel guest reviews and ratings

This Zoover reviews scraper turns any accommodation page on **Zoover.nl** into structured rows: one per guest review, with the 1-10 score, the title, the full text, the per-aspect scores, the travel party, the travel date, the reviewer and the owner's reply. As a hotel reviews scraper it reads Zoover hotel reviews, camping reviews, bungalow-park reviews and apartment reviews the same way, so you can pull guest reviews for a whole portfolio in one run. No browser, no login, no Zoover api key — just accommodation URLs or ids in, hotel reviews out, billed per delivered review.

Zoover is the review site Dutch and Flemish holidaymakers actually write on, and its reviews are graded 1-10 with a separate score for the room, the service, the location, the hygiene and the price/quality ratio. That makes it the sharpest source of dutch hotel reviews there is — and the one place where a Mediterranean resort's Dutch-language guest feedback lives.

**Last verified working: 2026-08-29.**

### What does this Zoover reviews scraper do?

Give it accommodation URLs (`https://www.zoover.nl/a/91488/esperos-blue-village-spa`) or ids, and every run produces three kinds of dataset row:

| Row `type` | What it is | Cost |
|---|---|---|
| `review` | One guest review, with everything Zoover holds about it | $0.004 |
| `accommodation` | One context row per property: ids, star rating, Zoover guest rating, aspect averages, place, chain, contact | free |
| `status` | One row per input: what happened, how many reviews were delivered, how many the filters dropped | free |

The important part is the billing rule: **you are charged for exactly the review rows delivered to your dataset**. Filters run before billing, a property with no reviews costs nothing, an unknown id costs nothing, and a run that hits your spending limit stops delivering rather than delivering rows you did not pay for.

### Zoover review fields: what do you get from each review?

Every `review` row carries these fields:

| Field | Description |
|---|---|
| `review_id` | Zoover's review id (a uuid). Legacy rows without one get `h<review_legacy_id>`, stable across runs |
| `review_legacy_id` | Zoover's numeric id of the review itself |
| `accommodation_id` | The property's internal id (uuid) — feed it back to skip the page read |
| `helios_id` | The number in the accommodation URL `/a/<number>/…` |
| `accommodation_name` | Property name as Zoover shows it |
| `accommodation_url` | The property's page on zoover.nl |
| `title` | Review title as the guest wrote it |
| `text` | Full review text |
| `text_length` | Characters of review text, as Zoover counts them |
| `score` | The guest's overall score, 1-10 (10 is best) |
| `aspects` | Scores per aspect, 1-10: `room`, `food`, `service`, `location`, `hygiene`, `pool`, `childFriendly`, `priceQuality`, `general` |
| `locale` | Language the review was written in (`nl`, `de`, …) |
| `traveled_with` | `COUPLE`, `FAMILY_WITH_YOUNG_CHILDREN`, `FAMILY_WITH_OLDER_CHILDREN`, `FRIENDS`, `SINGLE`, `BUSINESS`, `GROUP` |
| `review_date` / `review_datetime` | When the review was published (date and ISO timestamp) |
| `updated_date` | When the guest last edited it |
| `travel_date` | Month of the stay |
| `reviewer_name` | Reviewer display name |
| `reviewer_verified` | Whether Zoover marks the reviewer as verified |
| `reviewer_level` | Zoover's reviewer badge, when the profile has one |
| `likes` | Helpful votes the review received |
| `photos` / `photo_count` | Guest photo URLs (rewritten to fetchable links) and how many |
| `response` | The owner's reply, in full |
| `response_date` / `response_author` / `response_position` | When it was written, who signed it, their role (e.g. `Owner`) |
| `target` | The input value this row came from |
| `fetched_at` | When the row was read, ISO 8601 UTC |

The free `accommodation` row adds `giata_id`, `accommodation_type`, `star_rating`, `rating` (Zoover's overall guest rating), `review_count`, `aspect_ratings` (the property's average per aspect), `country`, `region`, `city`, `chain`, `phone`, `email`, `address`, `postal_code`, `website`, `image`, `bookable`, `reviews_listed`, `reviews_fetched`, plus this run's own tallies `scores` (reviews per score) and `travel_parties` (reviews per party).

The free `status` row carries `status`, `reviews`, `filtered`, `pages`, `total`, `duplicates` and `error` — so a scheduled run can be audited without reading a single review.

### How do you point the scraper at an accommodation?

Three ways, and you can mix them in one run:

1. **`startUrls`** — full accommodation URLs. Only the number after `/a/` matters; the slug can be wrong or missing.
2. **`accommodationIds`** — the same number on its own (`91488`). Zoover calls it the heliosId.
3. **`accommodationIds`** with a **uuid** — the Zoover accommodation id (`accommodation_id`) from an earlier run (`9c471493-27a9-4dfc-a0e5-60ec206b3b62`). This is the fast path: the uuid *is* the key Zoover's own review endpoint takes, so the run skips the page read entirely. A uuid has no page, so it produces no `accommodation` row.

A URL, its number and its uuid are recognised as the same property: one is scraped, the others come back as free `duplicate` status rows. An id Zoover does not know is a free `not_found` row, never an invented result.

```json
{
  "startUrls": ["https://www.zoover.nl/a/91488/esperos-blue-village-spa"],
  "accommodationIds": ["83376", "9c471493-27a9-4dfc-a0e5-60ec206b3b62"],
  "maxReviewsPerAccommodation": 0,
  "includeAccommodationRow": true
}
```

### Review filters: which ones keep your Zoover review data bill down?

Every filter runs **before** billing, so a filtered review is a review you never pay for:

- `maxReviewsPerAccommodation` — `0` takes every review the property has; `N` takes the newest N. It becomes the page size too, so a cap of 6 costs exactly one request.
- `maxRating` — keep only reviews scoring at or below this on the 1-10 scale. `6` is the complaints feed, and the fastest way to find zoover negative reviews.
- `minRating` — keep only reviews scoring at or above this. `9` is the testimonial feed. Combine the two for a band (5 to 7 = the lukewarm middle where churn hides).
- `requireText` — drop score-only reviews.
- `sinceDate` — `2026-01-01`, or relative (`30 days`, `6 months`, `2 years`) so a schedule never goes stale. Reviews come newest first, so the run stops paging once a whole page predates the cut.

```json
{
  "accommodationIds": ["91488", "83376"],
  "maxRating": 6,
  "requireText": true,
  "sinceDate": "12 months"
}
```

### How much does it cost?

$0.004 per review row. Nothing else is charged: `accommodation` rows, `status` rows, properties with no reviews, unknown ids, duplicate inputs and every filtered review are free. A typical Zoover property delivers a handful of reviews, so a hundred properties usually land between $0.02 and $0.40 for the whole sweep — and if a property turns out to be empty, that property cost you nothing at all.

There is no per-run start fee and no per-dataset-item fee, which matters when you are sweeping hundreds of properties that may each hold nothing.

### How many reviews does a Zoover property have?

Fewer than you would guess, and you should plan for it. In a measured sample of accommodations taken from Zoover's own sitemap on 2026-08-29, review counts ran 0, 0, 0, 0, 0, 0, 0, 1, 4, 4, 6, 11, 16, 23 — most properties had **none at all**, and the busiest held 23. Zoover's catalogue is large (32,504 accommodation URLs in its sitemap) and its review depth is shallow.

So use this scraper the way it is built to be used: **feed it lists of properties**, not one property expecting thousands of rows. A destination sweep of 500 hotels is a normal run; "all reviews of one resort" is a run that finishes in two seconds. Because empty properties are free, a wide sweep is cheap — you only pay where the reviews actually are.

### Zoover in the Dutch and Belgian market — why this review data is different

Zoover is a Dutch review platform (with a Belgian sibling) whose audience is Dutch and Flemish package-holiday travellers, plus German visitors on its sister sites. That gives Zoover review data three properties no global site has:

- **Language.** These are Dutch-language guest reviews, mostly `locale: "nl"`. If you monitor a Spanish, Greek or Turkish resort, this is where its Dutch-speaking guests speak — and their complaints rarely appear on the English-language sites.
- **The 1-10 grade with aspects.** Zoover ratings are not stars. Every review can score the room, food, service, location, hygiene, pool, child friendliness, price/quality and a general mark, all on 1-10. That is a ready-made feature vector for hotel sentiment analysis, no NLP required.
- **Package-holiday inventory.** Zoover covers campings, bungalow parks and apartment resorts that global OTAs list thinly or not at all, so zoover camping reviews and holiday-park feedback have no substitute elsewhere.

For a hotel that sells into the Benelux, this is the missing half of hotel reputation management: review monitoring in the language the guests complained in.

### How do you scrape Zoover reviews from Python, JavaScript or curl?

Python, with the Apify client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("kestrel/zoover-reviews-scraper").call(run_input={
    "startUrls": ["https://www.zoover.nl/a/91488/esperos-blue-village-spa"],
    "maxReviewsPerAccommodation": 0,
    "maxRating": 6,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "review":
        print(row["score"], row["review_date"], row["title"])
```

JavaScript (Node):

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('kestrel/zoover-reviews-scraper').call({
    accommodationIds: ['91488', '83376'],
    sinceDate: '12 months',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => i.type === 'review').length, 'reviews');
```

curl — start a run and read the dataset:

```bash
curl -X POST "https://api.apify.com/v2/acts/kestrel~zoover-reviews-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"startUrls":["https://www.zoover.nl/a/91488/esperos-blue-village-spa"],"maxReviewsPerAccommodation":0}'

curl "https://api.apify.com/v2/acts/kestrel~zoover-reviews-scraper/runs/last/dataset/items?token=$APIFY_TOKEN&format=csv&clean=1" > zoover-reviews.csv
```

That last line is also how you download Zoover reviews as CSV: the dataset exports to zoover reviews csv, JSON, XLSX or XML from the same endpoint, or with one click in the Apify console.

### How do you use it with n8n, Make and AI agents?

- **n8n** — the Apify node runs the actor and hands the dataset straight into your workflow; use "Run actor and get dataset" and filter on `type == "review"`.
- **Make** — the Apify app has a "Run an actor" module; chain it into Google Sheets, Slack or a database in the usual way.
- **MCP / AI agents** — the actor is callable over Apify's MCP server, so an agent can ask for a property's reviews as a tool call and reason over the returned rows. Its input schema is the tool schema; nothing extra to write.
- **Scheduling** — set `sinceDate` to `7 days` and a daily schedule, and each run reads only the new reviews.

### Input reference

| Input | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array | `[]` | Zoover accommodation URLs |
| `accommodationIds` | array | `[]` | The number from `/a/<number>/…`, or an `accommodation_id` uuid |
| `maxReviewsPerAccommodation` | integer | `0` | `0` = all; `N` = newest N |
| `maxRating` | number | `0` | Keep reviews scoring ≤ this (1-10); `0` = off |
| `minRating` | number | `0` | Keep reviews scoring ≥ this (1-10); `0` = off |
| `requireText` | boolean | `false` | Drop score-only reviews |
| `sinceDate` | string | `""` | `YYYY-MM-DD` or relative (`30 days`) |
| `includeAccommodationRow` | boolean | `true` | Emit the free property context row |
| `sessions` | integer | `2` | Parallel proxy sessions (egress IPs) |
| `perIp` | number | `1` | Requests per second per session |
| `proxyConfiguration` | object | Apify Proxy | Datacenter is enough; residential works too |

At least one of `startUrls` or `accommodationIds` is required. Bad input fails the run immediately, before anything is fetched or charged.

### Output reference — the dataset views

The dataset ships with five ready-made views, so you rarely need to write a transformation:

- **Overview** — `type`, `accommodation_name`, `score`, `title`, `text`, `review_date`, `traveled_with`, `status`.
- **Reviews** — every review field worth reading at a glance, including `aspects`, `locale`, `travel_date`, `reviewer_name`, `likes`, `photo_count`, `response` and `accommodation_url`.
- **Complaints** — the same, ordered around the low scores and the `response_date` of the owner's reply.
- **Accommodations** — `accommodation_id`, `helios_id`, `accommodation_name`, `accommodation_type`, `star_rating`, `rating`, `review_count`, `aspect_ratings`, `scores`, `travel_parties`, `city`, `region`, `country`, `reviews_listed`, `reviews_fetched`.
- **Status** — `target`, `accommodation_id`, `helios_id`, `accommodation_name`, `status`, `reviews`, `filtered`, `pages`, `total`, `duplicates`, `error`.

Every run also writes a `SUMMARY` record to the key-value store with the counts it delivered and charged, so a monitoring job can check one JSON object instead of a dataset.

### Is scraping Zoover legal?

This actor reads two public things: the accommodation page any visitor can open, and `POST /api/getReviews` — the JSON endpoint Zoover's own `robots.txt` explicitly **allows** (`Allow: /api/getReviews`, above its `Disallow: /api`). Nothing here is behind a login, a paywall or a personalisation cookie.

That is not legal advice. Reviews are user-generated content: the text belongs to its author and Zoover's terms govern reuse. Guest names are personal data under the GDPR, so treat `reviewer_name` accordingly, keep only what you need, and give it a retention period. Aggregate analysis of public reviews — reputation monitoring, competitive benchmarking, sentiment work — is the normal use; republishing scraped review text as if it were yours is not. If you are unsure, ask your own counsel.

### How is this different from the other Zoover scrapers?

- **Charged equals delivered.** One event, `review`, priced at $0.004, charged only for rows actually written to your dataset. No per-start fee, no per-dataset-item fee on free context rows.
- **Empty properties are free.** On a site where most accommodations hold no reviews, that is the difference between a cheap 500-property sweep and a bill for nothing.
- **A refusal is never reported as "no reviews".** A Cloudflare block, a throttle or a `400` from the API becomes `status: "error"` with the reason. An empty property is `no_reviews`; an unknown id is `not_found`. Three different answers, three different words.
- **It sends the page size Zoover requires.** The review endpoint quietly returns *one* review when the request omits its `size` — while still reporting the true total. A scraper that trips over that under-delivers and looks fine doing it. This one always sends it, and pages the cursor to the end.
- **The uuid fast path.** No other Zoover scraper takes the internal id as input. Store `accommodation_id` once and later runs skip the page fetch entirely — cheaper, faster and one less thing to be blocked on.

### FAQ

#### Do I need a Zoover API key?

No. There is no public Zoover api to sign up for. The actor calls the same endpoint the website's own front end calls, through Apify Proxy, so you get zoover reviews without api credentials of any kind.

#### Can I scrape Zoover reviews by hotel name?

Not directly — targets are URLs or ids. Search zoover.nl for the property, copy the URL from the address bar, and paste it into `startUrls`. Once a run has read it, keep the `accommodation_id` and use that for every later refresh.

#### How do I get the reviews of many hotels at once?

Put every URL in `startUrls` or every number in `accommodationIds` — hundreds are fine in one run. That is how bulk hotel reviews are meant to be collected here, and it is why the empty properties being free matters so much.

#### What language are the reviews in?

Mostly Dutch (`locale: "nl"`), which is the point: these are dutch travel reviews written by the guests who booked from the Netherlands and Belgium. The field is on every row, so you can split by language before you translate.

#### Does it include the hotel's replies?

Yes. Zoover owner replies come back in `response`, in full, with `response_date`, `response_author` and `response_position`. They are part of the review row, at no extra cost.

#### How fast is it, and will Zoover block me?

One accommodation page plus one review request per property, paced at one request per second per session (raise `sessions` to go wider). A paced probe of ten different properties on one datacenter session returned ten of ten, and the actor rotates its proxy session on any refusal and retries.

#### What happens when a property has no reviews?

You get a free `status` row with `status: "no_reviews"` and `total: 0`, and an `accommodation` row with the property's details. Nothing is charged. The run does not fail — that is the normal answer on this site.

#### Can I get zoover guest feedback into a spreadsheet?

Yes — export the dataset as CSV or XLSX from the run page, or hit the dataset API with `format=csv`. Every field in the tables above becomes a column.

### Related scrapers

Same billing model, same row shapes, other sources:

- [Booking.com Reviews Scraper](https://apify.com/kestrel/booking-reviews-scraper) — the global OTA counterpart, with the same charged-equals-delivered rule.
- [TripAdvisor Reviews Scraper](https://apify.com/kestrel/tripadvisor-reviews-scraper) — up to 30 site languages, sub-ratings and management responses.
- [Kurzurlaub Reviews Scraper](https://apify.com/kestrel/kurzurlaub-reviews-scraper) — the German short-break market, the closest sibling to this one.
- [HRS Reviews Scraper](https://apify.com/kestrel/hrs-reviews-scraper) — German business-travel hotel reviews from HRS with twelve category votes and the hotel's replies, the corporate counterpart to Zoover's holiday guests.
- [Agoda Reviews Scraper](https://apify.com/kestrel/agoda-reviews-scraper) — Agoda guest reviews with separate positives and negatives and the hotel's reply, by hotel name, URL or id.
- [Google Hotels Prices Scraper](https://apify.com/kestrel/google-hotels-prices) — what the same properties charge: every booking site's rate for a stay as its own row, for the price behind the score.

Run them over the same portfolio and you have the Dutch, German and global guest voice of every property in one dataset shape.

# Changelog

This Actor's version history is a separate document: https://apify.com/kestrel/zoover-reviews-scraper/changelog.md

# Actor input Schema

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

Accommodation pages on Zoover, e.g. https://www.zoover.nl/a/91488/esperos-blue-village-spa — only the number after /a/ counts, the slug does not have to be right. Any query string is fine.

## `accommodationIds` (type: `array`):

The number in /a/<number>/… (Zoover calls it the heliosId), e.g. 91488 — or the internal accommodation id (uuid) an earlier run put in accommodation\_id, e.g. 9c471493-27a9-4dfc-a0e5-60ec206b3b62. A uuid is the fastest path: it is the key the review API takes, so the run skips the page read (and, having no page, gets no accommodation row).

## `maxReviewsPerAccommodation` (type: `integer`):

0 = every review the property has (50 per request; Zoover properties rarely hold more than a few dozen, so 0 is normally right and cheap). N = the newest N. The main cost control.

## `maxRating` (type: `number`):

0 = keep every review. 1-10 = keep only reviews whose overall score is that number or lower — 6 gives a complaints feed on Zoover's 1-10 scale (10 is best). Filtered reviews are never charged.

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

0 = keep every review. 1-10 = keep only reviews whose overall score is that number or higher — 9 gives the testimonials. Combine with the maximum for a band (e.g. 5 to 7). Filtered reviews are never charged.

## `requireText` (type: `boolean`):

Drop score-only reviews before billing. Zoover reviews almost always carry text, so this rarely removes much.

## `sinceDate` (type: `string`):

YYYY-MM-DD, or relative so schedules never go stale: "30 days", "6 months", "2 years". Reviews come newest first, so the run stops paging once a whole page predates the date. Empty = no date limit.

## `includeAccommodationRow` (type: `boolean`):

Also emit one free row per property with its ids, name, star rating, the Zoover guest rating and review count, the seven aspect ratings, its place, chain, address and contact details, plus this run's tally of reviews per score and per travel party. Never charged.

## `sessions` (type: `integer`):

How many Apify Proxy sessions (egress IPs) run in parallel. More is faster; each is paced separately.

## `perIp` (type: `number`):

Pace for each session. Zoover serves 1 request/s per IP steadily (10 of 10 accommodation pages in a paced probe); raising it causes rotations, not speed.

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

Apify Proxy with the default datacenter group is enough: Zoover's Cloudflare gate reads the TLS fingerprint, not the IP, and this actor's client passes it. Residential works too but costs more. Keep the default.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.zoover.nl/a/91488/esperos-blue-village-spa"
  ],
  "accommodationIds": [],
  "maxReviewsPerAccommodation": 0,
  "maxRating": 0,
  "minRating": 0,
  "requireText": false,
  "sinceDate": "",
  "includeAccommodationRow": true,
  "sessions": 2,
  "perIp": 1,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per guest review, plus per-accommodation context and status rows. Charged rows are billed as delivered; accommodation and status rows are always free.

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

One JSON record with the counts this run delivered and charged, its error, not-found and duplicate tallies, and its HTTP stats.

# 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": [
        "https://www.zoover.nl/a/91488/esperos-blue-village-spa"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kestrel/zoover-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": ["https://www.zoover.nl/a/91488/esperos-blue-village-spa"] }

# Run the Actor and wait for it to finish
run = client.actor("kestrel/zoover-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": [
    "https://www.zoover.nl/a/91488/esperos-blue-village-spa"
  ]
}' |
apify call kestrel/zoover-reviews-scraper --silent --output-dataset

```

## MCP server setup

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