OrbTop

Singapore Transit Scraper — MRT, LRT, Bus via LTA DataMall

TRAVELBUSINESSDEVELOPER TOOLS

Singapore Transit Scraper — MRT, LRT, Bus via LTA DataMall

Extracts Singapore public transit data from the LTA DataMall REST API. Covers real-time bus arrivals, full bus stop inventories with GPS coordinates, bus service definitions, route-stop sequences, and live MRT/LRT service alerts — five modes, one actor, free government API.


Singapore Transit Scraper Features

  • Extracts real-time bus arrival ETAs for any bus stop — next three buses, loading status, wheelchair access, bus type (single/double deck/bendy)
  • Returns the complete inventory of ~5,400 bus stops with latitude, longitude, and road name
  • Collects all ~600 bus service definitions including operator, first/last bus times by day type, and service category
  • Downloads ~30,000 bus route-stop records with stop sequences and cumulative distance from origin
  • Fetches current MRT/LRT service alerts — normal-service status or disruption details with affected segments and timestamps
  • Pure API — no browser, no proxy, no HTML parsing. DataMall is a public government endpoint with no geo-restrictions.
  • A valid LTA DataMall AccountKey is required. Registration is free at datamall.lta.gov.sg.

What Can You Do with Singapore Transit Data?

  • MaaS developers — Build real-time arrival displays, trip planners, or transit apps on top of official LTA data rather than scraping operator websites
  • Logistics and last-mile planners — Map bus stop locations against delivery zones to identify coverage gaps or plan fleet positioning
  • Urban mobility researchers — Analyse Singapore's route network structure, service frequency by area, or first/last bus timing coverage
  • Transit alert systems — Monitor MRT/LRT disruptions in real time and trigger notifications for affected commuters or services
  • Data journalists — Track service changes, new routes, and LTA schedule adjustments over time
  • Fintech and PropTech analysts — Score properties by transit access using bus stop density, route counts, and MRT proximity

How Singapore Transit Scraper Works

  1. Choose a mode. Five modes cover different data types: bus_arrival for real-time ETAs, bus_stops / bus_services / bus_routes for the static network inventories, and train_alerts for live MRT/LRT status.
  2. Provide your LTA AccountKey. The scraper passes it as the AccountKey header on every request. The DataMall API enforces authentication on all endpoints.
  3. The scraper calls the API. For bus_arrival and train_alerts, it's a single request. For the three static modes, it pages through results in batches of 500 using $skip until it hits your maxItems limit or exhausts the dataset.
  4. Results land in the Apify dataset. Each record is a flat JSON object. A record_type field tells you which mode produced it, so mixed exports stay sorted.

Input

{
  "mode": "bus_arrival",
  "ltaApiKey": "your-lta-accountkey-here",
  "busStopCode": "83139",
  "serviceNo": "",
  "maxItems": 15,
  "sp_intended_usage": "Real-time bus arrival display for commuters",
  "sp_improvement_suggestions": "n/a"
}
Field Type Default Description
mode string bus_arrival Which dataset to fetch. One of: bus_arrival, bus_stops, bus_services, bus_routes, train_alerts.
ltaApiKey string (required) Your LTA DataMall AccountKey. Free registration at datamall.lta.gov.sg.
busStopCode string 83139 5-digit bus stop code. Required for bus_arrival mode. Run bus_stops mode to find codes.
serviceNo string (empty) Filter by bus service number (e.g. 857, 65M). Optional — omit to return all services at the stop.
maxItems integer 15 Max records to return. Caps pagination for bus_stops, bus_services, and bus_routes. Set high for full inventories.

Additional examples by mode:

{
  "mode": "bus_stops",
  "ltaApiKey": "your-lta-accountkey-here",
  "maxItems": 5400
}
{
  "mode": "train_alerts",
  "ltaApiKey": "your-lta-accountkey-here",
  "maxItems": 10
}

Singapore Transit Scraper Output Fields

Output varies by mode. Every record includes record_type, source_url, and scraped_at.

bus_arrival

