Can I calculate estimated time of arrival for a bus?

Originally asked by Simon:

I’m a passenger on a bus, I want to know how long the bus will take to get where I’m going (and I know Countdown has a 30 minute limitation). I open my smartphone and into my bus app I type ‘ETA LG52XYJ’. The app’s backend, using the legacy URL would post something like:


…and get back something like the below which the backend would then sort into either ‘EstimatedTime’ order (with the possibility of stops being slightly out of order) or Stop order (which it already knows & with the possibility of the arrival times being slightly wrong).

[1,”St Donatts Road”,”47876″,”490012652S”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461778771000]
[1,”Millmark Grove”,”47079″,”490009913S”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461778861000]
[1,”Peckham Park Road”,”51530″,”490010880EN”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461777740000]
[1,”New Cross Bus Garage”,”47366″,”490010204G”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461778279000]
[1,”Malt Street”,”71447″,”490009531E”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461777602000]
[1,”Old Kent Road / Ilderton Road”,”51870″,”490008461E2″,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461778059000]
[1,”Dunton Road”,”72792″,”490006266EC”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461777429000]
[1,”Briant Street”,”87898″,”490003246F”,”172″,”172″,”Brockley Rise”,”Brockley Rise”,16150,”LG52XYJ”,1461778146000]

Now, using the unified API, the app’s backend would post (with credentials) and get back far more data (9MB at 19:00 as I type). It would then have to filter that to find only the bus our user is interested in, sort it and then present it back to the user.

If the Unified API could do something like or maybe if we want to check a tram’s ETA. (Are vehicleIDs unique across modes in the unified API? If so, might rule out the need for /tram/ or /bus/.)Alternatively,

I did consider searching for vehicleId under ‘Line’ or ‘StopPoint’ but then we’d need to know what route the vehicle was on before we could search for it.

The output I would hope to see from a query like this would be like the return from or but restricted to the vehicleId we’ve searched for and maybe slimmed down… do I need to know the bearing of the stop, the ‘towards’ information (e.g. “Towards Waterloo, Trafalgar Square or Holborn”) or the direction (inbound/outbound)?

BTW, Are there any plans to remove the legacy Countdown feed any time soon? I hope not – It seems far more flexible in what you can ask it and ask it to present on return (i.e. don’t give me the information I don’t need) than what you can do with the unified API.

Dan Mewett replied:

Hi Simon,

Thanks for providing a very detailed description of your use case and expectations for an arrivals end-point based on vehicleid. I can see that such an interface would provide apps the ability to give customers really useful information on their journey, especially if you are trying to meet someone or catch a transport connection further down the route. On our “Arrivals of things” blog post, other users are also asking for the same functionality, and according to @Tim (see the comments section) we have already got a version of this in our development pipeline, so you can expect something to show up in the API for this very soon and we will let you know when that happens.

Here is a link to the blog article: Unified API Part 5: AoT – Arrivals of Things – TfL Digital

There are plans to make some changes to the web and mobile interfaces of Countdown in the near future (June) but currently no plans to change access or outputs of the existing Countdown API.

The Vehicle Arrivals API is now available, so using a vehicleId (which matches the registration mark for buses at least) you can retrieve the arrival times of the vehicle for the remainder of its route.

The API is structured as /Vehicle/{vehicleId}/Arrivals

For example:

$ curl "" -s | jq ".[] | .vehicleId"

Let’s try the first vehicleId…

$> curl "" -s | jq '.[] | .stationName, .expectedArrival'
"Hoxton Station  / Geffrye Museum"
"Pearson Street"
"St Leonard's Hospital"
"Laburnum Street"
"Haggerston Station"
"Middleton Road"
"Kingsland High Street / Dalston Jct"
"Dalston Junction Station"
"Dalston Kingsland Station"
"Rio Cinema"

Voilá - the 149 bus going North up Kingsland Road as expected

Oh, that’s a helpful endpoint! Previously I’d been doing this by requesting arrivals data for all the stops and then matching them up based on vehicleId. This worked okay for smallish modes (eg tube or river), but was impractical to do for a larger network (like buses). This lets me get the data on demand, rather than having to hold it all in memory. :grinning: