Skip to content

Cycling and Walking Options

mode: "bicycle" and mode: "foot" work without any options. When the defaults don’t fit the rider or walker, send a bicycle or pedestrian object with the request. Both work on Directions, Isochrones and the Distance Matrix.

Two kinds of options live in these objects:

  • Speeds (bicycle_type, cycling_speed, walking_speed) change how long the trip takes.
  • Preferences (everything else) change which way the route goes. They make a busy road or a staircase look more expensive to the router, but duration_s is still the time it takes to ride or walk the route. A matrix or an isochrone measures time, so preferences don’t change them; speeds and the roads you may use do.

A value out of range, an unknown option, or an object sent with the wrong mode is a 422 validation_error. The pedestrian object also works with mode: "transit", for the journey’s walks (see Transit Routing).

These defaults now apply to every bicycle and walking request, including requests with no bicycle or pedestrian object:

  • Walking routes, isochrones and matrices stay off trails harder than sac_scale=hiking, because max_hiking_difficulty defaults to 1. Transit walks to and from stops follow the same rule.
  • Walking routes count 30 seconds for each flight of steps. They avoid main roads without a tagged sidewalk (1.3x) and service roads (1.1x).
  • Bicycle routes avoid busy roads without cycle infrastructure (use_roads 0.5) and rough surfaces (avoid_bad_surfaces 0.25).
  • Bicycles push at 5 km/h where a way is tagged bicycle=dismount. Ways tagged bicycle=no, foot=no or crossing=no are left out for that mode, and bicycle=yes or foot=yes now opens a way that access=no would close.

The preference changes can pick a different path, but they never add to duration_s. Set use_roads: 1, avoid_bad_surfaces: 0, step_penalty: 0 or max_hiking_difficulty: 6 to get closer to the old behaviour.

FieldTypeDefaultRange
bicycle.bicycle_typestring"hybrid"road, hybrid, cross, mountain
bicycle.cycling_speednumberby type5 to 50 km/h
bicycle.use_roadsnumber0.50 to 1
bicycle.use_hillsnumber0.50 to 1
bicycle.avoid_bad_surfacesnumber0.250 to 1

Bike type. The type sets the cruising speed on a road: 21 km/h for a road bike, 17 for cyclocross, 15 for a hybrid and 13 for a mountain bike. cycling_speed replaces it. Cycleway, path and track speeds scale by the same amount. Pushing the bike along a footway or carrying it up steps stays at walking pace whatever you ride.

The type also decides how much rough ground hurts. A road bike slows down 25% more than a hybrid on gravel, a mountain bike half as much. See surfaces for the hybrid’s numbers.

use_roads. At 1 the route treats a primary road like any street. Lower values make busy roads without cycle infrastructure more expensive, trunk roads most, then primary, secondary and tertiary roads. A cycle track (cycleway=track) or a cycle street (bicycle_road=yes, cyclestreet=yes) removes the cost. A painted lane keeps a quarter of it, a shared lane (sharrows) 60%. Roads tagged bicycle=use_sidepath cost extra, since there’s a cycle path next to them.

Infrastructure on one side of a road only helps in the direction it serves. A cycleway:right=lane on a two-way street counts for traffic on the right, which is the direction the way is drawn in right-hand-traffic countries and the opposite one in left-hand-traffic countries such as the UK, Japan or Australia (and in Hong Kong and Macau). cycleway:left is the mirror image. cycleway:<side>:oneway overrides that (yes, -1, or no for both directions), lanes on a one-way street run with the traffic (unless oneway:bicycle=no lets cyclists ride both ways, when the driving side decides again), and contraflow lanes (cycleway=opposite_lane, opposite_track) count only against it. On two-way streets, cycleway=* and cycleway:both=* cover both directions.

use_hills. Climbs already slow you down. Lower values also make them more expensive to the router, so it goes around a hill when the detour is close. At 1 it only counts the extra time.

avoid_bad_surfaces. Higher values avoid unpaved and rough ways: gravel, dirt and grass from the surface and tracktype tags, and bad smoothness. Road bikes avoid them most and mountain bikes least.

Bicycles never use ways tagged bicycle=no or bicycle=private, smoothness=impassable, or crossings tagged crossing=no. Where a way is tagged bicycle=dismount, the bike is pushed at 5 km/h.

