Klook API

Asia's things-to-do catalogue as JSON, priced in the currency you ask for

The Klook API returns the largest marketplace for things to do in Asia as clean JSON in nine actions.

no credit card1,000 free credits · instant API key · pay by card or crypto
Missing a Klook endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
K
/klook/v1

9 active endpoints, on 0, 1 and 2 credit tiers.

  • POST/klook/v1/activities/search
  • POST/klook/v1/activities/list
  • POST/klook/v1/activity/detail
  • POST/klook/v1/activity/packages
  • POST/klook/v1/activities/batch
  • POST/klook/v1/activity/reviews
  • POST/klook/v1/destinations/resolve
  • +2 more

What Klook endpoints does ReefAPI ship?

9 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

9 endpoints

activities/search

2 cr

Search or browse Klook activities by keyword and/or destination, with category, price, date,…

required
—
optional
query, destination_id, category, sort, price_min, price_max, date, date_to, instant_confirmation, page, currency, language

activities/list

2 cr

Destination browse in 50-result pages.

required
—
optional
query, city_id, country_id, price_min, price_max, instant_confirmation, page, currency, language

activity/detail

2 cr

The full published record for one activity.

required
activity_id
optional
currency, language

activity/packages

2 cr

Every bookable package (option) of one activity with its OWN price, cancellation policy, conf…

required
activity_id
optional
currency, language

activities/batch

1 cr

Price, rating, coordinates, package count and availability for up to 50 activities in ONE ups…

required
activity_id
optional
currency, language

activity/reviews

1 cr

Traveller reviews for one activity, newest first, with rating, text, photos, the package the…

required
activity_id
optional
page, limit, language

destinations/resolve

0 cr

Turn a typed place name into the ids the other actions need.

required
query
optional
language

destinations/browse

0 cr

Klook's own destination directory.

required
—
optional
include_all_cities, language

categories

0 cr

The category vocabulary.

required
—
optional
language

Every parameter, every allowed value →

Klook API

5 of 9 endpoints, ready to run

View docs ↗

Klook activities by keyword, destination or both: id, title, url, category, city and country, coordinates, price and struck price in the currency you asked for, rating, review count and tags. 20 a page, with category, price, date, instant-confirmation and sort filters that were each proved to change the count.

2 credits0 required · 12 optional
POST/klook/v1/activities/search
idle
// Press "Try it" and this pane shows exactly what the
// live site returned this second — including an empty
// result, if that is the truth. No key, no account.

How the Klook API works

Klook is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 294 engines.

02
Call
POST /klook/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
0 or 1 or 2 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Resolve the destination first, because it is free and the id is not the one you think

Klook offsets country ids by 1000 in search and answers a bare country id with total 0 and no error anywhere. Resolving costs nothing, so there is no reason to build an id by hand.

01resolve
POST/klook/v1/destinations/resolve
{"query": "tokyo"}

Zero credits. Returns cities and countries with search_location_id already in the form search expects. Country ids are validated against Klook's own published directory, so an id that would return nothing comes back as null with the reason instead.

02search
POST/klook/v1/activities/search
{"destination_id": 28, "category": "attractions", "price_min": 10, "price_max": 40, "currency": "USD"}

2 credits for 20 rows. Read total, and total_is_capped, because Klook stops counting broad queries at 1,000. Every row carries product_type and has_activity_detail, so a hotel row is visible before you spend a credit on a detail call it cannot answer.

03detail
POST/klook/v1/activity/detail
{"activity_id": 93901, "currency": "USD"}

2 credits. Summary, highlights, images, address, coordinates, category path and the price span. Check redirected: Klook sometimes answers with a superseded listing's replacement, and requested_activity_id tells you which id you actually got.

04packages
POST/klook/v1/activity/packages
{"activity_id": 93901, "currency": "USD"}

2 credits. Each package with its own price, cancellation policy, confirmation type, ticket type and party-size limits, plus the available dates. is_open_dated true means an open ticket with no calendar, not a failure.

