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"
Get a token

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.

2026
JanFebMarAprMayJunJulAugSepOctNovDec
2025
JanFebMarAprMayJunJulAugSepOctNovDec
2024
JanFebMarAprMayJunJulAugSepOctNovDec
  • 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

NameMeaning
timestampReturn 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.

FieldTypeMeaning
uuidstringTracking uuid, stable for as long as the vehicle is tracked on one run. Same value as the feature id.
lineIdstringSTIB line number (GTFS route_short_name)
directionIdstringDestination stop id as reported by STIB
directionintegerGTFS direction_id
pointIdstringStop point last passed, as reported by STIB
distanceFromPointnumberMetres past pointId
colorstring or nullLine colour from the GTFS routes
routeIdstring or nullGTFS route_id
timestampnumberUnix timestamp of the poll
tripIdstring or nullGTFS trip_id, null until established (after the vehicle's second stop call)
startDatestring or nullService date of the trip, YYYYMMDD
startTimestring or nullScheduled departure of the trip, HH:MM:SS (may exceed 24:00)
delayinteger or nullSeconds late at the last stop called at; negative when early
statusstring or nullSTOPPED_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
stopIdstring or nullGTFS stop_id the vehicle is at or heading to
stopSequenceinteger or nullstop_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")