
Public transport data via the NDOV desk
The NDOV desk collects timetables and live trip information from Dutch transport operators, from Arriva and Connexxion to GVB, RET and NS. Stichting OpenGeo runs the desk under the name GOVI and publishes the data under CC0: timetables in NeTEx, the stop register and live positions and delays. There is also a ready-made GTFS version for the whole country.

Buses, trams and metros with a live position, by operator: most Qbuzz (39 vehicles), then Connexxion and EBS
Buses, trams and metros with a live position, by operator, October 2026, in vehicles. Total: 95; the largest 7 of 7 categories are shown. Qbuzz is 41% of the total. Snapshot of Sunday, 25 October 2026 at 03:33: buses, trams and metros with a live position. Trains are in a separate file.
What you can build with it2
DashboardTrain delay and disruption dashboardA page that shows every minute how many trains are running, which ones are late and which disruptions are going on, built on the open GTFS-Realtime file from openOV and, with a free key, the NS disruptions.2 sourcesGetting started
MapLive map of buses, trams and metrosA map on which every bus, tram and metro in the Netherlands moves live, coloured by delay, from one open 180 kB file and without a key.1 sourcesGetting startedWhat can you do with it?4 ideas
How far is the nearest stop?
Put the GTFS stops on a map with addresses or neighbourhoods. Count per neighbourhood how many stops lie within 400 metres and how often something departs per hour.
Live map of all buses
The vehicle positions file is refreshed continuously. On 15 October 2026 around 10.30 pm it held 1,658 vehicles.
Which lines are late most often?
Store the trip updates for a few weeks and compare expected with scheduled times. For longer periods Stichting OpenGeo supplies historical vehicle data on request, over ten years according to its FAQ.
What disappears from the timetable?
Compare the current NeTEx or GTFS timetable with that of a year earlier. Count per municipality the trips that are gone.
How to process it5 steps
Start with GTFS
openOV converts the NDOV data to GTFS for the whole country. The zip is large: 251 MB on 14 October 2026. Ask for Last-Modified with a HEAD request first and only download when something changed.
curl -I https://gtfs.ovapi.nl/nl/gtfs-nl.zip
Live positions and delays
The same folder has GTFS-Realtime files in protobuf: vehiclePositions.pb (positions), tripUpdates.pb (expected times), alerts.pb and trainUpdates.pb.
https://gtfs.ovapi.nl/nl/vehiclePositions.pb
Source data in NeTEx and the stop register
data.ndovloket.nl is an open folder. Under netex/ there is a daily NeTEx file per operator, under haltes/ the central stop register (CHB) as gzipped XML.
https://data.ndovloket.nl/
Real-time from the source via ZeroMQ
If you want the raw streams (KV6 positions, KV17 trip changes, NS InfoPlus, SIRI), subscribe via ZeroMQ to an envelope such as /ARR/KV6posinfo. Best effort, at most one connection per user per stream.
tcp://pubsub.besteffort.ndovloket.nl:7658
Be frugal
openOV asks you to identify yourself in the User-Agent, use If-Modified-Since and accept gzip. Timetables rarely change more than once a day; the new service day starts at 03:00 UTC.
Interesting combinations


Do lower-income neighbourhoods have worse public transport?
Work out the neighbourhood of each stop, count departures per neighbourhood and compare with income and car ownership from the key figures.


