# Zoover Listings Extractor (`kawsar/zoover-listings-extractor`) Actor

Zoover listings extractor that scrapes hotel and holiday listings by country, region, or city, returning review scores, star ratings, awards, and package prices as clean rows so travel SEO and pricing teams can track the Benelux market without copying data by hand.

- **URL**: https://apify.com/kawsar/zoover-listings-extractor.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** Travel, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 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

## Zoover Listings Extractor: scrape hotel and holiday listings from Zoover

The Zoover listings extractor scrapes hotel and holiday package listings from Zoover with review scores, star ratings, award history, package prices, and flight details on every record. Point it at a country, a region, a city, or a shortlist of properties, and it returns structured JSON you can drop straight into a spreadsheet or a database. It reads the same search that powers zoover.nl and zoover.be, so prices and review counts match what a visitor sees on the site.

Zoover is one of the biggest travel review sites in the Netherlands and Belgium, so it is a solid source for hotel review data and package holiday pricing in the Benelux market.

### Use cases

- **Travel SEO research**: pull review scores, star ratings, and award rankings for every hotel in a destination to see which properties dominate the results you are trying to rank against
- **Package holiday price monitoring**: track price per person for the same hotel and trip length on a schedule, and catch price drops before your competitors do
- **Hotel benchmarking**: compare your property's Zoover score, review count, and aspect ratings against every other hotel in the same city
- **Affiliate and content sites**: build "best hotels in Antalya" style pages from real ratings and prices instead of hand-collected data
- **Market sizing**: use the facet counts to see how many hotels in a country have a pool, a kids club, or a 5 star rating
- **Revenue management**: watch which tour operators, board types, and departure airports are being sold for a destination, and at what price

### Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `brand` | string | `ZVRNL` | Which storefront to search. `ZVRNL` for zoover.nl, `ZVRBE` for zoover.be. |
| `transportType` | string | `INCLUDING_FLIGHT` | `INCLUDING_FLIGHT` returns flight and hotel packages. `OWN` returns accommodation-only stays. |
| `countryIds` | array | `["933"]` | Zoover country IDs, one per line. 933 is Turkey, 919 is Spain, 922 is Greece. |
| `regionIds` | array | empty | Zoover region IDs, for example 4828 for the Turkish Riviera. |
| `cityIds` | array | empty | Zoover city IDs, for example 99048 for Belek. The tightest geographic filter. |
| `entityIds` | array | empty | Specific property IDs, for tracking a fixed shortlist of hotels. |
| `durationNights` | array | `["5","6","7","8","9"]` | Trip lengths in nights, one number per line. |
| `adults` | integer | `2` | Adults travelling. Prices are quoted for this party size. |
| `children` | integer | `0` | Children aged 2 to 17. |
| `babies` | integer | `0` | Infants under 2. |
| `starRatings` | array | empty | Keep only these star ratings. Values 0 to 5. |
| `minReviewScore` | string | empty | Minimum review score out of 10. One of `>=6`, `>=7`, `>=8`, `>=9`. |
| `accommodationTypes` | array | empty | hotel, aparthotel, resort, appartement, villa, bungalow, chalet, camping, and more. |
| `themes` | array | empty | sun\_holiday, city\_trip, child\_friendly, luxe, all\_inclusive, wellness, golf, and more. |
| `attributes` | array | empty | winter\_sun, ski\_holiday, package\_holiday, adult\_only, has\_family\_rooms, and more. |
| `facilities` | array | empty | wifi, pool, kids\_club, restaurant, jacuzzi, waterpark, pets\_allowed, and more. |
| `awards` | array | empty | `gold` or `silver`, to keep only Zoover award winners. |
| `departureAirports` | array | empty | IATA codes such as AMS, RTM, EIN, BRU, DUS. Packages with flight only. |
| `tourOperators` | array | empty | Restrict results to specific operator codes. |
| `sortingOrder` | string | `popularity_desc` | `popularity_desc`, `price`, `price_desc`, `hotel_review_rating`, or `price_quality`. |
| `maxItems` | integer | `100` | Stop after this many listings. |
| `pageSize` | integer | `50` | Listings per API call, up to 500. |
| `startPage` | integer | `1` | Page to begin from, for resuming a run. |
| `includeOffers` | boolean | `true` | Attach the raw offer array with rooms, board, flights, and surcharges. |
| `includeAggregations` | boolean | `false` | Save search facet counts to the key value store under `AGGREGATIONS`. |
| `requestTimeoutSecs` | integer | `30` | Timeout for a single API response. |
| `timeoutSecs` | integer | `300` | Overall time budget for the run. |
| `proxyConfiguration` | object | Datacenter (Anywhere) | Proxy type and location for requests. Supports Datacenter, Residential, Special, and custom proxies. Optional. |

#### Example input

