Klook Deals Scraper
Pricing
from $4.70 / 1,000 deal chargeds
Klook Deals Scraper
Get Sale-tab deals and promotions — a niche no other Klook scraper covers from Klook. Talks directly to Klook's own mobile app API, no login needed. Split from the mature, published klook-all-in-one-api for a focused, single-purpose workflow.
What does Klook Deals Scraper do?
Klook Deals Scraper scrapes Klook's Sale-tab deals page for a country — the page layout plus its "Ongoing promotions" grid, with real pagination.
It talks directly to the same internal API the official Klook Android app uses, reverse-engineered by disassembling the app's native request-signing library and validated against live traffic captured from a real device. No Klook account, no API key. This is the deals slice of Klook All-in-One API, split out as its own focused Actor.
Why use Klook Deals Scraper?
- Real, working pagination — confirmed live by the parent Actor: distinct
pagevalues return distinctvertical_ids, with zero overlap between pages tested - Real, server-computed pricing in any currency — pass
currency: "USD"(or any ISO code) and get genuine localized prices; confirmed live by the parent Actor to change each card'sdisplay_price - No account needed — works fully anonymously
- Use cases: deal/discount monitoring, price-drop alerting, promotions content aggregation
How it connects to the parent
This Actor is a narrow, batch-run spin-off of klook-all-in-one-api (an always-on Standby REST API exposing every Klook endpoint). It reuses the parent's exact, proven request-signing logic (klook-client.ts, copied verbatim) but only wraps /deals and /deals/more, and runs as a normal input-in/dataset-out Actor instead of a Standby API.
Input
| Field | Type | Description |
|---|---|---|
countryId | string | Required. Klook country id, e.g. 1012=Japan. |
currency | string | ISO code, default GBP |
page | integer | 1-indexed starting page for the promotions grid. Default 1 |
limit | integer | Page size. Default 10 |
categoryId / categoryType | string | Optional category filter for /deals/more. categoryId default "0" |
maxPages | integer | Stop after this many pages. Default 5 |
maxItems | integer | Stop once this many deals have been pushed |
Example:
{ "countryId": "1012", "maxPages": 3 }
Output
One row for the initial page layout ({ "type": "page", "data": {...} }), then one row per deal item ({ "type": "deal", "page": N, "data": {...} }) as pagination proceeds.
Known limitations
- Requires Apify's RESIDENTIAL proxy group. Klook's edge blocks non-residential IPs with a DataDome bot-challenge page — confirmed directly from this development sandbox (a request byte-for-byte identical to a working one, sent without the proxy, came back as a DataDome JS-challenge HTML page, not JSON). All outbound requests route through
Actor.createProxyConfiguration({ groups: ['RESIDENTIAL'] }). - Local dev smoke testing outside the Apify platform needs "Proxy external access" enabled on the account. This Actor's code was verified to be a byte-for-byte match against the parent's already-published, working
klook-client.ts, and the local smoke test run during development failed exactly at the proxy-URL-acquisition step (ProxyConfiguration: The "Proxy external access" feature isn't enabled for your account) — before any request to Klook was even attempted. That's an account-tier restriction on pulling a proxy URL from outside a real platform Actor run, not a defect in this code; once deployed and actually run on Apify's platform, proxy access works through the normal SDK path. /deals/more's exact response shape wasn't documented in the parent Actor's README (only its request params and confirmed-live pagination behavior were) — this Actor extracts deal items generically (the first non-empty array found in the response) rather than hardcoding an unverified path, so it stays correct even if Klook nests the promotions grid slightly differently than expected.- This is an unofficial, reverse-engineered integration, not affiliated with or endorsed by Klook Travel Technology Limited.
Pricing
Pay per event. Charged $0.006 per deal (FREE tier) — one event per row pushed to the dataset. See the Actor's Pricing tab for rates across all tiers.