Realtime APIs
Transport API (GTFS-R)

GTFS Realtime API Endpoint

GET https://api.data.gov.my/gtfs-realtime/<feed>/<agency>

What does GTFS Realtime do?

GTFS Realtime is an extension of the GTFS Static API that enables public transportation agencies to share live trip updates, service alerts and vehicle positions. At present, our GTFS Realtime API only offers vehicle position data - service alerts and and trip updates are in our pipeline for 2024-25. For more details on GTFS Realtime and its broader functionalities, please refer to https://gtfs.org/realtime/ (opens in a new tab).

Important note: We are building iteratively

This is the first time that Malaysia has had an official and freely-usable GTFS API. It is the result of months of hard work and collaboration between the data.gov.my developer team and various public transport operators. It is by no means complete; there are plenty of services that will only be integrated over the coming months and years. Furthermore, the Realtime API in particular needs a lot of work; the documentation for each endpoint transparently details known errors so that developers using the API are aware of its current limitations (and are aware that we are aware!).

However, we felt that it was time to go live - so that the private sector and public transport community could begin building from it, and most crucially, giving us feedback on how to improve it. If you have any feedback on the GTFS API, please write to us at data.dtsa@jdn.gov.my - we welcome any and all constructive feedback!

Note: The validation errors specific to each feed in the Vehicle Position section were generated using using the GTFS Realtime Validator (opens in a new tab).

Source of GTFS Realtime Data

The GTFS Realtime API incorporates data from various transport agencies in Malaysia. Currently, the following agencies contribute their transit data:

Request Query & Response Format

The GTFS Realtime API adheres to the standard GTFS Realtime protobuf format (.proto). The detailed format is available in the official GTFS Realtime reference (opens in a new tab), and you can access the protobuf files through the following endpoints:

Vehicle Position

GET https://api.data.gov.my/gtfs-realtime/vehicle-position/<agency>

Frequency of Data Update

  • All Vehicle Position feeds are updated every 30 seconds.

myBAS Johor Bahru

GET https://api.data.gov.my/gtfs-realtime/vehicle-position/mybas-johor
# .proto file is returned
  • Known errors:
    • E003 (opens in a new tab): GTFS-rt trip_id does not exist in GTFS data
      • ~50% of trips are undefined in GTFS Static.
    • E004 (opens in a new tab): GTFS-rt route_id does not exist in GTFS data
      • ~15% of the routes are undefined in GTFS Static.
    • E023 (opens in a new tab) - trip start_time does not match first GTFS arrival_time
      • start_time is invalid; this requires minor fixes to operational systems.
    • E028 (opens in a new tab) - Vehicle position outside agency coverage area
      • Does not invalidate the feed per se, but implies that improvements to the static endpoint are needed.

KTMB

GET https://api.data.gov.my/gtfs-realtime/vehicle-position/ktmb
# .proto file is returned

Prasarana

GET https://api.data.gov.my/gtfs-realtime/vehicle-position/prasarana?category=<category>
# .proto file is returned
  • Possible <category> values are rapid-bus-kl , rapid-bus-mrtfeeder, rapid-bus-kuantan and rapid-bus-penang.
    • rapid-rail-kl, for which static endpoint is available, does not yet have stable realtime feeds.
  • Known errors affecting rapid-bus-kuantan and rapid-bus-penang:
    • E003 (opens in a new tab): GTFS-rt trip_id does not exist in GTFS data
    • E004 (opens in a new tab): GTFS-rt route_id does not exist in GTFS data
      • These errors are due to issues with legacy operational systems (some more than a decade old) which cannot support tracking trips and routes properly, yet. Our team is actively working to alleviate these constraints to make the feed meaningful and compliant.
  • Known issue with rapid-bus-penang:
    • Developers need to match trip IDs in the realtime feed with existing trip IDs in the static schedule. This can be achieved by comparing the portion of the ID that comes after the service ID prefix.
      • For example, the GTFS Realtime trip ID 30000001_1000000855_053000_02 corresponds to trip IDs in the static schedule such as:
        • weekend_30000001_1000000855_053000_02
        • weekday_30000001_1000000855_053000_02
        • 23102302_30000001_1000000855_053000_02
      • We took the decision not to modify the realtime feed received from operational systems to avoid jeopardising performance; a deeper fix will be deployed in future to ensure out-of-the-box synchronicity between the realtime and static trip IDs.

Understanding the data

To properly parse the protobuf data, refer to the official GTFS Realtime language bindings (opens in a new tab) for guidance on decoding the information. Below is a concise Python example illustrating how to read RapidKL (bus) vehicle position data from the GTFS Realtime API:

# pip install gtfs-realtime-bindings pandas requests
from google.transit import gtfs_realtime_pb2
from google.protobuf.json_format import MessageToDict
import pandas as pd
from requests import get
 
# Sample GTFS-R URL from Malaysia's Open API
URL = 'https://api.data.gov.my/gtfs-realtime/vehicle-position/prasarana?category=rapid-bus-kl'
 
# Parse the GTFS Realtime feed
feed = gtfs_realtime_pb2.FeedMessage()
response = get(URL)
feed.ParseFromString(response.content)
 
# Extract and print vehicle position information
vehicle_positions = [MessageToDict(entity.vehicle) for entity in feed.entity]
print(f'Total vehicles: {len(vehicle_positions)}')
df = pd.json_normalize(vehicle_positions)
print(df)