# Hong Kong Transit Scraper - MTR, KMB, Citybus, Light Rail (`jungle_synthesizer/hong-kong-transit-scraper`) Actor

Hong Kong public transit data via the official HKSAR open APIs: MTR (10 lines), KMB and Citybus bus networks, and MTR Light Rail. Bilingual English / Traditional Chinese station names, real-time train and bus ETAs, full route catalogues.

- **URL**: https://apify.com/jungle\_synthesizer/hong-kong-transit-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Travel, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Hong Kong Transit Scraper

Scrapes Hong Kong's public transit network from the official [HKSAR open data programme](https://data.gov.hk/en/transport). Returns the full route and station catalogue plus real-time arrival ETAs across **MTR** (heavy rail), **MTR Light Rail**, **KMB** (Kowloon Motor Bus), and **Citybus**, all normalized into a single bilingual schema.

---

### Hong Kong Transit Scraper Features

- Returns **MTR** heavy rail across all 10 lines — Island, Tsuen Wan, Kwun Tong, Tseung Kwan O, Tung Chung, Airport Express, East Rail, Tuen Ma, South Island, and Disneyland Resort.
- Returns **MTR Light Rail** (Tuen Mun / Yuen Long) routes 505 through 761P with bilingual stop names.
- Returns **KMB** — ~700 unique bus routes, ~6,000 stops, with Octopus stop IDs and lat/long coordinates.
- Returns **Citybus** — ~400 routes covering Hong Kong Island and cross-harbour services.
- **Real-time ETAs** for every operator: MTR Next Train, MTR Light Rail Next Train, KMB stop ETA, Citybus stop ETA.
- **Bilingual** English / Traditional Chinese station names, route termini, and ETA destinations.
- Pure JSON / CSV API scraping — no headless browser, no captcha plumbing, no proxy required.

---

### Who Uses Hong Kong Transit Data?

- **Travel-tech apps** — power MTR / bus journey planners and arrival-board widgets for Hong Kong's 20M+ annual inbound visitors.
- **MaaS startups** — feed multimodal trip planners with normalized rail + bus data across all four operators.
- **Tourism analytics** — measure transit accessibility for hotels, attractions, and conference venues across Hong Kong Island, Kowloon, and the New Territories.
- **Logistics & delivery** — map last-mile coverage against bus stops and MTR exits.
- **Internal dashboards** — populate dropdowns and validate user-typed origin / destination stations against the real HKSAR transit catalogue.

---

### How Hong Kong Transit Scraper Works

1. Validates the input mode and operator. Rejects unsupported combinations (e.g. `route_stops` on MTR — heavy rail uses `station_list` instead).
2. Pulls the right HKSAR open-data endpoint for the chosen `(operator, mode)`:
   - MTR catalogue → `opendata.mtr.com.hk/data/mtr_lines_and_stations.csv`
   - MTR Light Rail catalogue → `opendata.mtr.com.hk/data/light_rail_routes_and_stops.csv`
   - MTR Next Train → `rt.data.gov.hk/v1/transport/mtr/getSchedule.php`
   - MTR Light Rail Next Train → `rt.data.gov.hk/v1/transport/mtr/lrnt/getSchedule`
   - KMB → `data.etabus.gov.hk/v1/transport/kmb/...`
   - Citybus → `rt.data.gov.hk/v2/transport/citybus/...`
3. Normalizes each operator's response into a single bilingual schema with consistent field names.
4. Resolves bus stop IDs to lat/long + bilingual names with bounded fan-out concurrency.
5. Emits one flat record per route, station, route-stop, or live ETA, capped by `maxItems`.

All endpoints are unauthenticated and operated by the Hong Kong government or a participating operator. No API key, no proxy, no auth headers required.

---

### Input

