# Klook Scraper - Activities, Tours & Attractions (`abotapi/klook-activities-scraper`) Actor

Scrape Klook activities, tours, attractions and travel experiences from search pages or activity URLs. Extract structured data for destinations, prices, ratings, availability, images, package details and more.

- **URL**: https://apify.com/abotapi/klook-activities-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Stats:** 3 total users, 2 monthly users, 85.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 klook records

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

## Klook Activities & Hotels Scraper

Collect hotel offers, activity listings, activity details, public reviews and discovery links from klook.com. Search by keyword or provide activity and keyword-search URLs. Save structured records with prices, ratings, locations and images where available. Use resume and recurring updates to avoid collecting the same records again.

### Why This Scraper?

- **Search and URL modes.** Discover activities by keyword or collect several selected activities in one run.
- **Activity details.** Add descriptions, addresses, images and cancellation information when available.
- **Public reviews.** Collect review text, available translations, dates and publicly displayed author names.
- **Hotels for your stay.** Search destinations and hotel URLs with dates, guests, rooms and offer filters. Categories, destinations and suggestions also provide discovery links.
- **Themed searches.** Find eSIM, dining, car rental, airport transfer and promotional listings.
- **Recurring collection.** Skip previously collected records or return new and changed records across runs.
- **App exports.** Send a summary of selected records to connected apps while keeping complete records in the dataset.

### Data You Get

Fields depend on the operation and the information available for each record.
These examples are fictional placeholders, not scraped records.

| Field | Example |
| --- | --- |
| `id` | `000000` |
| `activityId` | `000000` |
| `recordType` | `activity` |
| `title` | `Example observation deck admission` |
| `url` | `https://www.klook.com/en-US/activity/000000-example/` |
| `price` | `25.00` |
| `currency` | `USD` |
| `marketPrice` | `30.00` |
| `rating` | `4.5` for an activity |
| `reviewCount` | `100` |
| `location` | `Example city` |
| `country` | `Example country` |
| `address` | `100 Example Street` |
| `category` | `Attractions` |
| `description` | `Example admission description` |
| `cancellationPolicy` | `Example cancellation terms` |
| `imageUrls` | `["https://example.com/activity.jpg"]` |
| `promotions` | `["Example offer"]` |
| `detailStatus` | `complete` |
| `operation` | `activities` |
| `sourceMode` | `search` |
| `changeType` | `NEW` |
| `hotelId` | `000000` |
| `checkIn` | `2027-01-10` |
| `checkOut` | `2027-01-12` |

Review records also contain `author`, `date`, `language` and `translatedText` when available.
The author's public masking is retained. Review ratings use Klook's 0-100 scale;
do not compare them directly with activity ratings without adjusting the scale.

### How to Use

Choose an operation, select search or URL mode, and set **Max items**.
Start the actor and open the Results dataset view to inspect or export the records.
The default input searches Tokyo and returns up to 20 records.

#### Search for activities

```json
{
  "operation": "activities",
  "mode": "search",
  "query": "Tokyo",
  "maxItems": 20,
  "fetchDetails": true
}
```

#### Search hotels for a family stay

```json
{
  "operation": "hotels",
  "mode": "search",
  "query": "Tokyo",
  "checkIn": "30 days",
  "adults": 4,
  "rooms": 2,
  "childrenAges": ["8"],
  "starRatings": ["4"],
  "freeCancellation": true,
  "breakfastIncluded": true,
  "hotelSort": "priceAsc",
  "maxItems": 20
}
```

An omitted check-out gives a two-night stay. Dates and guests affect available offers.
For hotel URL mode, use a hotel property, hotel city or hotel search link.
For example: `https://www.klook.com/en-US/hotels/detail/81173-hotel-sardonyx-tokyo/`.
Hotel dates and guests included in a URL take precedence over the form values.
Each hotel is returned once per run. Hotel search does not use Fetch activity details.

#### Collect multiple activities by URL

```json
{
  "operation": "activities",
  "mode": "url",
  "urls": [
    "https://www.klook.com/en-US/activity/41352-tokyo-skytree/",
    "https://www.klook.com/en-US/activity/52-hong-kong-disneyland-resort-hong-kong/"
  ],
  "maxItems": 20
}
```

