How to Create 5-, 10-, and 15-Minute Travel-Time Zones
- API or service
- Isoline API + MapLibre GL
- Task
- Origin + several time limits → nested reachability zones
- Examples
- Difficulty
- Beginner
- Time
- 10 min
Create several travel-time zones
You have one origin and need to compare what is reachable within 5, 10, and 15 minutes. Send all three limits to the Isoline API in one request and render each returned feature as a nested zone.
Task flow: origin + 5/10/15-minute limits → one Isoline API request → three GeoJSON features → nested map zones.
Multiple ranges are useful for response-time bands, delivery promises, retail catchments, and facility planning. Each larger feature is cumulative: the 15-minute area includes locations that are also reachable within 5 or 10 minutes.
Request 5-, 10-, and 15-minute zones
Pass one comma-separated range value containing 300, 600, and 900 seconds. The API accepts between one and ten ranges per calculation.
https://api.geoapify.com/v1/isoline?lat=52.52&lon=13.405&type=time&mode=drive&range=300,600,900&traffic=free_flow&format=geojson&apiKey=YOUR_API_KEY
Reduced response: Geometry coordinates are omitted. Match each feature to its band through properties.range, not its array position.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "mode": "drive", "type": "time", "range": 300 },
"geometry": { "type": "MultiPolygon" }
},
{
"type": "Feature",
"properties": { "mode": "drive", "type": "time", "range": 600 },
"geometry": { "type": "MultiPolygon" }
},
{
"type": "Feature",
"properties": { "mode": "drive", "type": "time", "range": 900 },
"geometry": { "type": "MultiPolygon" }
}
]
}
The same request pattern works for distance zones: use type=distance and provide ranges in meters when units=metric or miles when units=imperial.
Style nested travel-time zones
Add the complete FeatureCollection as a GeoJSON source. Sort larger ranges first so smaller zones remain visible, then color each feature from its range property.
// `zones` is the complete response from the 300,600,900 request.
zones.features.sort((a, b) => b.properties.range - a.properties.range);
map.addSource("travel-time-zones", { type: "geojson", data: zones });
map.addLayer({
id: "travel-time-zones-fill",
type: "fill",
source: "travel-time-zones",
paint: {
"fill-color": [
"match", ["get", "range"],
300, "#00ac17",
600, "#ffb703",
900, "#ff005c",
"#623aff"
],
"fill-opacity": 0.3
}
});
map.addLayer({
id: "travel-time-zones-outline",
type: "line",
source: "travel-time-zones",
paint: { "line-color": "#ffffff", "line-width": 1 }
});
Label the legend as 5 min, 10 min, and 15 min, while keeping seconds in the data. If the bands must not overlap for analysis, subtract the preceding polygon from each larger polygon; map display usually does not require that conversion.