{
  "record_type": "arrival",
  "operator": "SMRT",
  "service_no": "858",
  "stop_code": "83139",
  "eta_1_time": "2026-05-05T06:14:22.000Z",
  "eta_1_minutes": 3,
  "eta_1_load": "SEA",
  "eta_1_feature": "WAB",
  "eta_1_type": "SD",
  "eta_2_time": "2026-05-05T06:23:10.000Z",
  "eta_2_minutes": 12,
  "eta_2_load": "SDA",
  "eta_2_type": "DD",
  "eta_3_time": "2026-05-05T06:34:55.000Z",
  "eta_3_minutes": 23,
  "eta_3_load": "SEA",
  "eta_3_type": "SD",
  "bus_load": "SEA",
  "bus_feature": "WAB",
  "source_url": "https://datamall2.mytransport.sg/ltaodataservice/v3/BusArrival?BusStopCode=83139",
  "scraped_at": "2026-05-05T06:11:00.000Z"
}
Field Type Description
record_type string Always arrival for this mode
operator string Bus operator: SMRT, SBS Transit, Tower Transit, Go-Ahead Singapore
service_no string Bus service number
stop_code string 5-digit bus stop code
eta_1_time string ISO 8601 arrival time for next bus
eta_1_minutes number Minutes until next bus arrives
eta_1_load string SEA (seats available), SDA (standing available), LSD (limited standing)
eta_1_feature string WAB = wheelchair accessible bus
eta_1_type string SD = single deck, DD = double deck, BD = bendy
eta_2_time string Arrival time for 2nd next bus
eta_2_minutes number Minutes until 2nd next bus
eta_2_load string Passenger load for 2nd bus
eta_2_type string Bus type for 2nd bus
eta_3_time string Arrival time for 3rd next bus
eta_3_minutes number Minutes until 3rd next bus
eta_3_load string Passenger load for 3rd bus
eta_3_type string Bus type for 3rd bus
bus_load string Alias for eta_1_load
bus_feature string Alias for eta_1_feature
source_url string DataMall endpoint URL
scraped_at string ISO 8601 extraction timestamp

bus_stops

{
  "record_type": "stop",
  "stop_code": "83139",
  "stop_name": "Bedok Int",
  "road_name": "New Upper Changi Rd",
  "latitude": 1.32479,
  "longitude": 103.93002,
  "source_url": "https://datamall2.mytransport.sg/ltaodataservice/BusStops?$skip=0",
  "scraped_at": "2026-05-05T06:11:00.000Z"
}
Field Type Description
record_type string Always stop
stop_code string 5-digit bus stop code
stop_name string Official stop name / description
road_name string Road the stop is on
latitude number WGS84 latitude
longitude number WGS84 longitude

bus_services

{
  "record_type": "service",
  "service_no": "858",
  "operator": "SMRT",
  "direction": 1,
  "service_type": "TRUNK",
  "category": "TRUNK",
  "origin_code": "46009",
  "destination_code": "84009",
  "loop_desc": "",
  "first_bus_weekday": "0430",
  "last_bus_weekday": "2330",
  "first_bus_saturday": "0500",
  "last_bus_saturday": "2330",
  "first_bus_sunday": "0530",
  "last_bus_sunday": "2330",
  "source_url": "https://datamall2.mytransport.sg/ltaodataservice/BusServices?$skip=0",
  "scraped_at": "2026-05-05T06:11:00.000Z"
}
Field Type Description
record_type string Always service
service_no string Bus service number
operator string Bus operator
direction number 1 = outbound, 2 = inbound
service_type string Service category
category string EXPRESS, FEEDER, INDUSTRIAL, TOWNLINK, TRUNK, NIGHT SERVICE, CITY_DIRECT, FLAT_FEE_BUS
origin_code string First stop code
destination_code string Last stop code
loop_desc string Loop terminal description (looping services only)
first_bus_weekday string First departure time on weekdays (HHMM)
last_bus_weekday string Last departure time on weekdays (HHMM)
first_bus_saturday string First departure on Saturdays (HHMM)
last_bus_saturday string Last departure on Saturdays (HHMM)
first_bus_sunday string First departure on Sundays/PH (HHMM)
last_bus_sunday string Last departure on Sundays/PH (HHMM)

bus_routes