Terminal window
curl -X POST https://plaza.fyi/api/v1/route \
-H "x-api-key: $PLAZA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": {"type": "Point", "coordinates": [13.3777, 52.5163]},
"destination": {"type": "Point", "coordinates": [13.4132, 52.5219]},
"mode": "bicycle",
"bicycle": {"bicycle_type": "road", "use_roads": 0.2, "use_hills": 0.3}
}'
FieldTypeDefaultRange
pedestrian.walking_speednumber51 to 10 km/h
pedestrian.use_hillsnumber0.50 to 1
pedestrian.use_litnumber00 to 1
pedestrian.walkway_factornumber10.1 to 10
pedestrian.sidewalk_factornumber10.1 to 10
pedestrian.step_penaltynumber300 to 3600 seconds
pedestrian.max_hiking_difficultyinteger11 to 6
pedestrian.wheelchairbooleanfalse

walking_speed is the speed on flat ground. Slopes change it with Tobler’s hiking function, so a gentle descent is a little faster and a steep climb much slower.

Ways. Main roads without a sidewalk cost 30% more than their walking time, and service roads 10% more. Roads tagged with a sidewalk (sidewalk=both, left, right or yes) don’t. walkway_factor multiplies the cost of footways, pedestrian streets and paths, and sidewalk_factor the cost of roads with a sidewalk. Below 1 the route prefers them.

use_hills. Lower values avoid ways steeper than 2%, up or down.

use_lit. Higher values avoid ways tagged lit=no, and to a lesser degree ways with no lighting information. Lit ways cost nothing extra.

Steps. Walkers take steps. step_penalty adds that many seconds to the router’s cost of each flight, plus half a second per step when the way has a step_count. Set it to 0 to treat steps like any path, or high to go around them.

max_hiking_difficulty is the hardest trail the route may use, on the SAC scale from the sac_scale tag: 1 hiking, 2 mountain_hiking, 3 demanding_mountain_hiking, up to 6 difficult_alpine_hiking. The default of 1 keeps walking routes off mountain trails. Ways without a sac_scale tag are always walked.

Walkers never use ways tagged foot=no or foot=private, or crossings tagged crossing=no.

With "wheelchair": true the route leaves out:

  • steps
  • ways tagged wheelchair=no
  • grades steeper than 8% either way, from elevation data or a numeric incline tag
  • sand and mud
  • smoothness of very_bad or worse

It prefers ways tagged wheelchair=yes and avoids cobblestones, setts, paving stones and unpaved surfaces.

It also goes around kerbs. Plaza reads kerb=* and barrier=kerb on the nodes of footways, paths, pedestrian streets and cycleways. A raised kerb costs the router 10 minutes, so the route takes a detour of up to that long to avoid it. A kerb of unknown height (barrier=kerb with no kerb value, or kerb=yes) costs 5 minutes and a rolled kerb 30 seconds. Lowered and flush kerbs cost nothing. A kerb mapped on the node where a crossing meets the sidewalk only counts for routes that take the crossing, not for ones that walk past it. Like the other preferences, kerbs change which way the route goes, not duration_s, and isochrones and matrices ignore them. Without wheelchair, kerbs don’t matter.

Terminal window
curl -X POST https://plaza.fyi/api/v1/route \
-H "x-api-key: $PLAZA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"origin": {"type": "Point", "coordinates": [-0.1276, 51.5072]},
"destination": {"type": "Point", "coordinates": [-0.1195, 51.5033]},
"mode": "foot",
"pedestrian": {"wheelchair": true, "use_lit": 1}
}'

use_hills, the wheelchair grade limit and the slope speeds need elevation, which Plaza takes from Copernicus DEM tiles. Where a road has no elevation data, it counts as flat. Grades are averaged over each stretch of road between junctions, so a short steep ramp inside a long stretch can be missed. A tagged incline (like incline=10%) still counts for wheelchairs.

route(), isochrone(), matrix(), optimize(), centroid(), expansion() and map_match() take the same options as keyword arguments, next to mode:

route(
origin: point(52.5163, 13.3777),
destination: point(52.5219, 13.4132),
mode: "bicycle",
bicycle_type: "road",
use_roads: 0.2
);
isochrone(center: point(51.5072, -0.1276), time: 900, mode: "foot", wheelchair: true);

use_hills belongs to whichever mode you set. See bicycle and pedestrian options in the PlazaQL guide.