Activity URLs read the selected activity's details directly.
Keyword search URLs preserve the query and starting page; other URL filters are not supported.

#### Collect public reviews

```json
{
  "operation": "reviews",
  "mode": "url",
  "urls": ["https://www.klook.com/en-US/activity/41352-tokyo-skytree/"],
  "maxItems": 20
}
```

Reviews always use the activity URLs, even if Mode is still set to Search.
No mode change is needed. The detail-enrichment option does not apply to reviews.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `operation` | string | "activities" | Choose activities, reviews, categories, destinations, home, suggestions, deals, esim, car\_rentals, airport\_transfers, dining or hotels. |
| `mode` | string | "search" | Keyword search or pasted URLs. Reviews always use activity URLs. |
| `query` | string | "Tokyo" | Keyword for activities or suggestions, or a hotel destination/property; ignored in URL mode. |
| `currency` | string | "USD" | Display currency where supported. |
| `urls` | array | Tokyo Skytree activity URL | Activity, keyword-search or hotel URLs. Reviews require activity URLs; Hotels requires hotel links. |
| `checkIn` | string | "30 days" | Hotels only. YYYY-MM-DD or a relative value such as 30 days. Defaults to 30 days from today. |
| `checkOut` | string | "empty" | Hotels only. Leave empty for two nights after check-in. A stay must be 1-30 nights. |
| `adults` | integer | 2 | Hotels only. Total adult guests across all rooms, with at least one adult per room. |
| `rooms` | integer | 1 | Hotels only. Number of rooms needed for the guest party. |
| `childrenAges` | array | \[] | Hotels only. One age from 0 to 17 per child, up to 10 children. The child count comes from this list. |
| `hotelSort` | string | "recommended" | Hotels only. Use Klook's hotel sort order. Live quoted prices may not be strictly ordered. |
| `starRatings` | array | \[] | Hotels only. Leave empty for all star ratings. |
| `minHotelRating` | string | "0" | Hotels only. Minimum guest review score on the 0-5 scale. |
| `minNightlyPrice` | integer | 0 | Hotels only. Minimum price in the selected currency, including taxes and fees. Zero means no minimum. |
| `maxNightlyPrice` | integer | 0 | Hotels only. Maximum price in the selected currency, including taxes and fees. Zero means no maximum. |
| `freeCancellation` | boolean | false | Hotels only. Request offers matching the free-cancellation filter. Deadlines and terms vary by offer. |
| `breakfastIncluded` | boolean | false | Hotels only. Request offers that include breakfast. |
| `fetchDetails` | boolean | true | Enrich activity search results. Direct activity URLs always read details. |
| `maxItems` | integer | 20 | Run-wide output cap, from 1 to 500. |
| `maxPages` | integer | 50 | Page limit per search or review source, defaulting to its maximum of 50. Stops earlier at Max items or the end of results; empty or 0 removes the page limit. |
| `resumeFromRunId` | string | empty | Previous run or dataset ID whose records should be skipped. |
| `incrementalMode` | boolean | false | Compare records with persistent state and return NEW or UPDATED records. |
| `stateKey` | string | empty | Optional recurring campaign name; otherwise derived from the operation, mode, query or URLs, currency and detail setting. |
| `emitUnchanged` | boolean | false | Also emit UNCHANGED records during incremental runs. |
| `proxyConfiguration` | object | Apify Proxy enabled | Apify Proxy connection settings. |
| `mcpConnectors` | array | empty | Optional connector names for summary export. |
| `notionParentPageUrl` | string | empty | Parent page for Notion export. |
| `maxNotifyListings` | integer | 50 | Maximum records sent to each connector; does not change the dataset cap. |

#### Operation scope

Hotels returns one offer card per property with the requested stay and guest context,
star rating, review score, nightly price description, images and availability.
`priceDisplay` preserves any member-price masking; `priceCondition` identifies conditions
such as login pricing. A returned rate is not a booking guarantee. Hotel results do not
include an additional activity-detail enrichment charge.

