Journey planning that knows about hills

Most journey planners rank routes by time, then by how far you walk. Neither tells you that one option's ten-minute walk is up a hill. This guide plans a journey across Great Britain and compares the options by how much climbing their walks involve, using the terrain figures TransCAPI adds to every walking leg.

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

Sheffield station to Crookes is 4 km, and Crookes sits about 180 metres above the station. It's a good test.

import os
import requests

API = "https://api.transcapi.com/v1"
HEADERS = {"X-Api-Key": os.environ["TRANSCAPI_KEY"]}

# Sheffield station to Crookes: a short hop, but up a big hill
plan = requests.get(f"{API}/journey.json", headers=HEADERS, params={
    "from_lat": 53.3781, "from_lon": -1.4623,
    "to_lat": 53.3855, "to_lon": -1.5130,
}).json()

options = plan["itineraries"] + plan["alternatives"].get("walk", {}).get("itineraries", [])
for it in options:
    modes = " > ".join(leg["mode"].lower() for leg in it["legs"])
    walk = it.get("walking") or {}
    print(f"{it['duration_s'] / 60:4.0f} min  {modes:<32} "
          f"walk {it['walk_distance_m']:5.0f} m, climb {walk.get('climb_m', '?')} m "
          f"({walk.get('shape', 'n/a')}), ~{walk.get('calories_kcal', '?')} kcal")

Run it:

$ python journey_climb.py
  38 min  walk > tram > walk > bus > walk  walk   482 m, climb 15 m (gentle climb), ~35 kcal
  42 min  walk > bus > walk                walk  1265 m, climb 17 m (gentle climb), ~79 kcal
  41 min  walk > bus > walk > bus > walk   walk   754 m, climb 7 m (flat), ~48 kcal
  40 min  walk > bus > walk > bus > walk   walk  1122 m, climb 25 m (steady climb), ~76 kcal
  55 min  walk                             walk  4008 m, climb 182 m (steep climb), ~302 kcal

Real output, 29 September 2026.

Walking takes 55 minutes, not far off the bus, but the bus does the 180 metres of climbing for you. Among the transit options, the third walks 750 m and climbs 7 m, while the fourth walks 1.1 km and climbs 25 m. That's worth knowing if you're carrying shopping, pushing a buggy or using a stick.

The figures

Each itinerary has a walking summary:

"walking": {
  "climb_m": 180,
  "descent_m": 17,
  "steepest_up_pct": 43.6,
  "shape": "steep climb",
  "direction": "up",
  "calories_kcal": 208,
  "complete": true
}

Each walking leg has the same figures in terrain, plus steepest_down_pct, so you can say which part of the journey is the hard bit. shape gives a label you can show as it is: flat, gentle climb, steady climb, steep climb, the three matching descents, rolling or hilly.

Where the numbers come from

Heights come from Ordnance Survey's OS Terrain 50, sampled every 25 metres along the walk's actual path and smoothed, so small errors in the model don't turn a flat street into a climb. Calories use a published model of the energy cost of walking on a slope, for a 70 kg adult. These are estimates for comparing routes, not measurements. A 50-metre grid softens short, sharp rises, so a flight of steps may read gentler than it is. The journey docs cover the method and its limits.

Combining it with walking limits

max_walk_distance caps the longest single walk and max_total_walk_distance the total, and both are enforced rather than just preferred. Use them to rule options out, then rank what's left by walking.climb_m:

params["max_walk_distance"] = 500
options = sorted(plan["itineraries"],
                 key=lambda it: (it.get("walking") or {}).get("climb_m", 0))

What else is in a journey

  • Bus, tram and metro legs follow the road or track, from the operator's published route, ready to draw on a map.
  • include_steps=true adds turn-by-turn walking directions.
  • Buses already running carry their live position and delay.
  • Fare estimates where fare data exists, currently bus in Yorkshire and West Sussex.
  • Journeys can be planned up to two months ahead with datetime, or to arrive by a time with arrive_by=true.

Coverage is England, Scotland and Wales, by bus, coach, rail, Underground, metro, tram and ferry. Journey planning pauses on Sundays from 03:00 to 04:30 UK time while the week's timetables load. During that window it returns 503 with Retry-After, and every other endpoint keeps working.


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.