Guides
- UK bus times in Python
- Live UK train departures
- Journey planning that knows about hills
- Where can I get to in 30 minutes?
- How reliable is my bus?
Docs
How reliable is my bus?
A timetable says when a bus should come. This guide asks how often it actually does: by route, by hour and at a single stop, and what that means for the chance of making a change. The figures are measured, from every tracked bus passing every timing point.
What you need
- Python 3.9 or later, and
pip install requests - A TransCAPI key: sign up free,
then
export TRANSCAPI_KEY=your_key
The code
import os
import requests
API = "https://api.transcapi.com/v1"
HEADERS = {"X-Api-Key": os.environ["TRANSCAPI_KEY"]}
# 1. How has a route performed over the last four weeks?
route = requests.get(f"{API}/bus/reliability.json", headers=HEADERS,
params={"operator": "FSYO", "line": "51"}).json()
print(f"Line {route['line']}: {route['on_time_pct']}% on time, "
f"{route['very_late_pct']}% very late, "
f"leaves the first stop on time {route['first_stop_on_time_pct']}% of the time")
# ... and when is it worst, between 6am and 10pm?
worst = min((h for h in route["by_hour"] if 6 <= h["hour"] <= 22 and h["observations"] >= 200),
key=lambda h: h["on_time_pct"])
print(f" worst hour: {worst['hour']:02d}:00, {worst['on_time_pct']}% on time")
# 2. How late is "late" at my stop?
stop = requests.get(f"{API}/bus/stop_reliability/370022870.json", headers=HEADERS).json()
for line in stop["lines"]:
print(f" at the stop, line {line['line']}: 1 bus in 10 is more than "
f"{line['p90_delay_s'] // 60} min late")
# 3. Will I make my change? Plan a journey and read its connections
plan = requests.get(f"{API}/journey.json", headers=HEADERS, params={
"from_lat": 53.4302, "from_lon": -1.3568, # Rotherham
"to_lat": 53.5543, "to_lon": -1.4776, # Barnsley
"datetime": "2026-10-01T09:00:00",
}).json()
for it in plan["itineraries"]:
changes = it.get("connections", [])
if not changes:
continue
lines = " > ".join(f"{c['from_line']} to {c['to_line']}" for c in changes)
chance = it["connection_chance_pct"]
print(f" {it['start_time'][11:16]} {lines}: "
f"{str(chance) + '% chance of making every change' if chance is not None else 'no history'}")
Run it:
$ python bus_reliability.py
Line 51: 73.8% on time, 4.1% very late, leaves the first stop on time 91.9% of the time
worst hour: 16:00, 61.9% on time
at the stop, line 95: 1 bus in 10 is more than 5 min late
at the stop, line 51: 1 bus in 10 is more than 7 min late
09:15 X3 to NT: 84% chance of making every change
09:25 138 to X2 > X2 to NT: 30% chance of making every change
09:23 X2 to NT: 81% chance of making every change
09:26 TT to YELL > YELL to NT: no history
Real output, 30 September 2026. The 51 in Sheffield leaves on time but loses it through the day, worst at 4pm with the school run. And the 09:25 option from Rotherham looks fine on a timetable but works less than a third of the time.
Route and line punctuality
/v1/bus/reliability.json takes a route_id (from
/v1/bus/routes.json), or an operator code and
line, over the last days complete days (default 28).
It returns the share on time, early, late and very late, mean delay, the
on-time rate at timing points and at the first and last stops, and the same
by hour. Ask with operator alone to list every line it runs,
busiest first.
"On time" is the standard the Traffic Commissioners apply: no more than a minute early and less than 6 minutes late. The response spells the definitions out.
At one stop
/v1/bus/stop_reliability/{atcocode}.json gives each line at a
stop with the median and 90th-percentile delay. The 90th percentile is the
honest version of "usually on time": the lateness to allow for if you can't
afford to miss it.
Making a connection
Every journey plan with a change carries connections: the time
to spare at each change and chance_pct, how often that change
actually worked for those exact buses over recent weeks. The whole journey's
chance is connection_chance_pct. Where there's no history, from a
train, tram or an untracked bus, it's null rather than a guess.
Coverage
Punctuality is measured wherever operators report bus positions to the Bus Open Data Service: most of England, some of Wales and little of Scotland. Northern England and West Sussex go back to 4 August 2026; everywhere else from 30 September 2026, so figures there firm up over the coming weeks.
All the parameters are in the bus docs and the journey docs.
Try it. A free key gives you 1,000 requests a day with no card. Every endpoint covers Great Britain: see coverage for the parts that are regional.