05batch
POST/klook/v1/activities/batch
{"activity_id": [93901, 141, 1552], "currency": "USD"}

1 credit for up to 50 ids in one call. This is where a price you are tracking over time should come from, because the search card's price rotates and this one did not across twelve repeats.

A destination id you can prove, a market you can count, an activity enriched with fields the results list does not carry, and a per-package price you can quote.

request
curl -X POST https://api.reefapi.com/klook/v1/activities/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"destination_id":28,"category":"attractions","currency":"USD"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "klook",
    "endpoint": "activities/search",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

Seven Klook values that are not what they look like

Klook publishes several fields that read as one thing and mean another: a price that moves between calls, a rating on a different scale to the rating beside it, an id that answers with a different product. These were read from live responses on 2026-09-24 and 2026-09-25.

FieldLooks likeActually isWhat comes back
price on a search cardthe priceone of several promotional prices Klook rotates: the same activity answered with 4 distinct prices across 12 calls in the same minutes, while activities/batch and activity/detail answered with 1 eachthe price Klook really showed, plus price_note on every search response pointing at the two surfaces that did not move
pricean exact pricesometimes the cheapest package's price instead: 135 exact and 25 from-price across 160 search cards, and 175 exact against 25 from-price-only across 200 list rowsprice_is_from on both surfaces, so a from-price is never read as an exact one and never lands as a null
a review's rating100Klook scores reviews on 0 to 100 and activities on 0 to 5, in the same documentnormalised to the 0 to 5 scale Klook displays, with rating_scale stated alongside
packagesnull, which reads as a failurean open-dated ticket with no dated schedule to publish, returned in the same minute another activity returned 9 packagesis_open_dated true, an empty list and a sentence, not an error
a country idan id activities/search takesoffset by 1000 there: Japan is 12 in the directory and 1012 in search, and the bare id returns total 0 with no errorsearch_location_id from destinations/resolve, already in the form search expects, validated against Klook's published country directory, or null with the reason
the activity id you asked forthe activity you get1 of 24 sampled ids was a superseded listing that resolved to a different product with HTTP 200requested_activity_id, a redirected flag and a sentence naming the id actually served
a search rowan activitysometimes a hotel: vertical_type 102 rows carry activity-shaped ids and 3 of 3 returned NOT_FOUND from the activity endpointsproduct_type and has_activity_detail on every row, and a NOT_FOUND message that says it was a hotel id

Prices are returned in the currency the call asks for, and every price object repeats the code it belongs to. Klook's own default is HKD, so USD is sent unless you ask for something else. Round-trip on one activity: USD 38.29, HKD 294, JPY 6,049, EUR 33.49, SGD 42.09, THB 1,101.

Asia, in 42 currencies, and the lines that go against us

Measured 2026-09-24 and 2026-09-25 through the live engine. Every action was run on twelve different real inputs, never one id repeated: twelve cities, twelve queries, twelve activity ids. Four of these lines go against us.

Nine actions, all at 12 of 12

activities/search on destinations and on keywords, activities/list, activities/batch, activity/reviews, activity/detail, activity/packages, destinations/resolve, destinations/browse and categories. Twelve distinct inputs per action, 12 of 12 on every one, on 2026-09-25. Klook publishes 39,849 activity pages and about 1,440 cities, and destinations/browse hands you the whole directory.

The currency is whatever your call asks for, and every price says which

currency is a parameter, it accepts 42 codes measured as working, and it defaults to USD. Klook's own default is HKD, so a call that did not ask would hand you Hong Kong dollars. Every price object repeats the code it belongs to. Round-trip on one activity: USD 38.29, HKD 294, JPY 6,049, EUR 33.49, SGD 42.09, THB 1,101. A code Klook does not support is refused before the call goes out, because the source answers one with an empty list rather than an error.

klook.cn is a different storefront, and it is not used here

On one activity in the same minute with the same requested currency, klook.cn showed 46.65 where klook.com showed 66.65, and 503.55 where klook.com showed 719.35. The schema is byte-identical, which is exactly what would have hidden it. This engine reads the global klook.com storefront only, on every action and every field, so the price you get is the price a klook.com traveller sees.