```json
{
  "mode": "route_list",
  "operator": "kmb",
  "maxItems": 15
}
````

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `mode` | string | `route_list` | One of `route_list`, `station_list`, `route_stops`, `stop_eta`. See modes below. |
| `operator` | string | `mtr` | One of `mtr`, `mtr_lr`, `kmb`, `citybus`. |
| `route` | string | `1A` | Bus route number (KMB / Citybus) or MTR line code (`TKL`, `ISL`, etc.). Required for `route_stops`, optional for `stop_eta` to filter. |
| `direction` | string | `outbound` | Direction. `outbound` / `inbound` for buses, `UP` / `DOWN` for MTR. Used by `route_stops`. |
| `stop_id` | string | — | Operator-specific stop identifier. Required for `stop_eta`. KMB uses 16-character hex (`A3ADFCDF8487ADB9`); Citybus uses 6-digit numeric (`001027`); MTR uses 3-letter station codes (`CEN`, `TST`); Light Rail uses 3-letter stop codes. |
| `mtr_line` | string | — | Required for `stop_eta` on MTR. The MTR Next Train API needs both station and line code. |
| `maxItems` | integer | `15` | Maximum records to emit. Default is 15 to keep test runs fast. Set higher for full inventory dumps. |
| `proxyConfiguration` | object | no proxy | HK Open Data APIs are public — proxy not required. Honoured if you opt in. |

#### Modes

| Mode | What it returns |
|------|-----------------|
| `route_list` | Every route operated by the chosen operator. |
| `station_list` | Full station / stop inventory with bilingual names and (for buses) lat/long coordinates. |
| `route_stops` | Ordered stop sequence for a single bus route. Bus-only — for MTR use `station_list`. |
| `stop_eta` | Real-time arrival ETAs at a single stop. |

#### Run examples

**KMB route catalogue:**

```json
{
  "mode": "route_list",
  "operator": "kmb",
  "maxItems": 1000
}
```

**MTR Tseung Kwan O Line — live arrivals at Tiu Keng Leng:**

```json
{
  "mode": "stop_eta",
  "operator": "mtr",
  "stop_id": "TIK",
  "mtr_line": "TKL"
}
```

**KMB bus 1A — full outbound stop list with bilingual names + lat/long:**

```json
{
  "mode": "route_stops",
  "operator": "kmb",
  "route": "1A",
  "direction": "outbound",
  "maxItems": 100
}
```

**Citybus stop ETAs at Central (Macao Ferry):**

```json
{
  "mode": "stop_eta",
  "operator": "citybus",
  "stop_id": "001027"
}
```

***

### Hong Kong Transit Scraper Output Fields

Every record carries a `record_type`. The unused fields for that record type are empty strings or `null`.

| `record_type` | Mode | Operator |
|---------------|------|----------|
| `route` | `route_list` | all |
| `station` | `station_list` | all |
| `route_stop` | `route_stops` | KMB, Citybus |
| `eta` | `stop_eta` | all |

#### Route record example (KMB)

```json
{
  "record_type": "route",
  "operator": "KMB",
  "service_type": "bus",
  "route_number": "1A",
  "route_origin_en": "STAR FERRY",
  "route_origin_zh": "尖沙咀碼頭",
  "route_dest_en": "SAU MAU PING (CENTRAL)",
  "route_dest_zh": "中秀茂坪",
  "direction": "inbound",
  "service_class": "1",
  "source_url": "https://data.etabus.gov.hk/v1/transport/kmb/route/",
  "scraped_at": "2026-05-02T16:56:14.723Z"
}
```

#### Station record example (MTR)

```json
{
  "record_type": "station",
  "operator": "MTR",
  "service_type": "metro",
  "line_code": "TKL",
  "line_name": "Tseung Kwan O Line",
  "direction": "DT",
  "station_code": "NOP",
  "station_name_en": "North Point",
  "station_name_zh": "北角",
  "sequence": 1,
  "source_url": "https://opendata.mtr.com.hk/data/mtr_lines_and_stations.csv",
  "scraped_at": "2026-05-02T16:56:14.723Z"
}
```

#### ETA record example (MTR live)

```json
{
  "record_type": "eta",
  "operator": "MTR",
  "service_type": "metro",
  "line_code": "TKL",
  "line_name": "Tseung Kwan O Line",
  "station_code": "TIK",
  "direction": "UP",
  "eta_seq": 1,
  "eta_time": "2026-05-03 00:36:28",
  "eta_minutes": 3,
  "eta_destination_en": "POA",
  "platform": "3",
  "source_url": "https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php?line=TKL&sta=TIK",
  "scraped_at": "2026-05-02T16:56:14.723Z"
}
```

#### Field reference

| Field | Type | Description |
|-------|------|-------------|
| `record_type` | string | `route`, `station`, `route_stop`, or `eta`. |
| `operator` | string | `MTR`, `MTR_LR`, `KMB`, or `CTB`. |
| `service_type` | string | `metro` / `light_rail` / `bus` / `airport_express`. |
| `route_number` | string | Bus route number or MTR line code. |
| `route_origin_en` / `route_origin_zh` | string | Origin terminus (English / Traditional Chinese). |
| `route_dest_en` / `route_dest_zh` | string | Destination terminus. |
| `direction` | string | `outbound` / `inbound` for buses; `UP` / `DOWN` for MTR. |
| `service_class` | string | KMB service variant. `1` is the primary route; higher numbers are alternates. |
| `line_code` / `line_name` | string | MTR line identifier and full name. |
| `station_code` | string | Operator-specific stop identifier. |
| `station_name_en` / `station_name_zh` | string | Stop / station name. |
| `sequence` | number | Stop sequence on a route (1-based). |
| `latitude` / `longitude` | number | WGS84 coordinates. Buses only — MTR catalogue does not publish coordinates. |
| `eta_seq` | number | ETA index (1, 2, 3 for the next three arrivals). |
| `eta_time` | string | ETA timestamp (ISO 8601 / HKT). |
| `eta_minutes` | number | Minutes to next arrival. |
| `eta_destination_en` / `eta_destination_zh` | string | Arriving service's destination. |
| `platform` | string | MTR platform number. |
| `remarks_en` / `remarks_zh` | string | Operator-published remark (e.g. "Bus is full", "Service ended"). |
| `data_timestamp` | string | Operator-published data timestamp. |
| `source_url` | string | Source endpoint the record was derived from. |
| `scraped_at` | string | ISO 8601 timestamp when the record was scraped. |

***

### FAQ

#### How do I scrape Hong Kong transit data?

Pick a mode (`route_list`, `station_list`, `route_stops`, `stop_eta`) and an operator (`mtr`, `mtr_lr`, `kmb`, `citybus`), then run. The scraper hits the right HKSAR open-data endpoint, normalizes the response, and emits flat records.

#### Does Hong Kong Transit Scraper need an API key?

No. The HKSAR open-data programme publishes these endpoints for free public use. No registration, no token, no rate-limit headers.

#### Does the scraper return fares?

Not in v1. Neither KMB nor Citybus expose fares via the open APIs, and MTR fares are a separate closed download. Fare modes are out of scope for this version.

#### What about Star Ferry, First Ferry, TurboJET, or HK Tramways?

Out of scope. Star Ferry, First Ferry, and TurboJET publish PDF schedules (no structured API). HK Tramways has no public data feed at all. Adding them would require HTML scraping that is materially more work than the API-only surface.

#### How do I find a stop ID for `stop_eta`?

Run `station_list` mode for the operator first. The `station_code` field on each record is the ID you pass to `stop_eta`. For MTR, also note the `line_code` — `stop_eta` on MTR needs both.

#### How fresh is the data?

ETAs are live (~30 second refresh). Route and stop catalogues are refreshed daily by KMB and Citybus, quarterly by MTR.

#### How many records does a full run produce?

Per operator at full inventory: KMB ~6,000 stops or ~1,600 route-direction-variants; Citybus ~3,000 stops or ~400 routes; MTR 99 stations × 2 directions = ~270 station rows; Light Rail ~70 stops. Set `maxItems` accordingly — default 15 keeps test runs fast.

***

### Need More Features?

Need ferry coverage, fare data, journey-planning A→B routing, or a GTFS-RT export? File an issue or get in touch.

### Why Use Hong Kong Transit Scraper?

- **Free APIs, low cost** — pay-per-event pricing, ~$0.0008 per record at the default coefficient. A full Hong Kong network catalogue dump costs less than a single Octopus tap.
- **Bilingual & normalized** — every record carries both English and Traditional Chinese names. Field names are consistent across MTR, KMB, Citybus, and Light Rail.
- **Stable** — no headless browser, no captcha solver, no scraping-the-DOM heuristics. Just public HKSAR open-data endpoints over HTTPS.

# Actor input Schema

## `sp_intended_usage` (type: `string`):

Please describe how you plan to use the data extracted by this crawler.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

Provide your email address so we can get in touch with you.

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

What to extract. route\_list returns every route the operator runs. station\_list returns the operator's full station / stop inventory with bilingual names and coordinates. route\_stops returns the ordered stop sequence for a single route. stop\_eta returns real-time arrival ETAs at a single stop.

## `operator` (type: `string`):

Which Hong Kong transit operator to query. MTR covers all heavy-rail lines (Island, Tsuen Wan, Kwun Tong, Tseung Kwan O, Tung Chung, Airport Express, East Rail, Tuen Ma, South Island, Disneyland Resort). MTR Light Rail covers Tuen Mun / Yuen Long routes 505-761P.

## `route` (type: `string`):

Required for route\_stops. Optional for stop\_eta (filters ETAs to one route). For KMB/Citybus this is the bus route number ('1A', '118'). For MTR this is the line code (TKL, ISL, EAL, TWL, KTL, TCL, AEL, TML, SIL, DRL). Ignored in route\_list and station\_list.

## `direction` (type: `string`):

Required for route\_stops. 'outbound' / 'inbound' for KMB/Citybus, 'UP' / 'DOWN' for MTR. Defaults to 'outbound'.

## `stop_id` (type: `string`):

Required for stop\_eta. Operator-specific stop identifier. KMB stop IDs are 16-character hex (e.g. 'A3ADFCDF8487ADB9'). Citybus stop IDs are 6-digit numbers ('001027'). MTR uses 3-letter station codes ('CEN', 'TST'). Light Rail uses 3-letter stop codes ('TML', 'TIK'). Run station\_list mode first to discover IDs.

## `mtr_line` (type: `string`):

Only used when operator='mtr' and mode='stop\_eta'. The MTR Next Train API requires both station code and line code. Examples: TKL, ISL, EAL, TWL, KTL, TCL, AEL, TML, SIL, DRL.

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

Maximum records to return. The Apify automated tester runs the default — keep small (15) for fast validation. Set higher (e.g. 1000+) for full inventory dumps.

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

Proxy not required — HKSAR open data APIs are public and keyless. Default: no proxy.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "mode": "route_list",
  "operator": "mtr",
  "route": "1A",
  "direction": "outbound",
  "maxItems": 15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "mode": "route_list",
    "operator": "mtr",
    "route": "1A",
    "direction": "outbound",
    "stop_id": "",
    "mtr_line": "",
    "maxItems": 15,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/hong-kong-transit-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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "mode": "route_list",
    "operator": "mtr",
    "route": "1A",
    "direction": "outbound",
    "stop_id": "",
    "mtr_line": "",
    "maxItems": 15,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/hong-kong-transit-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "mode": "route_list",
  "operator": "mtr",
  "route": "1A",
  "direction": "outbound",
  "stop_id": "",
  "mtr_line": "",
  "maxItems": 15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call jungle_synthesizer/hong-kong-transit-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=jungle_synthesizer/hong-kong-transit-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Hong Kong Transit Scraper - MTR, KMB, Citybus, Light Rail",
        "description": "Hong Kong public transit data via the official HKSAR open APIs: MTR (10 lines), KMB and Citybus bus networks, and MTR Light Rail. Bilingual English / Traditional Chinese station names, real-time train and bus ETAs, full route catalogues.",
        "version": "1.0",
        "x-build-id": "8RSnVSfRoNsLCXPNK"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/jungle_synthesizer~hong-kong-transit-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-jungle_synthesizer-hong-kong-transit-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/jungle_synthesizer~hong-kong-transit-scraper/runs": {
            "post": {
                "operationId": "runs-sync-jungle_synthesizer-hong-kong-transit-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/jungle_synthesizer~hong-kong-transit-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-jungle_synthesizer-hong-kong-transit-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "sp_intended_usage": {
                        "title": "What is the intended usage of this data?",
                        "minLength": 1,
                        "type": "string",
                        "description": "Please describe how you plan to use the data extracted by this crawler."
                    },
                    "sp_improvement_suggestions": {
                        "title": "How can we improve this crawler for you?",
                        "minLength": 1,
                        "type": "string",
                        "description": "Provide any feedback or suggestions for improvements."
                    },
                    "sp_contact": {
                        "title": "Contact Email",
                        "minLength": 1,
                        "type": "string",
                        "description": "Provide your email address so we can get in touch with you."
                    },
                    "mode": {
                        "title": "Scrape Mode",
                        "enum": [
                            "route_list",
                            "station_list",
                            "route_stops",
                            "stop_eta"
                        ],
                        "type": "string",
                        "description": "What to extract. route_list returns every route the operator runs. station_list returns the operator's full station / stop inventory with bilingual names and coordinates. route_stops returns the ordered stop sequence for a single route. stop_eta returns real-time arrival ETAs at a single stop.",
                        "default": "route_list"
                    },
                    "operator": {
                        "title": "Operator",
                        "enum": [
                            "mtr",
                            "mtr_lr",
                            "kmb",
                            "citybus"
                        ],
                        "type": "string",
                        "description": "Which Hong Kong transit operator to query. MTR covers all heavy-rail lines (Island, Tsuen Wan, Kwun Tong, Tseung Kwan O, Tung Chung, Airport Express, East Rail, Tuen Ma, South Island, Disneyland Resort). MTR Light Rail covers Tuen Mun / Yuen Long routes 505-761P.",
                        "default": "mtr"
                    },
                    "route": {
                        "title": "Route Number",
                        "type": "string",
                        "description": "Required for route_stops. Optional for stop_eta (filters ETAs to one route). For KMB/Citybus this is the bus route number ('1A', '118'). For MTR this is the line code (TKL, ISL, EAL, TWL, KTL, TCL, AEL, TML, SIL, DRL). Ignored in route_list and station_list."
                    },
                    "direction": {
                        "title": "Direction",
                        "enum": [
                            "outbound",
                            "inbound",
                            "UP",
                            "DOWN"
                        ],
                        "type": "string",
                        "description": "Required for route_stops. 'outbound' / 'inbound' for KMB/Citybus, 'UP' / 'DOWN' for MTR. Defaults to 'outbound'.",
                        "default": "outbound"
                    },
                    "stop_id": {
                        "title": "Stop / Station ID",
                        "type": "string",
                        "description": "Required for stop_eta. Operator-specific stop identifier. KMB stop IDs are 16-character hex (e.g. 'A3ADFCDF8487ADB9'). Citybus stop IDs are 6-digit numbers ('001027'). MTR uses 3-letter station codes ('CEN', 'TST'). Light Rail uses 3-letter stop codes ('TML', 'TIK'). Run station_list mode first to discover IDs."
                    },
                    "mtr_line": {
                        "title": "MTR Line (for stop_eta on MTR only)",
                        "type": "string",
                        "description": "Only used when operator='mtr' and mode='stop_eta'. The MTR Next Train API requires both station code and line code. Examples: TKL, ISL, EAL, TWL, KTL, TCL, AEL, TML, SIL, DRL."
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "type": "integer",
                        "description": "Maximum records to return. The Apify automated tester runs the default — keep small (15) for fast validation. Set higher (e.g. 1000+) for full inventory dumps.",
                        "default": 15
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy not required — HKSAR open data APIs are public and keyless. Default: no proxy."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