Is the bus stuck in the same jam as the car?
Compare delays of bus trips on a route with measured speed on the road alongside.
Similar sources
- NNS travel information
Trains only, through NS's own API, with a key. Includes disruptions, crowding and rolling stock.
- OOOVapi en openOV not in the index yet
The GTFS and GTFS-Realtime files on this page come from here, built from NDOV data by Bliksem Labs.
What to watch out for
- Best effort, no guarantee
The open streams have no service agreement. For a guaranteed connection, sign a user agreement with GOVI. There is no technical support; questions go to the OpenOV Discord.
- Not every operator delivers everything
According to GOVI the large operators deliver planned and live data, but for FlixBus, the Westerschelde Ferry and German operators, for example, there is only a timetable. Check the overview on the datasets page.
- No history in the open files
The real-time files show only the present. To measure punctuality, store them yourself or request historical data.
- Don't pose as an operator
The openOV licence allows everything except claiming to represent one of the operators. Report data errors at ovdata.nl.
APIGTFS / GTFS-RT (protobuf), NeTEx-bestanden en REST (JSON) · read 16 Oct 2026
No key or account for the files, GTFS-RT and v0.ovapi.nl. A recognisable User-Agent is required (openOV usage rule). A guaranteed real-time connection needs a signed NDOV user agreement. tested
vehicles in vehiclePositions.pb, from 8 operators (16 Oct 2026, 23:36) tested
gtfs (zip)protobufnetex (xml.gz)json
Base URL
https://gtfs.ovapi.nl/nl
Endpoints 6
- GET
/gtfs-nl.zipTimetable of the whole Netherlands in GTFS (241 MB; daily, last 16 Oct 2026 18:58 UTC). Contains stops.txt (7 MB), routes.txt, trips.txt (75 MB), stop_times.txt (1.17 GB unzipped), shapes.txt (289 MB), calendar_dates.txt, transfers.txt and feed_info.txt, among others. - GET
/vehiclePositions.pbGTFS-Realtime: position of every vehicle in service with trip, stop and delay (192 kB, new every minute). - GET
/tripUpdates.pbGTFS-Realtime: expected arrival and departure times per trip and stop (1.9 MB). - GET
/trainUpdates.pbGTFS-Realtime for trains, with scheduled and actual platform (1.3 MB). - GET
/alerts.pbGTFS-Realtime: disruptions and notices (461 kB). - GET
/archive/Older GTFS files by date (NL-YYYYMMDD.gtfs.zip, 170–210 MB each, from 1 January 2026).
The APIs of this source 3 · from the provider's documentation from the description
NDOV-loket open map (bron in NeTEx)
The source data as delivered by operators, CC0. Plain file folder, no robots.txt.
https://data.ndovloket.nl- GET
/netex/<vervoerder>/NeTEx-dienstregeling per vervoerder (arr, cxx, ebs, gvb, htm, keolis, qbuzz, ret …), bv. GVB 4,6 MB gezipt per week - GET
/haltes/ExportCHB_<datum>.xml.gzCentraal Haltebestand (CHB), dagelijks, 13 MB; plus PassengerStopAssignmentExportCHB (1,0 MB) - GET
/ns/Dienstregeling NS (ns-latest.zip, 9,1 MB) en stationsgegevens - GET
/tarieven/Tarieven per vervoerder - GET
/docs/Koppelvlakdocumentatie (KV78Turbo, InfoPlus, BISON …)
Realtime via ZeroMQ (best effort)
Raw real-time streams; subscribe to an envelope such as /ARR/KV6posinfo. At most one connection per user per stream; abuse leads to a block.
tcp://pubsub.besteffort.ndovloket.nl- SUB
:7658BISON KV6 (posities), KV15 (berichten), KV17 (ritwijzigingen) per vervoerder - SUB
:7817KV78Turbo (verwachte doorkomsttijden) - SUB
:7664NS InfoPlus (o.a. DVS vertrektijden, treinposities) - SUB
:7666SIRI
OVapi KV78Turbo (REST, JSON)
Expected departure times per stop, line or journey as JSON, built from KV78Turbo. HTTP only (HTTPS gives a certificate error). Supports gzip.
http://v0.ovapi.nl- GET
/tpc/{TimingPointCode}Haltegegevens en de komende ~20 doorkomsten (Passes) met verwachte en geplande tijden; meerdere codes met komma's - GET
/tpc/Alle 38.395 haltecodes (125 kB gezipt) - GET
/stopareacode/{code}Alle haltes in een haltegebied; /stopareacode/ geeft er 4.595 - GET
/line/{lijn}Lijn met haltes en actuele ritten, bv. GVB_24_1; /line/ geeft er 4.164 - GET
/journey/{rit}Eén rit met alle haltes, bv. GVB_20261016_24_51324_0
Filtering tested
No query language: the feeds are whole files for the whole Netherlands. Filter yourself on agency, route or stop_id. With v0.ovapi.nl you pick a stop, line or journey in the path.
Parameters 3
If-None-Match / If-Modified-Since | openOV usage rule: only fetch again when something changed. Unchanged gives 304 with no body (tested on gtfs-nl.zip). | tested |
Accept-Encoding | gzip; required by openOV's usage rules, also useful with v0.ovapi.nl. | from the description |
User-Agent | Say who you are, with contact details; that lets openOV work without registration. | from the description |
Fields in GTFS-RT, GTFS and v0.ovapi.nl (selection) 9
| Name | Type | Meaning |
|---|---|---|
entity.id | tekst | Datum:vervoerder:lijn:rit, bv. 2026-10-16:CXX:M340:242 (vehiclePositions) |
vehicle.trip.trip_id / route_id / start_date | tekst | Rit in de GTFS-dienstregeling; koppel met trips.txt |
vehicle.position.latitude / longitude | getal · graden WGS84 | Positie van het voertuig |
vehicle.stop_id / current_stop_sequence / current_status | tekst | Halte waar het voertuig is of naartoe rijdt |
vehicle.timestamp | integer · Unix-tijd (s) | Tijdstip van de positie |
ovapi_vehicle_position.delay | integer · s | Vertraging bij de volgende halte; negatief = te vroeg (OVapi-uitbreiding) |
ExpectedDepartureTime / TargetDepartureTime | datetime · lokale tijd | Verwachte en geplande vertrektijd (v0.ovapi.nl, Passes) |
TripStopStatus | tekst | Status van de doorkomst, bv. DRIVING (v0.ovapi.nl) |
stop_id / stop_name / stop_lat / stop_lon | tekst | Haltes in stops.txt (GTFS) |
Limits and pitfalls
- No documented rate limit, but rules: recognisable User-Agent, If-Modified-Since/If-None-Match, gzip. Timetables rarely change more than daily; the new service day starts at 03:00 UTC. from the description
- ZeroMQ: at most one connection per user per stream, best effort, no service level. from the description
- The v0.ovapi.nl wiki asks to bundle several objects in one call (commas) and not to scrape the same stops at a short interval; heavy users should run KV78Turbo themselves. from the description
- GTFS-RT is protobuf, not JSON. Read it with gtfs-realtime-bindings (Python, Node) and OVapi's .proto file for the extra fields; without a library a simple varint reader also works. tested
- No trains in vehiclePositions: on 16 Oct 2026 23:36 it contained only CXX, ARR, QBUZZ, GVB, EBS, RET, HTM and KEOLIS. Trains are in trainUpdates.pb (without positions). tested
- The GTFS file is large (241 MB, stop_times 1.17 GB unzipped). Ask for Last-Modified or ETag with HEAD first. The root folder also has govi (partial, with KV8) and openov-nl (without AVV and Thalys). tested
- Stop coordinates in /stopareacode/ of v0.ovapi.nl are not always right: Papendrecht, Pieter Zeemanlaan was at 47.97 N 3.31 E (in France). Take coordinates from the CHB or the GTFS stops. tested
- The v0.ovapi.nl wiki still mentions the old GOVI licence (keep no longer than 30 minutes); the NDOV data itself is now CC0. When in doubt, keep the source files from data.ndovloket.nl. from the description
- No robots.txt on gtfs.ovapi.nl, data.ndovloket.nl and v0.ovapi.nl (404). tested
Try it HTTP 200 · 371 ms · 16 Oct
http://v0.ovapi.nl/tpc/30005071
{
"30005071": {
"Stop": {
"Longitude": 4.8918076,
"Latitude": 52.37493,
"TimingPointTown": "unknown",
"TimingPointName": "Dam",
"TimingPointCode": "30005071",
"StopAreaCode": null
},
"Passes": {
"NL_20261016_24_51324_0": {
"IsTimingStop": false,
"DestinationName50": "Centraal Station",
"DataOwnerCode": "NL",
"OperatorCode": "GVB",
"FortifyOrderNumber": 0,
"TransportType": "TRAM",
"Latitude": 52.37493,
"Longitude": 4.8918076,
"JourneyNumber": 51324,
"JourneyPatternCode": 1868939642,
"LocalServiceLevelCode": 20261016,
"LineDirection": 1,
"OperationDate": "2026-10-16",
"TimingPointCode": "30005071"
},
"NL_20261016_2_5068_0": {
"IsTimingStop": false,
"DestinationName50": "Centraal Station",
"DataOwnerCode": "NL",
"OperatorCode": "GVB",
"FortifyOrderNumber": 0,
"TransportType": "TRAM",
"Latitude": 52.37493,
"Longitude": 4.8918076,
"JourneyNumber": 5068,
"JourneyPatternCode": 1504650659,
"LocalServiceLevelCode": 20261016,
"LineDirection": 1,Shortened response, saved at harvest time. Click the URL for the real, current response.
Read from openOV: origin of the GTFS feeds, licence and usage rules (User-Agent, If-Modified-Since, gzip) · OVapi protobuf extensions to GTFS-Realtime (delay, platform, realtime_trip_id) · NDOV desk: real-time via ZeroMQ, ports and envelopes per operator · Wiki of the KV78Turbo API at v0.ovapi.nl (stops, lines, journeys). Labels: from the description stated in what the api itself publishes. tested from our own small call. platform applies to every api on this platform, per its documentation. experience learned while building open data index.
How to fetch it
curl -sI https://gtfs.ovapi.nl/nl/vehiclePositions.pb
More in this topic
See how this page is built
bron: ndov-ov-data blokken: [] secties: - ideeen - verwerken - koppelingen - vergelijkbaar - beperkingen - code cache: tag: bron:ndov-ov-data ververs: na statuscheck, als de bron nieuwer is statuscheck: methode: Last-Modified van de GTFS-Realtime voertuigposities (gtfs.ovapi.nl) verwacht: elke minuut
Source: content/bronnen/ndov-ov-data.yaml · Markdown