```json
{
    "brand": "ZVRNL",
    "transportType": "INCLUDING_FLIGHT",
    "countryIds": ["933"],
    "durationNights": ["7"],
    "adults": 2,
    "starRatings": ["4", "5"],
    "minReviewScore": ">=8",
    "facilities": ["pool", "kids_club"],
    "sortingOrder": "popularity_desc",
    "maxItems": 100,
    "includeOffers": false,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### What data does this actor extract?

Each dataset record is one property with its cheapest matching offer flattened onto it.

```json
{
    "giataId": 1400605,
    "accommodationId": "1163cee7-775e-4736-8bea-fc23fdcc26fd",
    "entityId": 130137,
    "accoName": "Long Beach",
    "accoType": "hotel",
    "listingUrl": "https://www.zoover.nl/turkije/turkse-riviera/alanya/long-beach-resort",
    "starRating": 5,
    "reviewScore": 9.2,
    "reviewCount": 605,
    "lastReviewDate": "2026-08-10T08:35:27.356000+00:00",
    "aspectRatings": {
        "childFriendly": { "rating": 9.49, "count": 605 },
        "hygiene": { "rating": 9.24, "count": 605 },
        "location": { "rating": 9.18, "count": 605 },
        "priceQuality": { "rating": 9.07, "count": 605 },
        "room": { "rating": 9.07, "count": 605 },
        "service": { "rating": 9.19, "count": 605 }
    },
    "latestAwardYear": "2025",
    "latestAwardType": "gold",
    "latestAwardRank": 200,
    "country": "Turkije",
    "countryCode": "TR",
    "regionName": "Turkse Rivièra",
    "cityName": "Alanya",
    "cityId": 52799,
    "currency": "EUR",
    "bestPricePerPerson": 777.25,
    "bestPriceTotal": 1554.5,
    "mealPlan": "AI",
    "boardName": "all inclusief",
    "roomDescription": "Tweepersoonskamer - voordeel",
    "durationNights": 5,
    "departureDate": "2026-11-01",
    "returnDate": "2026-11-06",
    "departureAirport": "AMS",
    "arrivalAirport": "AYT",
    "airline": "Corendon Dutch Airlines B.V.",
    "flightNumber": "CD 5099",
    "tourOperator": "VAKNLB2C",
    "searchRank": 1,
    "resultsTotal": 34,
    "scrapedAt": "2026-08-10T10:51:50.254715+00:00"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `giataId` | integer | GIATA property ID, stable across travel suppliers, useful for joining with other hotel datasets |
| `accommodationId` | string | Zoover internal UUID for the property |
| `entityId` | integer | Zoover entity ID, reusable as an `entityIds` input value |
| `accoName` | string | Property name |
| `accoType` | string | hotel, aparthotel, resort, villa, camping, and so on |
| `listingUrl` | string | Direct link to the property page on Zoover |
| `slug` / `fullSlug` | string | URL slug and full destination path |
| `previewImage` | string | Main listing photo |
| `starRating` | integer | Official star rating, 0 to 5 |
| `reviewScore` | number | Average Zoover review score out of 10 |
| `reviewCount` | integer | Number of reviews behind the score |
| `lastReviewDate` | string | Timestamp of the most recent review |
| `aspectRatings` | object | Sub-scores for hygiene, location, room, service, price quality, and child friendliness |
| `travellerRatings` | object | Scores split by couples, families, friends, solo travellers, and business |
| `awardHistory` | object | Every Zoover award year with tier and rank |
| `latestAwardYear` / `latestAwardType` / `latestAwardRank` | string, string, integer | Most recent award, flattened for easy sorting |
| `country` / `countryCode` / `countryEntityId` | string, string, integer | Country name, ISO code, and reusable filter ID |
| `regionName` / `regionId` | string, integer | Region and its reusable filter ID |
| `cityName` / `cityId` | string, integer | City and its reusable filter ID |
| `isBookable` | boolean | Whether the property is bookable on Zoover right now |
| `offerCount` | integer | How many offers the search returned for this property |
| `currency` | string | Currency of all price fields |
| `bestPricePerPerson` | number | Cheapest price per person for the searched party and trip length |
| `bestPriceTotal` | number | Cheapest total package price |
| `priceBeforeDiscount` | number | Total before discounts, so you can spot real markdowns |
| `mealPlan` / `boardName` | string | Board code and its description, for example AI and all inclusief |
| `roomDescription` | string | Room or unit type sold with the cheapest offer |
| `durationNights` / `durationDays` | integer | Length of the cheapest offer |
| `departureDate` / `returnDate` | string | Travel dates, or check-in and check-out for accommodation-only stays |
| `departureAirport` / `arrivalAirport` | string | IATA codes for the outbound flight |
| `airline` / `flightNumber` / `stopOver` | string, string, integer | Outbound flight details |
| `luggageIncluded` | boolean | Whether checked luggage is in the package price |
| `tourOperator` / `supplier` / `productCode` | string | Who sells the package and under which code |
| `offers` | array | Raw offers with rooms, board, flight segments, surcharges, and funds |
| `searchRank` | integer | Position in the sorted search results, starting at 1 |
| `pageNumber` | integer | Search page the listing came from |
| `resultsTotal` | integer | How many listings matched the search |
| `scrapedAt` | string | When the record was collected |

### How it works

1. Your filters are turned into a single search query against the Zoover search backend, the same one the website calls.
2. The actor pages through the sorted results, pulling up to 500 listings per request.
3. Each result is flattened: property details, review breakdown, award history, and the cheapest offer become one record.
4. Prices arrive in cents and are converted to normal euro amounts.
5. Records are pushed to the dataset in batches while a running time budget keeps the run from overshooting.
6. If facet counts are enabled, they are saved once to the key value store under `AGGREGATIONS`.

### FAQ

**How many listings can I get in one run?**
The Zoover search backend returns at most 500 matches for any single query, no matter how many exist. To go past that, split the run by region or city and merge the datasets. Each record carries `resultsTotal` so you can tell when you have hit the ceiling.

**Where do I find the country, region, and city IDs?**
Every record includes `countryEntityId`, `regionId`, and `cityId`. Run one broad search, read the IDs off the results, then feed them back in to drill down. The IDs also appear as `heliosId` values on Zoover destination pages.

**Can I scrape accommodation-only stays without flights?**
Yes. Set `transportType` to `OWN`. You get campsites, apartments, and holiday parks with a nightly package price and no flight fields.

**Do the prices include everything?**
`bestPriceTotal` is the package total for the party you searched. Some surcharges and local taxes are paid on arrival and appear inside the raw `offers` array rather than in the headline price.

**Why is my dataset so large?**
`includeOffers` is on by default and the raw offers contain full flight segments and supplier text. Turn it off for a flat, compact dataset.

**Can I run this on a schedule?**
Yes. Schedule the actor daily or weekly and the same query returns fresh prices and review counts each time, which is how you build a price history.

### Integrations

Connect Zoover Listings Extractor with other apps and services using [Apify integrations](https://apify.com/integrations). You can integrate with Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive, and many more. You can also use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger actions whenever results are available.

### Start scraping Zoover listings

Set a country ID, pick a trip length, and run it. You get a clean table of Zoover hotel listings with review scores, award rankings, and package prices, ready for an SEO audit or a price tracker.

# Actor input Schema

## `brand` (type: `string`):

Which Zoover storefront to search. ZVRNL returns Dutch listings and prices, ZVRBE returns the Belgian catalogue.

## `transportType` (type: `string`):

INCLUDING\_FLIGHT returns flight and hotel packages. OWN returns accommodation-only stays where the traveller arranges transport.

## `countryIds` (type: `array`):

Zoover destination IDs for countries, one per line. Example: 933 is Turkey, 919 is Spain, 922 is Greece. Find the ID in the heliosId value of any destination page. Leave empty to search every country.

## `regionIds` (type: `array`):

Zoover region IDs, one per line. Example: 4828 is the Turkish Riviera. Use this to target a coastline or province instead of a whole country.

## `cityIds` (type: `array`):

Zoover city IDs, one per line. Example: 99048 is Belek. This is the tightest geographic filter and usually returns well under 100 properties.

## `entityIds` (type: `array`):

Pull specific properties by their Zoover entity ID, one per line. Useful for tracking prices on a fixed shortlist of hotels.

## `durationNights` (type: `array`):

How many nights the trip should last, one number per line. Add several values to widen the search. Defaults to 5 through 9 nights.

## `adults` (type: `integer`):

Number of adults travelling. Prices are quoted for this party size.

## `children` (type: `integer`):

Number of children aged 2 to 17 travelling.

## `babies` (type: `integer`):

Number of infants under 2 travelling.

## `starRatings` (type: `array`):

Keep only properties with these star ratings, one per line. Allowed values: 0, 1, 2, 3, 4, 5.

## `minReviewScore` (type: `string`):

Keep only properties at or above this Zoover review score out of 10.

## `accommodationTypes` (type: `array`):

One type per line. Allowed values: hotel, aparthotel, resort, appartement, villa, bungalow, chalet, camping, bungalow\_tent, bed\_and\_breakfast, pension, hostel, gasthof, country\_house, castle, lodge, vakation\_house, other.

## `themes` (type: `array`):

One theme per line. Allowed values: city\_trip, sun\_holiday, child\_friendly, luxe, all\_inclusive, boutique, aqua\_park, distant\_destination, adult\_only, budget, small\_scale, wellness, golf, workation.

## `attributes` (type: `array`):

One attribute per line. Allowed values: city\_trip, sun\_holiday, child\_friendly, luxe, boutique, aqua\_park, distant\_destination, adult\_only, budget, small\_scale, wellness, golf, workation, package\_holiday, car\_holiday, winter\_sun, ski\_holiday, children\_deals, has\_family\_rooms.

## `facilities` (type: `array`):

One facility per line. Allowed values: wifi, airco, playground, entertainment, restaurant, accessibility, pets\_allowed, pool, jacuzzi, childrens\_pool, waterpark, family\_room, baby\_cot, kids\_club, gameroom, sport\_facilities.

## `awards` (type: `array`):

Keep only award winners. One per line, either gold or silver. Award winners are the highest rated properties in their destination.

## `departureAirports` (type: `array`):

IATA codes, one per line, applied only when transport type is a package with flight. Allowed values: AMS, ANR, BRU, CGN, CRL, DTM, DUS, EIN, FMO, GRQ, MST, NRN, RTM.

## `tourOperators` (type: `array`):

Operator codes, one per line, to restrict which supplier the package comes from.

## `sortingOrder` (type: `string`):

Order the search results before they are collected. Popularity mirrors the default order on the Zoover website.

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

Stop after this many listings. Keeps runs cheap and predictable.

## `pageSize` (type: `integer`):

How many listings to pull per API call. Larger pages mean fewer requests and faster runs.

## `startPage` (type: `integer`):

Page number to begin from. Set this above 1 to resume a run or to skip results you already have.

## `includeOffers` (type: `boolean`):

Attach the raw offer array to every listing, with room codes, board types, flight segments, surcharges, and fund breakdowns. Turn this off for a smaller, flatter dataset.

## `includeAggregations` (type: `boolean`):

Store the search facet counts (star ratings, themes, facilities, regions, award winners) in the key value store under AGGREGATIONS. Handy for keyword research and market sizing.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for a single API response before giving up on it.

## `timeoutSecs` (type: `integer`):

Overall time budget for the run. The actor stops paginating and finishes cleanly once this is reached.

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

Select proxies to use for requests. Helps avoid IP blocking and rate limits. Datacenter proxies are fastest; Residential proxies are harder to detect.

## Actor input object example

```json
{
  "brand": "ZVRNL",
  "transportType": "INCLUDING_FLIGHT",
  "countryIds": [
    "933"
  ],
  "regionIds": [
    "4828"
  ],
  "cityIds": [
    "99048"
  ],
  "entityIds": [
    "475371"
  ],
  "durationNights": [
    "7"
  ],
  "adults": 2,
  "children": 0,
  "babies": 0,
  "starRatings": [
    "4",
    "5"
  ],
  "minReviewScore": "",
  "accommodationTypes": [
    "hotel",
    "resort"
  ],
  "themes": [
    "sun_holiday"
  ],
  "attributes": [
    "winter_sun"
  ],
  "facilities": [
    "pool",
    "kids_club"
  ],
  "awards": [
    "gold"
  ],
  "departureAirports": [
    "AMS",
    "RTM"
  ],
  "tourOperators": [
    "VAKNLB2C"
  ],
  "sortingOrder": "popularity_desc",
  "maxItems": 100,
  "pageSize": 50,
  "startPage": 1,
  "includeOffers": true,
  "includeAggregations": false,
  "requestTimeoutSecs": 30,
  "timeoutSecs": 300,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

All extracted Zoover listings as dataset items.

## `listingsCsv` (type: `string`):

All extracted listings exported as a CSV file.

## `runLog` (type: `string`):

Live log for this run.

# 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 = {
    "brand": "ZVRNL",
    "transportType": "INCLUDING_FLIGHT",
    "countryIds": [
        "933"
    ],
    "durationNights": [
        "5",
        "6",
        "7",
        "8",
        "9"
    ],
    "adults": 2,
    "sortingOrder": "popularity_desc",
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/zoover-listings-extractor").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 = {
    "brand": "ZVRNL",
    "transportType": "INCLUDING_FLIGHT",
    "countryIds": ["933"],
    "durationNights": [
        "5",
        "6",
        "7",
        "8",
        "9",
    ],
    "adults": 2,
    "sortingOrder": "popularity_desc",
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kawsar/zoover-listings-extractor").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 '{
  "brand": "ZVRNL",
  "transportType": "INCLUDING_FLIGHT",
  "countryIds": [
    "933"
  ],
  "durationNights": [
    "5",
    "6",
    "7",
    "8",
    "9"
  ],
  "adults": 2,
  "sortingOrder": "popularity_desc",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kawsar/zoover-listings-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kawsar/zoover-listings-extractor"
        }
    }
}

```

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/hDHKdE5a0UxWqPpi1/builds/tvgiaFzFlhqfGnP84/openapi.json