Against us: the search card's price rotates

The same activity answered with 4 distinct prices across 12 search calls in the same minutes. Those are prices Klook really showed, so they are returned as shown rather than smoothed into one. activities/batch and activity/detail answered with 1 price each across 12 and 6 repeats, and every search response carries price_note saying so. Read a tracked price from batch or detail.

Against us: there is no cancellation policy at the activity level

Klook attaches cancellation terms to each package, so activity.cancellation_policy is always null with a comment saying so, and the real terms are on every row of activity/packages, where they were present on every package measured. What a package includes is prose rather than a structured list, so it comes back in highlights rather than being invented into fields.

Against us: Klook's own counting ceilings

Broad searches stop counting at 1,000 matches, and one activity serves at most 2,000 reviews even when it has 16,776. Both are reported as total_is_capped rather than passed off as the real total. Narrow by city, category, price band or date to reach past them. Row counts are also language-specific: 1,412 results in English against 1,319 in Japanese for the same search.

Against us: some rows are hotels, and they have no activity detail

Klook's search mixes verticals, and a hotel row carries an activity-shaped id. 3 of 3 hotel ids returned NOT_FOUND from the activity endpoints against 12 of 12 for real activity ids. Every row now carries product_type and has_activity_detail, and the NOT_FOUND message names it as a hotel id, so the mistake costs one look instead of a debugging session.

Every filter was proven against a same-run control

Against an unfiltered control of 196 in the same run: one city cut it to 47, another to 14, a country to 91, attractions to 19, hotels to 6, transport to 2, a 10 to 30 price band to 35, 100 to 500 to 39, a single date to 161, a three-day range to 171 and instant confirmation to 165. On the list endpoint a city cut 2,510 to 55 and a country to 278. Filters Klook accepts and silently ignores are not offered, and junk values are refused without a fetch.

Sort is a ranking, not a sort, and it says so

All five published orderings genuinely reorder page one: lowest price moved the cheapest row on page one from 27.99 to 1.79. But promoted rows stay mixed in, and across six queries only 63% of adjacent price pairs were ascending. Documented rather than papered over, with the advice to sort locally when you need a guarantee.

Price

destinations/resolve, destinations/browse and categories are free. activities/search, activities/list, activity/detail and activity/packages are 2 credits each. activities/batch and activity/reviews are 1. Batch is the bargain on purpose: 50 activities for 1 credit against 50 detail calls for 100.

What people build with Klook

The jobs this data is most often used for.

9

endpoints

0/1/2

credits per call

01

Track attraction and tour pricing across Asian cities week over week, reading the stable price from activities/batch rather than the rotating search card.

02

Build a things-to-do module for a travel site: resolve the city, search by category and price band, and render title, rating, review count and image from one call.

03

Compare a single attraction's packages before booking, each with its own price, cancellation policy, confirmation type and party-size limits.

04

Refresh a watchlist of up to 50 activities in one call for one credit, catching price moves, rating changes and next available date.

What Klook data costs