{
  "record_type": "route_stop",
  "service_no": "858",
  "operator": "SMRT",
  "direction": 1,
  "sequence": 1,
  "stop_code": "46009",
  "distance_km": 0.0,
  "first_bus_weekday": "0430",
  "last_bus_weekday": "2330",
  "first_bus_saturday": "0500",
  "last_bus_saturday": "2330",
  "first_bus_sunday": "0530",
  "last_bus_sunday": "2330",
  "source_url": "https://datamall2.mytransport.sg/ltaodataservice/BusRoutes?$skip=0",
  "scraped_at": "2026-05-05T06:11:00.000Z"
}
Field Type Description
record_type string Always route_stop
service_no string Bus service number
operator string Bus operator
direction number 1 = outbound, 2 = inbound
sequence number Stop sequence on this route (1-based)
stop_code string 5-digit bus stop code
distance_km number Cumulative distance from route origin in km
first_bus_weekday string First departure from this stop on weekdays (HHMM)
last_bus_weekday string Last departure from this stop on weekdays (HHMM)
first_bus_saturday string First departure on Saturdays (HHMM)
last_bus_saturday string Last departure on Saturdays (HHMM)
first_bus_sunday string First departure on Sundays/PH (HHMM)
last_bus_sunday string Last departure on Sundays/PH (HHMM)

train_alerts

{
  "record_type": "train_alert",
  "train_alert_status": "Disrupted",
  "affected_segments": "CCL:City:Caldecott:Bartley",
  "train_alert_message": "05:00-CCL-Planned Service Adjustment. Circle Line train services will end earlier at 11.00pm on Saturday nights.",
  "train_alert_created_at": "2026-04-10T00:15:58.000Z",
  "source_url": "https://datamall2.mytransport.sg/ltaodataservice/TrainServiceAlerts",
  "scraped_at": "2026-05-05T06:11:00.000Z"
}
Field Type Description
record_type string Always train_alert
train_alert_status string Normal or Disrupted
affected_segments string MRT/LRT segments affected, comma-separated (empty when Normal)
train_alert_message string Human-readable alert text from LTA
train_alert_created_at string ISO 8601 timestamp of the alert

FAQ

How do I get an LTA DataMall API key?

Singapore Transit Scraper requires a free AccountKey from LTA DataMall. Fill out the registration form — name, company, email, intended use — and LTA sends the key by email. Registration is free for any use case. Most applicants receive their key within a business day.

How much does Singapore Transit Scraper cost to run?

Singapore Transit Scraper charges $0.10 per actor start plus $0.0008 per record. A full bus stop inventory (~5,400 records) runs roughly $4.40 total. Real-time arrivals for a single stop return 3–15 records, making it a few cents per call. Train alerts return a handful of messages at most.

What transit data does LTA DataMall provide?

Singapore Transit Scraper wraps five LTA DataMall datasets: real-time bus arrivals, the complete bus stop network (5,400 stops with GPS), all bus services (600), bus route-stop sequences (~30,000 records), and current MRT/LRT alerts. MRT timetables, taxi availability, ERP gantry data, and parking availability are separate DataMall endpoints not covered in this actor.

Does Singapore Transit Scraper need proxies?

No. LTA DataMall is a Singapore government API with no geo-restrictions and no aggressive rate limiting. The scraper runs without proxy configuration and adds a 200ms courtesy delay between paginated requests.

Can I get arrivals for multiple bus stops in one run?

bus_arrival mode takes one busStopCode per actor run. To query multiple stops, trigger parallel runs via the Apify API. Use bus_stops mode first to build a complete stop list with codes.


Need More Features?

Need additional DataMall endpoints, multi-stop arrival batching, or scheduled monitoring? File a request or get in touch.

Why Use Singapore Transit Scraper?

  • Official data — Sourced directly from LTA DataMall, Singapore's authoritative transit data source. The same data that powers the MyTransport.SG app.
  • Five datasets in one actor — Real-time arrivals, bus stops, services, routes, and train alerts without managing multiple API integrations or paginating $skip loops yourself.
  • No infrastructure overhead — No browser, no proxy, no fragile HTML parsing. DataMall returns clean JSON; Singapore Transit Scraper normalizes it into flat records and handles pagination, retries, and rate limiting.