Vehicle position
STIB: brussels metro, tram and bus operator
- Format
- GeoJSON
- Updates
- Every 20 seconds (computed from vehicle-distance)
- Latest snapshot
- Snapshots stored
- about 3,551,950
curl -H "Authorization: Bearer $MOBILITYTWIN_TOKEN" "https://api.mobilitytwin.brussels/stib/vehicle-trip"
Every STIB/MIVB vehicle on the road, every 20 seconds, with the GTFS trip it is running and its delay.
STIB's real-time API gives each vehicle's position on its line. This endpoint tracks each vehicle from poll to poll under the constraint that vehicles on a line do not overtake each other, reads its stop calls as they happen, and pairs the vehicles on the road with the timetabled trips that could be running by the smallest total deviation between observed and scheduled times. It is the live form of the method behind the punctuality table.
Each feature carries uuid (stable for as long as the vehicle is tracked on one run), lineId, directionId (the destination stop), direction (GTFS direction_id), pointId and distanceFromPoint, routeId, and where a trip was established tripId, startDate, startTime, delay (seconds late at the last stop called at, negative when early), stopId and stopSequence (the stop the vehicle is at or heading to) and status (STOPPED_AT or IN_TRANSIT_TO).
A vehicle gets its trip after its second stop call, about a minute after leaving its first stop; a vehicle still waiting at its first stop has none, since which waiting vehicle makes the next departure is not knowable from the feed. Measured over a full replayed day, 91% of the vehicles that had left their first stop carried a trip, and 93% of those trips were the ones the daily method assigns with the whole day in hand (88% at the morning peak, 97% off-peak). For long time ranges, download Parquet files from /stib/vehicle-trip/parquet.
Which days have data
Data from 5 Apr 2024 to 2 Nov 2026, on 892 days. 30 of the last 30 days have data. A typical day holds 3889 snapshots. Days are in UTC.
- Full day
- Partial, 50–90% of a typical day
- Low, under 50%
- No snapshot
- Not expected
Click a day above, or pick a date, to get its requests.
Downloading weeks or months
Do not fetch snapshots one by one for long ranges. /stib/vehicle-trip/parquet gives you ready-made Parquet files, one per day.
Parameters
| Name | Meaning |
|---|---|
timestamp | Return the last snapshot at or before this moment, in Unix seconds or ISO 8601 (e.g. 2026-05-06T12:00:00Z). Without it, the latest snapshot is returned. |
Response fields
A GeoJSON FeatureCollection. Field names without a prefix are in each feature's properties.
| Field | Type | Meaning |
|---|---|---|
uuid | string | Tracking uuid, stable for as long as the vehicle is tracked on one run. Same value as the feature id. |
lineId | string | STIB line number (GTFS route_short_name) |
directionId | string | Destination stop id as reported by STIB |
direction | integer | GTFS direction_id |
pointId | string | Stop point last passed, as reported by STIB |
distanceFromPoint | number | Metres past pointId |
color | string or null | Line colour from the GTFS routes |
routeId | string or null | GTFS route_id |
timestamp | number | Unix timestamp of the poll |
tripId | string or null | GTFS trip_id, null until established (after the vehicle's second stop call) |
startDate | string or null | Service date of the trip, YYYYMMDD |
startTime | string or null | Scheduled departure of the trip, HH:MM:SS (may exceed 24:00) |
delay | integer or null | Seconds late at the last stop called at; negative when early |
status | string or null | STOPPED_AT or IN_TRANSIT_TO; null on the metro (lines 1, 2, 5, 6), whose feed gives the station but no distance, so standing and running cannot be told apart |
stopId | string or null | GTFS stop_id the vehicle is at or heading to |
stopSequence | integer or null | stop_sequence of that stop in the trip |
Python example
import requests
url = "https://api.mobilitytwin.brussels/stib/vehicle-trip"
data = requests.get(url, headers={
'Authorization': 'Bearer [MY_API_KEY]'
}).json()
# Every vehicle on the road, with its GTFS trip and delay where established
for feature in data["features"]:
p = feature["properties"]
if p["tripId"]:
print(f"Line {p['lineId']} trip {p['tripId']} ({p['startTime']}): "
f"{p['delay']:+d} s, {p['status']} stop {p['stopId']}")
else:
print(f"Line {p['lineId']} vehicle {p['uuid'][:8]}: no trip yet")