The cheapest call here is 0 credits, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 294 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/klook/v1/activities/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"destination_id":28,"category":"attractions","currency":"USD"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/klook/v1/activities/search",
    headers={"x-api-key": REEF_KEY},
    json={
  "destination_id": 28,
  "category": "attractions",
  "currency": "USD"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Klook.

Get a free key →
Which currency are Klook prices in?▾

Whichever one your call asks for. currency is a parameter on search, list, detail, packages and batch, it accepts 42 codes measured as working, and it defaults to USD here. Klook's own default is HKD, so leaving it out upstream would hand you Hong Kong dollars. Every price object in the response repeats the currency code it belongs to, so a number is never separated from its unit. A code Klook does not support is refused before the call goes out rather than answered with an empty list, which is what the source does with one.

Why does the same activity come back at a different price on a second call?▾

Because Klook rotates a promotional price on its search cards. The same activity answered with four distinct prices across twelve search calls in the same minutes, while activities/batch and activity/detail answered with one price on every repeat. Those are prices Klook genuinely showed, so they are returned as shown, and every search response carries price_note pointing at the two stable surfaces. If you are tracking a price over time, read it from batch or detail.

Do prices on klook.cn match the ones I get here?▾

No, and that is worth knowing. klook.cn is a separate storefront, not a mirror of klook.com, and it prices differently: on one activity in the same minute and the same requested currency it showed 46.65 against klook.com's 66.65, and 503.55 against 719.35. The schema is identical, which is exactly what would hide the difference. This API reads the global klook.com storefront only, on every action and every field, so the numbers you get are the ones a traveller on klook.com sees.

Why is the price on the activity not the price I pay?▾

Because Klook prices each package independently and the headline figure is only a starting point. One Mount Fuji day tour sells as nine packages running from 46.65 to 503.55 in a single currency. activity/packages returns each one with its own price, cancellation policy, confirmation type, ticket type, minimum and maximum participants, stock and the dates Klook publishes as available. Nothing is copied down from the parent listing, and a struck price is only emitted where Klook's market price is genuinely above what it is selling for, because Klook publishes packages where it is below.

How do I turn a place name into an id?▾

destinations/resolve, which costs nothing. Pass a place the way a traveller types it and it returns cities and countries with a search_location_id already in the form activities/search expects. This matters more than it sounds: Klook offsets country ids by 1000 in search, so Japan is 12 in its directory and 1012 in search, and passing the bare id returns total 0 with no error anywhere. The rule also has an exception Klook does not document, so every computed country id is checked against Klook's own published country directory and comes back as null with the reason rather than as an id that silently returns nothing. destinations/browse gives you the whole directory when you have no name to resolve, about 1,440 cities with include_all_cities.

Does sort actually sort?▾

Not strictly, and that was measured rather than assumed. Klook publishes five orderings and all five genuinely reorder page one: asking for lowest price moved the cheapest row on page one from 27.99 to 1.79. But promoted listings stay mixed in, and across six queries only 63% of adjacent price pairs on a page were ascending. So sort is a ranking, it is documented as one, and if you need a guaranteed order you sort the rows yourself. Values Klook does not publish are rejected here, because the site accepts them and changes nothing.

How many results can one Klook search return?▾

20 a page on activities/search and 50 a page on activities/list, both fixed by Klook, and a limit parameter on those endpoints is ignored. Klook stops counting broad queries at 1,000 matches, and serves at most 2,000 reviews for one activity even when the activity has far more, so both are flagged with total_is_capped rather than presented as the real total. Narrow by city, category, price band or date to reach past the ceiling. Row counts are also language-specific: the same search returned 1,412 results in English and 1,319 in Japanese.

What does Klook not publish?▾

A cancellation policy at the activity level, so activity.cancellation_policy is always null and the real terms are on every row of activity/packages, where they were present on every package measured. An inclusions list as a discrete field, because what a package includes is prose that comes back in highlights rather than being invented into a structured list. A struck price on most tours, 0% of tour rows had one and 14% overall, so a discount is never manufactured. A rating on most hotel rows, 23% against 92% overall, because hotel cards are a different Klook product. And Klook has no 404: an unpublished id answers HTTP 200 with an empty result, which is translated to NOT_FOUND so you can tell a missing activity from an outage.

What is the Klook API?▾

Klook API is a ReefAPI endpoint group for asian activities, attraction tickets and experiences, with packages, reviews and the price in the currency you ask for. It returns live JSON through POST requests under /klook/v1.

Is the Klook API free to try?▾

Yes. ReefAPI starts with 1,000 free credits, no card required. Klook calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Klook login or account?▾

No login to Klook is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Klook data?▾

The page example is captured from a live activities/search call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Klook API use?▾

Klook actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.

Can I call Klook from an AI assistant or MCP client?▾

Yes. Connect ReefAPI once through MCP and your assistant can call klook actions with the same key, credit pool and JSON envelope used by normal REST requests.

9 Travel & Lodging APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Klook, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 293 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-09-25.