Categories, destinations and home return discovery links rather than activity details.
Suggestions uses the query to return matching discovery links.
Popular destinations can vary with the connection's location.
The eSIM, dining, car rental and airport transfer operations search matching listings.
Car rental and transfer records are discovery listings, not date-specific availability or booking quotes.

#### Resume and recurring updates

Use `resumeFromRunId` to skip records already returned by a particular run or dataset.
Use `incrementalMode` for repeated runs of the same search: the first run returns NEW
records, and later runs return NEW or UPDATED records by default.
Enable `emitUnchanged` to include records that match the saved state.
Hotel state also includes resolved stay dates, guests, sort and filters.
Relative dates move as days pass; use fixed stay dates to monitor the same stay.
Keep the same search and detail settings between recurring runs, or set a separate
`stateKey` for each campaign. This actor does not emit disappearance records.

#### Send results into your apps

Authorize a connector under Apify Settings > Integrations, then select it in
`mcpConnectors`. For Notion, also provide `notionParentPageUrl`.
Each exported item is a condensed, human-readable summary. Nested information may
be shortened; the complete record remains in the Apify dataset.
`maxNotifyListings` limits export only. Leave connectors empty to skip this step.

### Output Example

This fictional example shows an enriched activity search record.
Optional values may be empty or absent when Klook does not provide them.

```json
{
  "id": "000000",
  "activityId": "000000",
  "recordType": "activity",
  "title": "Example observation deck admission",
  "url": "https://www.klook.com/en-US/activity/000000-example/",
  "price": 25.0,
  "currency": "USD",
  "marketPrice": 30.0,
  "rating": 4.5,
  "reviewCount": 100,
  "location": "Example city",
  "country": "Example country",
  "address": "100 Example Street",
  "category": "Attractions",
  "description": "Example admission description.",
  "cancellationPolicy": "Example cancellation terms.",
  "imageUrls": ["https://example.com/activity.jpg"],
  "promotions": ["Example offer"],
  "booked": "100+ booked",
  "detailStatus": "complete",
  "operation": "activities",
  "sourceMode": "search",
  "changeType": "NEW"
}
```

An additional charge applies only to successfully enriched activity search records
saved in the dataset. Failed or skipped enrichment, unchanged records suppressed
by incremental mode, and direct activity URL lookups do not incur this extra charge.

If optional enrichment is unavailable, the listing is retained. `detailStatus`
identifies completed or unavailable enrichment attempts. After repeated failures,
further enrichment is skipped, so later records may have no `detailStatus`.
A direct activity lookup can fail if its details cannot be read.

Max items is a cap, not a guaranteed count. A source returning no records causes
the run to fail visibly. Resume and incremental runs can legitimately return zero
records when all inspected records were already collected or are unchanged.

### Plan Requirement

An Apify account and access to the configured proxy are required.

# Actor input Schema

## `operation` (type: `string`):

Choose activities, public reviews, catalog navigation, suggestions, or a themed listing search. Home returns homepage links; deals returns listings with promotions or reduced prices. Car rentals and airport transfers return discovery listings, not date-specific quotes. Reviews always use the activity URLs; no mode change is needed. Hotels searches properties for your selected stay and guests.

## `mode` (type: `string`):

Search by keyword or read pasted Klook URLs. Reviews always use the activity URLs, regardless of this setting.

## `query` (type: `string`):

Keyword for activity search and suggestions, or a hotel city, area or property name. Ignored in URL mode and for categories, destinations and home.

## `currency` (type: `string`):

Three-letter display currency when supported by the page.

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

Activity or keyword search URLs. Reviews require an activity URL. Search URLs preserve the query and start page; other URL filters are not supported. Hotels accepts hotel property, hotel city and hotel search URLs. Hotel stay dates and guests in a URL take precedence over form values.

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

Hotels only. YYYY-MM-DD or a relative value such as 30 days. Defaults to 30 days from today.

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

Hotels only. Leave empty for two nights after check-in. A stay must be 1-30 nights.

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

Hotels only. Total adult guests across all rooms, with at least one adult per room.

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

Hotels only. Number of rooms needed for the guest party.

## `childrenAges` (type: `array`):

Hotels only. One age from 0 to 17 per child, up to 10 children. The child count comes from this list.

