# Klook Hotels Scraper (`shahidirfan/klook-hotels-scraper`) Actor

Extract Klook hotel listings with hotel names, prices, ratings, reviews, locations, room details, amenities, discounts, images, and booking URLs. Ideal for hotel price monitoring, travel market research, competitor analysis, accommodation datasets, and travel apps.

- **URL**: https://apify.com/shahidirfan/klook-hotels-scraper.md
- **Developed by:** [Shahid Irfan](https://apify.com/shahidirfan) (community)
- **Stats:** 3 total users, 3 monthly users, 87.1% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 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?

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

### What does Klook Hotels Listing Scraper do?

Klook Hotels Listing Scraper collects hotel listings from Klook search results for destination research, hotel comparisons, and price monitoring. Enter a Klook hotel search URL or a location to receive property names, hotel links, star ratings, guest ratings, prices, images, coordinates, and listing features.

Each dataset row represents one hotel. You can download results as JSON, CSV, Excel, or XML, schedule repeat runs, and access datasets through the Apify API. This Actor collects listing data, not individual guest reviews or a hotel's full room inventory.

### Why use Klook Hotels Listing Scraper?

- **Compare properties across a destination** - Collect hotel names, star categories, guest ratings, and location descriptions in one dataset.
- **Monitor advertised hotel prices** - Keep currency, availability, price descriptions, and the stay dates associated with each listing.
- **Research hotel positioning** - Compare features such as swimming pools, fitness facilities, and business centers when Klook publishes them.
- **Create travel datasets** - Export hotel links, property images, city and country information, and geographic coordinates.
- **Control collection size** - Set an exact maximum result count and a page limit. Duplicate properties within a run are excluded.
- **Keep exports clean** - Unavailable fields are omitted rather than written as null placeholders. Numeric zero and boolean false are retained.

### What data can you extract from Klook?

| Data                   | Fields                                                                           |
| ---------------------- | -------------------------------------------------------------------------------- |
| Hotel identity         | `hotel_id`, `name`, `hotel_url`, `product_id`                                    |
| Hotel quality          | `stars`, `rating`, `rating_max`, `rating_label`, `review_count_text`             |
| Destination            | `city`, `country`, `city_id`, `country_id`, `latitude`, `longitude`, `time_zone` |
| Listing details        | `location_description`, `images`, `features`, `booking_popularity`               |
| Price and availability | `price`, `formatted_price`, `currency`, `currency_symbol`, `available`           |
| Stay context           | `check_in`, `check_out`, `suggested_dates`, `price_date_description`             |
| Collection context     | `locale`, `page`, `position`, `total_properties`, `scraped_at`                   |

Klook may also publish promotions, tax descriptions, stock messages, pay-later descriptions, or reward information. These are included only when present. Listing features are not a complete inventory of hotel amenities.

### How to scrape Klook hotel listings

1. Open the Actor input form in Apify Console.
2. Enter a hotel listing URL in `startUrl`, or enter a destination in `location`.
3. Optionally specify stay dates, occupancy, and guest-rating or recommended sorting.
4. Set `resultsWanted` and `maxPages`.
5. Review the proxy settings and start the run.
6. Open the dataset preview, then download the results or connect them to your workflow.

With no search input, the Actor searches Dubai. A supplied `startUrl` takes priority over `location`. Explicit dates, occupancy, and supported sorting inputs override the corresponding URL options. There is no raw filter or currency input. URL filter selections are preserved; budget filtering and price ordering are not guaranteed by Klook. Options you leave unset preserve the URL values.

### Input Parameters

| Parameter            | Type          | Default                    | Description                                                                          |
| -------------------- | ------------- | -------------------------- | ------------------------------------------------------------------------------------ |
| `startUrl`           | String        | None                       | Klook `hotels/searchresult/` listing URL. Takes priority over location.              |
| `location`           | String        | `Dubai`                    | Destination name used when no URL is supplied.                                       |
| `checkIn`            | String        | URL value or unset         | Check-in date in `YYYY-MM-DD` format.                                                |
| `checkOut`           | String        | URL value or unset         | Check-out date after check-in. Supply both dates together.                           |
| `adults`             | Integer       | URL value or `2`           | Adult occupancy, at least 1.                                                         |
| `rooms`              | Integer       | URL value or `1`           | Number of rooms, at least 1.                                                         |
| `childAges` | Integer | URL ages or no children | Optional age from 0 to 17 for one child. Use a listing URL for multiple children. |

| `sortBy`             | String        | URL sorting or Klook order | `hotel_score` (recommended) or `review_score` (guest rating, highest first).                         |
| `resultsWanted`      | Integer       | `20`                       | Maximum unique hotel records to save.                                                |
| `maxPages`           | Integer       | `10`                       | Maximum listing pages to process, with up to 20 hotels per page.                     |
| `proxyConfiguration` | Object        | Apify residential proxy    | Proxy settings. Explicit user settings are respected.                                |

#### Supported URLs

Use public Klook hotel search-result URLs with `stype` and `svalue`, or a `city_id`. Localized paths such as `/en-US/hotels/searchresult/`, `/zh-HK/hotels/searchresult/`, and locale-free `/hotels/searchresult/` are accepted. Search types include city, district, place, and hotel searches when the URL contains a valid Klook identifier.

Hotel detail URLs, activity URLs, and city landing pages are not accepted as listing URLs. For these cases, enter the destination in `location` or open the hotel's destination search on Klook and copy that listing URL. The Actor does not silently substitute a different destination for an invalid URL.

Location names can be ambiguous. The Actor prefers an exact destination match and reports the selected destination in its run log. Use a URL when you need a specific district, landmark, or city with a common name.

### Usage Examples

#### Dubai hotel search URL

Collect up to 20 hotels using the URL's destination and occupancy.

```json
{
    "startUrl": "https://www.klook.com/en-US/hotels/searchresult/?city_id=78&stype=city&svalue=78&adult_num=2&child_num=0&room_num=1&currency=USD",
    "resultsWanted": 20,
    "maxPages": 2
}
```

#### Search by location

Collect a larger Dubai dataset without having to find a search URL first.

```json
{
    "location": "Dubai",
    "resultsWanted": 60,
    "maxPages": 3
}
```

#### Five-star hotels with fixed stay dates

Compare hotels using the same dates and occupancy. Change these dates before running if they are no longer in the future.

```json
{
    "startUrl": "https://www.klook.com/en-US/hotels/searchresult/?city_id=78&filter_selected=star%7C5",
    "checkIn": "2026-11-15",
    "checkOut": "2026-11-17",
    "adults": 2,
    "rooms": 1,

    "sortBy": "review_score",
    "resultsWanted": 20,
    "maxPages": 2
}
```

### Output Data

All optional fields are omitted when missing. Dates and prices are a snapshot, not a booking quote.

| Field                                           | Type    | Description                                                           |
| ----------------------------------------------- | ------- | --------------------------------------------------------------------- |
| `hotel_id`                                      | String  | Klook hotel identifier.                                               |
| `name`, `local_name`                            | String  | Hotel name and local name when published.                             |
| `hotel_url`                                     | String  | Hotel detail link without tracking parameters.                        |
| `stars`                                         | Number  | Hotel star category.                                                  |
| `rating`, `rating_max`                          | Number  | Guest rating and its maximum scale.                                   |
| `rating_label`                                  | String  | Guest rating label, such as Fantastic.                                |
| `review_count_text`                             | String  | Review count exactly as Klook displays it.                            |
| `city_id`, `country_id`, `product_id`           | Number  | Destination and product identifiers.                                  |
| `city`, `country`                               | String  | Property city and country.                                            |
| `latitude`, `longitude`                         | Number  | Property coordinates.                                                 |
| `time_zone`                                     | String  | Property timezone offset.                                             |
| `location_description`, `description`           | String  | Listing location text and description when published.                 |
| `images`                                        | Array   | Property image URLs.                                                  |
| `features`, `promotions`, `price_tags`          | Array   | Published feature, promotional, and pricing labels.                   |
| `booking_popularity`                            | String  | Booking-count label shown in the listing.                             |
| `price`, `price_after_tax`                      | Number  | Listed price and post-tax price when published.                       |
| `formatted_price`                               | String  | Formatted listing price.                                              |
| `currency`, `currency_symbol`                   | String  | Currency associated with the returned price and its displayed symbol.                              |
| `tax_description`, `original_price_description` | String  | Tax and original-price information when available.                    |
| `available`                                     | Boolean | Availability marker published with the price.                         |
| `stock_description`                             | String  | Availability text when published.                                     |
| `price_date_description`                        | String  | Date context associated with the listed rate.                         |
| `pay_later_description`, `reward_description`   | String  | Pay-later and reward information when published.                      |
| `check_in`, `check_out`                         | String  | Stay dates associated with the listing price.                         |
| `suggested_dates`                               | Boolean | Whether Klook supplied suggested dates instead of fixed search dates. |
| `locale`                                        | String  | Search language/region.                                               |
| `search_url`, `search_location`                 | String  | Supplied search URL or location, depending on search mode.            |
| `page`, `position`                              | Number  | Source page and position in saved results.                            |
| `total_properties`                              | Number  | Number of matching properties reported by Klook.                      |
| `scraped_at`                                    | String  | Collection timestamp in ISO format.                                   |

### Sample Output

This shortened record is based on a live Dubai result. Prices, review counts, and suggested dates change over time.

```json
{
    "hotel_id": "116863",
    "name": "The S Hotel Al Barsha",
    "hotel_url": "https://www.klook.com/en-US/hotels/detail/116863-the-s-hotel-al-barsha/",
    "stars": 4,
    "rating": 4.5,
    "rating_max": 5,
    "rating_label": "Fantastic",
    "review_count_text": "240 reviews",
    "city": "Dubai",
    "country": "United Arab Emirates",
    "latitude": 25.069861,
    "longitude": 55.244083,
    "location_description": "1.0km from Dubai Butterfly Garden",
    "features": ["Fitness", "Business center"],
    "booking_popularity": "3K+ people booked",
    "price": 63.13,
    "currency": "USD",
    "available": true,
    "check_in": "2026-10-09",
    "check_out": "2026-10-10",
    "suggested_dates": true,
    "locale": "en-US",
    "page": 1,
    "position": 1,
    "total_properties": 1039
}
```

### Tips for Best Results

- Specify fixed dates for meaningful price comparisons. Without dates, different hotels can use different suggested stays.
- Keep currency and occupancy constant across monitoring runs.
- Copy filters from a working Klook search. Filter IDs and sorting choices can vary by destination.
- Increase both limits for large collections. For example, 100 hotels normally requires at least 5 pages.
- Klook may include surrounding towns in a destination search. The output city identifies each property's actual city.
- Start with 20 hotels and check the results before scheduling larger runs.
- Residential proxies can improve access consistency, but access is not guaranteed. Review failure logs before retrying.

### Integrations

- **Google Sheets and Excel** - Compare hotel ratings, prices, and destination coverage.
- **JSON and CSV exports** - Import structured hotel data into analysis tools.
- **Apify schedules** - Collect periodic listing snapshots.
- **Webhooks, Make, and Zapier** - Trigger reporting and downstream workflows after a run.
- **Apify API** - Start runs and retrieve datasets from your own applications.

### Frequently Asked Questions

#### Does this Actor scrape individual hotel reviews?

No. It collects hotel listings and their rating summaries. Individual guest review text is outside this Actor's scope.

#### Can I collect every hotel in a destination?

You can request a large result count and enough pages. The run stops at either configured limit, an empty or repeated page, or the end of Klook's reported results. Access restrictions and changing search results can reduce coverage.

#### Why are some fields missing?

Missing fields were not published for that listing. The Actor omits null values, empty strings, and empty collections, while retaining valid zero and false values.

#### Are the prices guaranteed booking rates?

No. Prices reflect the listing at collection time and can change with dates, occupancy, availability, taxes, promotions, and user context. Check Klook before booking.

#### What happens if I provide both a URL and a location?

The URL determines the destination. Explicit dates, occupancy, and supported sorting inputs can still override URL options.

#### Can I schedule collection and export CSV or Excel?

Yes. Use Apify schedules and dataset exports. Preserve run timestamps if you combine several snapshots.

### Support

Report problems through the Actor's Issues tab. Include the search URL or location, the relevant input options, and a run link. Do not share proxy credentials or other secrets.

### Legal Notice

This Actor is not affiliated with Klook. Use it for legitimate collection of publicly available hotel data and comply with Klook's terms, applicable laws, privacy requirements, and rights associated with property images. Do not use collected data to misrepresent hotel availability or booking prices.

# Actor input Schema

## `startUrl` (type: `string`):

Optional Klook hotels/searchresult/ URL for a city, district, landmark or hotel search. Takes priority over location. Hotel detail URLs are not supported.

## `location` (type: `string`):

City, district or landmark to search when no listing URL is supplied. Use a URL to identify an ambiguous destination precisely.

## `checkIn` (type: `string`):

Optional YYYY-MM-DD date. Supply both check-in and check-out dates. Overrides the URL check-in date.

## `checkOut` (type: `string`):

Optional YYYY-MM-DD date after check-in. Overrides the URL check-out date. Without dates, Klook supplies suggested-date prices.

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

Number of adults, at least 1. Overrides URL occupancy; otherwise the URL value or 2 is used.

## `rooms` (type: `integer`):

Number of rooms, at least 1. Overrides the URL room count; otherwise the URL value or 1 is used.

## `childAges` (type: `integer`):

Optional age from 0 to 17 for one child. Overrides the URL child count and ages. Leave unset to preserve URL occupancy or use no children. For multiple children, provide their ages in the listing URL.

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

Choose Klook's recommended order or guest review score, highest first. Overrides URL sorting when supplied. Price sorting is not offered because displayed prices are not reliably ordered.

## `resultsWanted` (type: `integer`):

Maximum number of unique hotel listings to save. Fewer may be returned when matching properties or available pages are exhausted.

## `maxPages` (type: `integer`):

Maximum listing pages to request. Each source page normally contains up to 20 hotel cards.

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

Residential proxies are recommended for reliable Klook access. Explicit proxy settings are preserved; access is not guaranteed.

## Actor input object example

```json
{
  "location": "Dubai",
  "resultsWanted": 20,
  "maxPages": 10,
  "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 = {
    "location": "Dubai"
};

// Run the Actor and wait for it to finish
const run = await client.actor("shahidirfan/klook-hotels-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 = { "location": "Dubai" }

# Run the Actor and wait for it to finish
run = client.actor("shahidirfan/klook-hotels-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 '{
  "location": "Dubai"
}' |
apify call shahidirfan/klook-hotels-scraper --silent --output-dataset

```

## MCP server setup

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