## `hotelSort` (type: `string`):

Hotels only. Use Klook's hotel sort order. Live quoted prices may not be strictly ordered.

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

Hotels only. Leave empty for all star ratings.

## `minHotelRating` (type: `string`):

Hotels only. Minimum guest review score on the 0-5 scale.

## `minNightlyPrice` (type: `integer`):

Hotels only. Minimum price in the selected currency, including taxes and fees. Zero means no minimum.

## `maxNightlyPrice` (type: `integer`):

Hotels only. Maximum price in the selected currency, including taxes and fees. Zero means no maximum.

## `freeCancellation` (type: `boolean`):

Hotels only. Request offers matching the free-cancellation filter. Deadlines and terms vary by offer.

## `breakfastIncluded` (type: `boolean`):

Hotels only. Request offers that include breakfast.

## `fetchDetails` (type: `boolean`):

Add description, address, images and cancellation information to activity listings. Does not apply to reviews or catalog navigation. An additional charge applies only to successfully enriched records saved in the dataset.

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

Maximum number of records returned. Applies to every operation.

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

Maximum search pages to read. Defaults to the maximum of 50; stops earlier at Max items or the end of results. Empty or 0 removes the page limit.

## `resumeFromRunId` (type: `string`):

Skip activity IDs already present in a previous run or dataset.

## `incrementalMode` (type: `boolean`):

Return only new or changed activities for the same state key.

## `stateKey` (type: `string`):

Name for shared recurring-run state. Leave empty to derive it from operation, query or URLs, and currency.

## `emitUnchanged` (type: `boolean`):

Return records that have not changed during incremental monitoring.

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

Apify Proxy settings used for Klook requests.

## `mcpConnectors` (type: `array`):

Optional connector names for downstream export.

## `notionParentPageUrl` (type: `string`):

Optional parent page for Notion export.

## `maxNotifyListings` (type: `integer`):

Maximum records sent to each optional connector.

## Actor input object example

```json
{
  "operation": "activities",
  "mode": "search",
  "query": "Tokyo",
  "currency": "USD",
  "urls": [
    "https://www.klook.com/en-US/activity/41352-tokyo-skytree/"
  ],
  "checkIn": "30 days",
  "adults": 2,
  "rooms": 1,
  "childrenAges": [],
  "hotelSort": "recommended",
  "starRatings": [],
  "minHotelRating": "0",
  "minNightlyPrice": 0,
  "maxNightlyPrice": 0,
  "freeCancellation": false,
  "breakfastIncluded": false,
  "fetchDetails": true,
  "maxItems": 20,
  "maxPages": 50,
  "incrementalMode": false,
  "emitUnchanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}
```

# 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 = {
    "operation": "activities",
    "mode": "search",
    "query": "Tokyo",
    "currency": "USD",
    "urls": [
        "https://www.klook.com/en-US/activity/41352-tokyo-skytree/"
    ],
    "checkIn": "30 days",
    "fetchDetails": true,
    "maxItems": 20,
    "maxPages": 50,
    "incrementalMode": false,
    "emitUnchanged": false,
    "proxyConfiguration": {
        "useApifyProxy": true
    },
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/klook-activities-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 = {
    "operation": "activities",
    "mode": "search",
    "query": "Tokyo",
    "currency": "USD",
    "urls": ["https://www.klook.com/en-US/activity/41352-tokyo-skytree/"],
    "checkIn": "30 days",
    "fetchDetails": True,
    "maxItems": 20,
    "maxPages": 50,
    "incrementalMode": False,
    "emitUnchanged": False,
    "proxyConfiguration": { "useApifyProxy": True },
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/klook-activities-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 '{
  "operation": "activities",
  "mode": "search",
  "query": "Tokyo",
  "currency": "USD",
  "urls": [
    "https://www.klook.com/en-US/activity/41352-tokyo-skytree/"
  ],
  "checkIn": "30 days",
  "fetchDetails": true,
  "maxItems": 20,
  "maxPages": 50,
  "incrementalMode": false,
  "emitUnchanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxNotifyListings": 50
}' |
apify call abotapi/klook-activities-scraper --silent --output-dataset

```

## MCP server setup

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