Navigation | Isochrone API | Examples | Urbi Documentation
Isochrone API

Examples

Below are the main scenarios and examples of Isochrone API requests. Request examples are provided using cURL. Detailed information about request parameters is provided in the API Reference.

To get started with the Isochrone API, get an API key.

You can build availability zones for multiple travel times. For example, get areas where you can get from the specified point in 5, 10, 20, and 30 minutes. The response result is several availability zones calculated for different time values.

An example of availability zones for a car for different travel times:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2GIS Isochrone API</title>
    <meta name="description" content="Building availability zones with different travel time" />
    <style>
        html,
        body,
        #container {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        select {
            border: 0;
            padding: 4px 10px;
            font-size: 13px;
            box-shadow: 0 1px 3px 0 rgba(38, 38, 38, 0.5);
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <div id="tooltip"></div>
    <script src="https://mapgl.2gis.com/api/js/v1"></script>
    <script>
        const reqUrl = `https://routing.api.2gis.com/isochrone/2.0.0?key=Your directions API access key`;
        const start = {
            lat: 25.19918,
            lon: 55.27280,
        };

        const map = new mapgl.Map('container', {
            center: [start.lon, start.lat],
            zoom: 11,
            key: 'Your API access key',
        });

        const controlsHtml = `<div class="controls">
        <select name="duration">
            <option value="300">5 min</option>
            <option value="600" selected>10 min</option>
            <option value="1200">20 min</option>
            <option value="1800">30 min</option>
        </select>
    </div>`;
        new mapgl.Control(map, controlsHtml, {
            position: "topLeft"
        });
        const durationSelectEl = document.querySelector('select[name="duration"]');
        const startMarker = new mapgl.Marker(map, {
            coordinates: [start.lon, start.lat]
        });
        let polygon;
        function renderGeometries(geometry) {
            if (polygon) {
                polygon.destroy();
            }
            const coordinates = geometry
                .replace("MULTIPOLYGON(((", "")
                .replace(")))", "")
                .split(",")
                .map((point) => point.trim().split(" ").map(Number));
            polygon = new mapgl.Polygon(map, {
                coordinates: [coordinates],
                strokeWidth: 3,
                strokeColor: "#bb0000",
                fillColor: "rgba(187, 0, 0, 0.3)"
            });
        }
        window.addEventListener("change", (evt) => {
            if (
                evt.target.name === "duration"
            ) {
                updateGeometries();
            }
        });
        updateGeometries();
        function updateGeometries() {
            const duration = Number(durationSelectEl.value);
            fetch(reqUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    start,
                    durations: [duration],
                    transport: "driving",
                    reverse: false,
                    format: "wkt",
                    start_time: new Date().toISOString()
                })
            })
                .then((res) => res.json())
                .then((parsed) => {
                    if (parsed.isochrones && parsed.isochrones.length > 0) {
                        renderGeometries(parsed.isochrones[0].geometry);
                    } else {
                        console.error("No isochrones found in response");
                    }
                })
                .catch((err) => console.error("Error fetching isochrone data:", err));
        }
    </script>
</body>

</html>

To build multiple availability zones for different travel times, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - array of travel times in seconds. For example, 600 seconds (10 minutes) and 1200 seconds (20 minutes).
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600, 1200],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    }
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 1200,
            "geometry": "MULTIPOLYGON(((55.187743 25.111514, 55.198544 25.120035, 55.20526 25.119618, 55.204728 25.123586, 55.212818 25.130901, 55.217387 25.12896, 55.229739 25.132051, 55.226411 25.135914, 55.229515 25.141833, 55.235578 25.131779, 55.247931 25.145266, 55.250697 25.141403, 55.249727 25.12848, 55.261854 25.136664, 55.263875 25.133845, 55.27196 25.13604, 55.274664 25.138362, 55.267475 25.139172, 55.266995 25.144068, 55.273981 25.15128, 55.284434 25.147206, 55.280622 25.137743, 55.288718 25.138276, 55.290501 25.131937, 55.291527 25.138327, 55.299425 25.141403, 55.289633 25.142763, 55.285772 25.150856, 55.290151 25.154275, 55.298086 25.152381, 55.301352 25.163358, 55.308342 25.169792, 55.316924 25.169295, 55.310447 25.167016, 55.31867 25.165388, 55.318289 25.161385, 55.324512 25.158784, 55.319671 25.168846, 55.323009 25.169315, 55.332596 25.158022, 55.33288 25.161785, 55.318068 25.179821, 55.323838 25.183479, 55.32249 25.183594, 55.320469 25.182472, 55.316427 25.182717, 55.314405 25.184211, 55.310087 25.198111, 55.318448 25.205828, 55.324512 25.204141, 55.335238 25.206693, 55.332596 25.211757, 55.330575 25.208347, 55.320221 25.209084, 55.328254 25.21667, 55.331813 25.216398, 55.332596 25.213168, 55.336014 25.216964, 55.339797 25.216398, 55.343169 25.225541, 55.33866 25.222835, 55.333804 25.22737, 55.343621 25.236511, 55.340786 25.240263, 55.328554 25.226743, 55.32249 25.226824, 55.307457 25.234683, 55.312384 25.24677, 55.30586 25.244241, 55.304796 25.23789, 55.296868 25.238931, 55.296171 25.242036, 55.28813 25.232833, 55.286109 25.235597, 55.27899 25.234683, 55.279166 25.240963, 55.282465 25.242357, 55.278729 25.248119, 55.271689 25.245897, 55.264274 25.234322, 55.255632 25.236655, 55.260546 25.232855, 55.25579 25.227011, 55.248768 25.230065, 55.251923 25.219897, 55.241642 25.208774, 55.2376 25.212251, 55.23582 25.197892, 55.230081 25.197598, 55.231708 25.194298, 55.22819 25.193823, 55.227708 25.188772, 55.212419 25.173342, 55.206945 25.163358, 55.202926 25.139573, 55.206139 25.137743, 55.205119 25.132126, 55.211324 25.134213, 55.211552 25.132048, 55.203239 25.126056, 55.195132 25.128614, 55.195049 25.126669, 55.198221 25.123104, 55.185232 25.112124, 55.187743 25.111514)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        },
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.245805 25.176053, 55.251748 25.179156, 55.255342 25.185714, 55.261525 25.179523, 55.269939 25.186384, 55.274684 25.184115, 55.273981 25.181193, 55.282066 25.182565, 55.290151 25.193385, 55.293322 25.185308, 55.289381 25.183479, 55.294375 25.181486, 55.300318 25.188966, 55.297793 25.194854, 55.303289 25.198111, 55.298236 25.199232, 55.295452 25.195143, 55.291442 25.196282, 55.294193 25.213406, 55.286109 25.210074, 55.282066 25.21372, 55.278024 25.207885, 55.276002 25.212785, 55.269939 25.206722, 55.265487 25.209084, 55.265896 25.214483, 55.257812 25.213757, 55.256689 25.210913, 55.264475 25.201769, 55.259833 25.197236, 55.249727 25.197437, 55.253697 25.187137, 55.250283 25.182976, 55.241642 25.186306, 55.241461 25.185308, 55.246986 25.179821, 55.245233 25.177992, 55.245805 25.176053)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "driving",
    "status": "OK",
    "generation_time": 0
}

By default, the direction of movement from the specified point is used for building an availability zone. The area reachable from the specified point in a set time is built. You can build reverse availability zones and calculate areas from which boundaries you can get in a set time to the specified point.

The reverse direction of movement parameter is not supported for public transport ("transport": "public_transport").

An example of availability zones for a car with a travel time of 10 minutes for different directions of movement:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2GIS Isochrone API</title>
    <meta name="description" content="Building availability zones with different movement direction" />
    <style>
        html,
        body,
        #container {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        select {
            border: 0;
            padding: 4px 10px;
            font-size: 13px;
            box-shadow: 0 1px 3px 0 rgba(38, 38, 38, 0.5);
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <div id="tooltip"></div>
    <script src="https://mapgl.2gis.com/api/js/v1"></script>
    <script>
        const reqUrl = `https://routing.api.2gis.com/isochrone/2.0.0?key=Your directions API access key`;
        const start = {
            lat: 25.19918,
            lon: 55.27280,
        };

        const map = new mapgl.Map('container', {
            center: [start.lon, start.lat],
            zoom: 11,
            key: 'Your API access key',
        });

        const controlsHtml = `<div class="controls">
        <select name="reverse">
            <option value="to">Go here</option>
            <option value="from" selected>Go from here</option>
        </select>
    </div>`;
        new mapgl.Control(map, controlsHtml, {
            position: "topLeft"
        });
        const reverseSelectEl = document.querySelector('select[name="reverse"]');
        const startMarker = new mapgl.Marker(map, {
            coordinates: [start.lon, start.lat]
        });
        let polygon;
        function renderGeometries(geometry) {
            if (polygon) {
                polygon.destroy();
            }
            const coordinates = geometry
                .replace("MULTIPOLYGON(((", "")
                .replace(")))", "")
                .split(",")
                .map((point) => point.trim().split(" ").map(Number));
            polygon = new mapgl.Polygon(map, {
                coordinates: [coordinates],
                strokeWidth: 3,
                strokeColor: "#bb0000",
                fillColor: "rgba(187, 0, 0, 0.3)"
            });
        }
        window.addEventListener("change", (evt) => {
            if (
                evt.target.name === "reverse"
            ) {
                updateGeometries();
            }
        });
        updateGeometries();
        function updateGeometries() {
            const reverse = reverseSelectEl.value === "to";
            fetch(reqUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    start,
                    durations: [600],
                    transport: "driving",
                    reverse,
                    format: "wkt",
                    start_time: new Date().toISOString()
                })
            })
                .then((res) => res.json())
                .then((parsed) => {
                    if (parsed.isochrones && parsed.isochrones.length > 0) {
                        renderGeometries(parsed.isochrones[0].geometry);
                    } else {
                        console.error("No isochrones found in response");
                    }
                })
                .catch((err) => console.error("Error fetching isochrone data:", err));
        }
    </script>
</body>

</html>

To build an availability zone which boundaries can be reached from the specified point in a set time, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • "reverse": "false" - direction of movement: from the specified point.

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "reverse": false
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.248431 25.177336, 55.25641 25.185573, 55.257789 25.180508, 55.261014 25.183426, 55.262474 25.178737, 55.263944 25.183417, 55.270218 25.186885, 55.274601 25.183356, 55.282686 25.183613, 55.28875 25.192562, 55.294813 25.182657, 55.295634 25.193892, 55.302527 25.199379, 55.298856 25.200286, 55.290405 25.195391, 55.293994 25.203037, 55.2908 25.212207, 55.284707 25.209605, 55.281301 25.212756, 55.274601 25.212267, 55.270559 25.208117, 55.259648 25.21108, 55.266876 25.201208, 55.258431 25.194676, 55.252324 25.195761, 55.255482 25.190235, 55.251105 25.184061, 55.246126 25.18308, 55.248431 25.177336)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "driving",
    "status": "OK",
    "generation_time": 0
}

To build an availability zone from which boundaries you can get to the specified point in a set time, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • "reverse": "true" - direction of movement: to the specified point.

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "reverse": true
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.262717 25.180869, 55.263773 25.185401, 55.270559 25.187328, 55.279112 25.184323, 55.278767 25.190346, 55.271895 25.195721, 55.278644 25.198196, 55.281974 25.193248, 55.284707 25.196201, 55.29143 25.19266, 55.294955 25.184619, 55.293636 25.192064, 55.300941 25.199438, 55.282686 25.205211, 55.280665 25.202021, 55.283111 25.21218, 55.278441 25.215838, 55.270559 25.210382, 55.264495 25.213617, 55.2562 25.21237, 55.262409 25.206694, 55.262264 25.202847, 55.267039 25.204866, 55.25605 25.188406, 55.262717 25.180869)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "driving",
    "status": "OK",
    "generation_time": 0
}

By default, the value of the "transport": "driving" parameter (travel by car) is passed to the request for building availability zones. You can build availability zones for other transportation types.

An example of availability zones with a travel time of 10 minutes for different transportation types:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2GIS Isochrone API</title>
    <meta name="description" content="Building availability zones for different transport types" />
    <style>
        html,
        body,
        #container {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        select {
            border: 0;
            padding: 4px 10px;
            font-size: 13px;
            box-shadow: 0 1px 3px 0 rgba(38, 38, 38, 0.5);
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <div id="tooltip"></div>
    <script src="https://mapgl.2gis.com/api/js/v1"></script>
    <script>
        const reqUrl = `https://routing.api.2gis.com/isochrone/2.0.0?key=Your directions API access key`;
        const start = {
            lat: 25.19918,
            lon: 55.27280,
        };

        const map = new mapgl.Map('container', {
            center: [start.lon, start.lat],
            zoom: 11,
            key: 'Your API access key',
        });

        const controlsHtml = `<div class="controls">
        <select name="transport">
            <option value="walking">On foot</option>
            <option value="driving" selected>By car</option>
            <option value="bicycle">By bicycle</option>
            <option value="public_transport">By public transport</option>
        </select>
    </div>`;
        new mapgl.Control(map, controlsHtml, {
            position: "topLeft"
        });
        const transportSelectEl = document.querySelector('select[name="transport"]');
        const startMarker = new mapgl.Marker(map, {
            coordinates: [start.lon, start.lat]
        });
        let polygons_on_map = [];
        function renderGeometries(geometry) {
            for (let polygon_on_map of polygons_on_map) {
                polygon_on_map.destroy();
            }
            polygons_on_map = [];

            let polygon_groups = [];

            const wkt_polygon_groups = geometry.replace("MULTIPOLYGON(((", "((").replace(")))", "))").split(")), ");
            for (let wkt_polygon_group_str of wkt_polygon_groups)
            {    
                wkt_polygon_group_str = wkt_polygon_group_str.indexOf("))") == -1 ? wkt_polygon_group_str + "))" : wkt_polygon_group_str;
                const wkt_polygon_group = wkt_polygon_group_str.replace("((", "(").replace("))", ")").split("), ");
                
                let polygon_group = [];
                for (let wkt_polygon_str of wkt_polygon_group)
                {
                    wkt_polygon_str = wkt_polygon_str.indexOf(")") == -1 ? wkt_polygon_str + ")" : wkt_polygon_str;
                    let polygon = wkt_polygon_str.replace("(", "").replace(")", "").split(",").map((point) => point.trim().split(" ").map(Number));

                    polygon_group.push(polygon);
                }    

                polygon_groups.push(polygon_group);
            }

            for (let polygon_group of polygon_groups)
            {
                polygon_on_map = new mapgl.Polygon(map, {
                    coordinates: polygon_group,
                    strokeWidth: 3,
                    strokeColor: "#bb0000",
                    fillColor: "rgba(187, 0, 0, 0.3)"
                });

                polygons_on_map.push(polygon_on_map);
            }
        }
        window.addEventListener("change", (evt) => {
            if (
                evt.target.name === "transport"
            ) {
                updateGeometries();
            }
        });
        updateGeometries();
        function updateGeometries() {
            const transport = transportSelectEl.value;
            fetch(reqUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    start,
                    durations: [600],
                    transport,
                    reverse: false,
                    format: "wkt",
                    start_time: new Date().toISOString()
                })
            })
                .then((res) => res.json())
                .then((parsed) => {
                    if (parsed.isochrones && parsed.isochrones.length > 0) {
                        renderGeometries(parsed.isochrones[0].geometry);
                    } else {
                        console.error("No isochrones found in response");
                    }
                })
                .catch((err) => console.error("Error fetching isochrone data:", err));
        }
    </script>
</body>

</html>

To build an availability zone for walking, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • "transport": "walking" - transportation type: on foot.

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "transport": "walking"
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.272354 25.192268, 55.274898 25.193165, 55.274714 25.194791, 55.277131 25.196416, 55.275854 25.198157, 55.280346 25.197988, 55.278549 25.204128, 55.275854 25.202758, 55.269566 25.202745, 55.269686 25.204653, 55.267769 25.204689, 55.26654 25.202919, 55.267917 25.200481, 55.266264 25.198855, 55.265539 25.193165, 55.272354 25.192268)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27276451009232,
                    "lat": 25.199191383170145
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "walking",
    "status": "OK",
    "generation_time": 0
}

By default, information about current traffic jams is used to build an availability zone for the transportation type by car ("transport": "driving"). To use information about statistical traffic jams for the calculation, specify the departure time.

To build an availability zone for a car, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • "transport": "driving" - transportation type: by car.

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "transport": "driving"
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.244461 25.173611, 55.255925 25.185186, 55.257789 25.180508, 55.262819 25.178948, 55.263918 25.183441, 55.270559 25.186926, 55.274601 25.181002, 55.283498 25.184012, 55.288345 25.192429, 55.291377 25.190235, 55.290872 25.181181, 55.295407 25.182381, 55.29618 25.187168, 55.300942 25.190235, 55.295962 25.193892, 55.302509 25.199379, 55.291009 25.195721, 55.293988 25.199379, 55.291938 25.210352, 55.294476 25.21218, 55.282277 25.214379, 55.266516 25.208086, 55.264495 25.214413, 55.256326 25.212257, 55.264231 25.199379, 55.260453 25.196588, 55.250282 25.197609, 55.249516 25.191312, 55.253085 25.186576, 55.248325 25.183393, 55.242262 25.185873, 55.243814 25.182494, 55.247274 25.181089, 55.242197 25.173772, 55.244461 25.173611)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "driving",
    "status": "OK",
    "generation_time": 0
}

To build an availability zone for a bicycle, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • "transport": "bicycle" - transportation type: bicycle.

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "transport": "bicycle"
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.277057 25.184354, 55.280412 25.188634, 55.283724 25.188545, 55.290504 25.194173, 55.287581 25.197998, 55.290711 25.198824, 55.291031 25.201488, 55.28528 25.206365, 55.286742 25.207584, 55.28412 25.210023, 55.285071 25.213869, 55.275357 25.211497, 55.271596 25.207136, 55.264859 25.208008, 55.258562 25.202708, 55.260311 25.195392, 55.256477 25.188076, 55.257626 25.18519, 55.277057 25.184354)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27276451009232,
                    "lat": 25.199191383170145
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "bicycle",
    "status": "OK",
    "generation_time": 0
}

By default, availability zones are built for all available types of public transport. You can select particular types of public transport: metro, bus, and others.

In some cases, the result may represent multiple polygons, including non-solid ones (with cut-out polygons inside). For example, you can get to a remote area in 10 minutes by metro, and this area is included to the result. The result also includes the area around the specified start point (metro station).

An example of availability zones with a travel time of 10 minutes for different types of public transport:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2GIS Isochrone API</title>
    <meta name="description" content="Building availability zones for different public transport types" />
    <style>
        html,
        body,
        #container {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        select {
            border: 0;
            padding: 4px 10px;
            font-size: 13px;
            box-shadow: 0 1px 3px 0 rgba(38, 38, 38, 0.5);
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <div id="tooltip"></div>
    <script src="https://mapgl.2gis.com/api/js/v1"></script>
    <script>
        const reqUrl = `https://routing.api.2gis.com/isochrone/2.0.0?key=Your directions API access key`;
        const start = {
            lat: 25.19918,
            lon: 55.27280,
        };

        const map = new mapgl.Map('container', {
            center: [start.lon, start.lat],
            zoom: 13,
            key: 'Your API access key',
        });

        const controlsHtml = `<div class="controls">
    <select name="publicTransportTypes" id="publicTransportTypesSelect">
                        <option value="metro">Metro</option>
                        <option value="bus" selected>Bus</option>
                    </select>
</div>`;
        new mapgl.Control(map, controlsHtml, {
            position: "topLeft"
        });
        const publicTransportTypesSelectEl = document.querySelector('select[name="publicTransportTypes"]');
        const startMarker = new mapgl.Marker(map, {
            coordinates: [start.lon, start.lat]
        });
        let polygons_on_map = [];
        function renderGeometries(geometry) {
            for (let polygon_on_map of polygons_on_map) {
                polygon_on_map.destroy();
            }
            polygons_on_map = [];

            let polygon_groups = [];

            const wkt_polygon_groups = geometry.replace("MULTIPOLYGON(((", "((").replace(")))", "))").split(")), ");
            for (let wkt_polygon_group_str of wkt_polygon_groups)
            {    
                wkt_polygon_group_str = wkt_polygon_group_str.indexOf("))") == -1 ? wkt_polygon_group_str + "))" : wkt_polygon_group_str;
                const wkt_polygon_group = wkt_polygon_group_str.replace("((", "(").replace("))", ")").split("), ");
                
                let polygon_group = [];
                for (let wkt_polygon_str of wkt_polygon_group)
                {
                    wkt_polygon_str = wkt_polygon_str.indexOf(")") == -1 ? wkt_polygon_str + ")" : wkt_polygon_str;
                    let polygon = wkt_polygon_str.replace("(", "").replace(")", "").split(",").map((point) => point.trim().split(" ").map(Number));

                    polygon_group.push(polygon);
                }    

                polygon_groups.push(polygon_group);
            }

            for (let polygon_group of polygon_groups)
            {
                polygon_on_map = new mapgl.Polygon(map, {
                    coordinates: polygon_group,
                    strokeWidth: 3,
                    strokeColor: "#bb0000",
                    fillColor: "rgba(187, 0, 0, 0.3)"
                });

                polygons_on_map.push(polygon_on_map);
            }
        }
        window.addEventListener("change", (evt) => {
            if (
                evt.target.name === "publicTransportTypes"
            ) {
                updateGeometries();
            }
        });
        updateGeometries();
        function updateGeometries() {
            const publicTransportTypes = [publicTransportTypesSelectEl.value];
            fetch(reqUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    start,
                    durations: [1200],
                    transport: "public_transport",
                    public_transport_types: publicTransportTypes,
                    reverse: false,
                    format: "wkt",
                    start_time: new Date().toISOString()
                })
            })
                .then((res) => res.json())
                .then((parsed) => {
                    if (parsed.isochrones && parsed.isochrones.length > 0) {
                        renderGeometries(parsed.isochrones[0].geometry);
                    } else {
                        console.error("No isochrones found in response");
                    }
                })
                .catch((err) => console.error("Error fetching isochrone data:", err));
        }
    </script>
</body>

</html>

To build an availability zone for public transport, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • "transport": "public_transport" - transportation type: by public transport.
  • "public_transport_types": ["metro", "bus"] - array of public transport types. For example, metro and bus. See the full list of public transport types in the description of the public_transport_types parameter in the API Reference. If the parameter is not specified, availability zones are built for all available public transport types.

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "transport": "public_transport",
    "public_transport_types": ["metro", "bus"]
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.272354 25.192268, 55.274898 25.193165, 55.274714 25.194791, 55.277131 25.196416, 55.275854 25.198157, 55.280346 25.197988, 55.278549 25.204128, 55.275854 25.202758, 55.269566 25.202745, 55.269686 25.204653, 55.267769 25.204689, 55.26654 25.202919, 55.267917 25.200481, 55.266264 25.198855, 55.265539 25.193165, 55.272354 25.192268)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.272799993546045,
                    "lat": 25.199180003614458
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "public_transport",
    "status": "OK",
    "generation_time": 0
}

When building an availability zone, you can specify departure time for the following transportation types:

  • By car ("transport": "driving"). If you specify a date and time of the travel start, information about statistical traffic jams is used for calculation.
  • By public transport ("transport": "public_transport"). The transport schedule is used for calculation. If you specify a date and time of the travel start when public transport is not available, a pedestrian availability zone is built.

An example of availability zones for a car with a travel time of 10 minutes for different departure times:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2GIS Isochrone API</title>
    <meta name="description" content="Building availability zones with different start time" />
    <style>
        html,
        body,
        #container {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        select {
            border: 0;
            padding: 4px 10px;
            font-size: 13px;
            box-shadow: 0 1px 3px 0 rgba(38, 38, 38, 0.5);
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <div id="tooltip"></div>
    <script src="https://mapgl.2gis.com/api/js/v1"></script>
    <script>
        const reqUrl = `https://routing.api.2gis.com/isochrone/2.0.0?key=Your directions API access key`;
        const start = {
            lat: 25.19918,
            lon: 55.27280,
        };

        const map = new mapgl.Map('container', {
            center: [start.lon, start.lat],
            zoom: 11,
            key: 'Your API access key',
        });

        const controlsHtml = `<div class="controls">
        <select name="start_time">
            <option value="2025-05-15T18:00:00Z" selected>18:00</option>
            <option value="2025-05-15T00:00:00Z">00:00</option>
        </select>
    </div>`;
        new mapgl.Control(map, controlsHtml, {
            position: "topLeft"
        });
        const startSelectEl = document.querySelector('select[name="start_time"]');
        const startMarker = new mapgl.Marker(map, {
            coordinates: [start.lon, start.lat]
        });
        let polygon;
        function renderGeometries(geometry) {
            if (polygon) {
                polygon.destroy();
            }
            const coordinates = geometry
                .replace("MULTIPOLYGON(((", "")
                .replace(")))", "")
                .split(",")
                .map((point) => point.trim().split(" ").map(Number));
            polygon = new mapgl.Polygon(map, {
                coordinates: [coordinates],
                strokeWidth: 3,
                strokeColor: "#bb0000",
                fillColor: "rgba(187, 0, 0, 0.3)"
            });
        }
        window.addEventListener("change", (evt) => {
            if (
                evt.target.name === "start_time"
            ) {
                updateGeometries();
            }
        });
        updateGeometries();
        function updateGeometries() {
            const start_time = startSelectEl.value;
            fetch(reqUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    start,
                    start_time,
                    durations: [600],
                    transport: "driving",
                    reverse: false,
                    format: "wkt"
                })
            })
                .then((res) => res.json())
                .then((parsed) => {
                    if (parsed.isochrones && parsed.isochrones.length > 0) {
                        renderGeometries(parsed.isochrones[0].geometry);
                    } else {
                        console.error("No isochrones found in response");
                    }
                })
                .catch((err) => console.error("Error fetching isochrone data:", err));
        }
    </script>
</body>

</html>

To build an availability zone depending on the departure time, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • start_time - date and time of the start of travel in RFC 3339 format (for example, 2025-05-15T15:52:01Z).

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "start_time": "2025-05-15T15:52:01Z"
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.230229 25.159052, 55.248325 25.176208, 55.251272 25.171943, 55.248325 25.166289, 55.25641 25.172638, 55.261327 25.171152, 55.259861 25.175602, 55.262474 25.17822, 55.265843 25.177431, 55.266516 25.170375, 55.267619 25.174604, 55.27258 25.173369, 55.286728 25.181735, 55.294813 25.178934, 55.311272 25.181089, 55.297301 25.184747, 55.304919 25.18932, 55.296225 25.193892, 55.313495 25.200764, 55.318815 25.208523, 55.317383 25.208828, 55.31288 25.206806, 55.308962 25.202115, 55.294813 25.202199, 55.292238 25.210352, 55.300517 25.214009, 55.296137 25.215207, 55.297617 25.22386, 55.293934 25.22498, 55.294813 25.225943, 55.299065 25.224791, 55.302315 25.230993, 55.319068 25.227418, 55.307464 25.234122, 55.307614 25.243873, 55.301483 25.233574, 55.292792 25.237866, 55.28875 25.231332, 55.282841 25.232294, 55.286186 25.230466, 55.276622 25.217109, 55.271883 25.218864, 55.272881 25.225253, 55.264495 25.225121, 55.261014 25.218987, 55.250282 25.215896, 55.250083 25.201208, 55.245915 25.19537, 55.249582 25.184747, 55.243429 25.187633, 55.244283 25.193384, 55.238078 25.190363, 55.238114 25.184652, 55.246936 25.17926, 55.234133 25.170154, 55.23411 25.166516, 55.229871 25.160967, 55.230229 25.159052)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "driving",
    "status": "OK",
    "generation_time": 0
}

You can specify the detailing level of drawing polygons when building availability zones. It is the number of points that are used to build a polygon. Available values of the detailing level are the range of floating-point numbers from 0 (minimum detailing) to 1 (maximum detailing). The higher the detailing level, the more complex the shape of the polygon, the size of the geometry in the response, and the speed of request processing.

An example of availability zones for a car with a travel time of 10 minutes with different levels of polygon detailing:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>2GIS Isochrone API</title>
    <meta name="description" content="Building availability zones with different detailing levels" />
    <style>
        html,
        body,
        #container {
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        select {
            border: 0;
            padding: 4px 10px;
            font-size: 13px;
            box-shadow: 0 1px 3px 0 rgba(38, 38, 38, 0.5);
            border-radius: 4px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <div id="tooltip"></div>
    <script src="https://mapgl.2gis.com/api/js/v1"></script>
    <script>
        const reqUrl = `https://routing.api.2gis.com/isochrone/2.0.0?key=Your directions API access key`;
        const start = {
            lat: 25.19918,
            lon: 55.27280,
        };

        const map = new mapgl.Map('container', {
            center: [start.lon, start.lat],
            zoom: 13,
            key: 'Your API access key',
        });

        const controlsHtml = `<div class="controls">
                    <select name="detailing">
                        <option value="0" selected>0 detailing level</option>
                        <option value="0.5">0.5 detailing level</option>
                        <option value="1">1 detailing level</option>
                    </select>
                </div>`;
        new mapgl.Control(map, controlsHtml, {
            position: "topLeft"
        });

        const detailingSelectEl = document.querySelector('select[name="detailing"]');

        const startMarker = new mapgl.Marker(map, {
            coordinates: [start.lon, start.lat]
        });

        let polygon;
        function renderGeometries(geometry) {
            if (polygon) {
                polygon.destroy();
            }
            const coordinates = geometry
                .replace("MULTIPOLYGON(((", "")
                .replace(")))", "")
                .split(",")
                .map((point) => point.trim().split(" ").map(Number));
            polygon = new mapgl.Polygon(map, {
                coordinates: [coordinates],
                strokeWidth: 3,
                strokeColor: "#bb0000",
                fillColor: "rgba(187, 0, 0, 0.3)"
            });
        }

        window.addEventListener("change", (evt) => {
            if (
                evt.target.name === "detailing"
            ) {
                updateGeometries();
            }
        });
        updateGeometries();

        function updateGeometries() {
            const detailing = parseFloat(detailingSelectEl.value);

            fetch(reqUrl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    start,
                    durations: [600],
                    transport: "driving",
                    reverse: false,
                    detailing,
                    format: "wkt",
                    start_time: new Date().toISOString()
                })
            })
                .then((res) => res.json())
                .then((parsed) => {
                    if (parsed.isochrones && parsed.isochrones.length > 0) {
                        renderGeometries(parsed.isochrones[0].geometry);
                    } else {
                        console.error("No isochrones found in response");
                    }
                })
                .catch((err) => console.error("Error fetching isochrone data:", err));
        }
    </script>
</body>

</html>

To specify a detailing level when building an availability zone, send a POST request to /isochrone/2.0.0 with the following parameters:

  • durations (mandatory parameter) - travel time.
  • start (mandatory parameter) - coordinates of the point (latitude and longitude).
  • detailing - level of polygon detailing from 0 to 1 (0 is minimal detailing, 1 is maximum detailing).

Request example:

curl --request POST \
 --url 'https://routing.api.2gis.com/isochrone/2.0.0?key=API_KEY' \
 --header 'Content-Type: application/json' \
 --data '{
    "durations": [600],
    "start": {
        "lat": 25.19918,
        "lon": 55.27280
    },
    "detailing": 1
}'

Response example:

response.json
{
    "isochrones": [
        {
            "duration": 600,
            "geometry": "MULTIPOLYGON(((55.247673 25.178021, 55.259105 25.190462, 55.260589 25.189015, 55.257947 25.187186, 55.257402 25.182918, 55.260372 25.180406, 55.264495 25.178697, 55.26472 25.179463, 55.263428 25.179514, 55.262185 25.180828, 55.262142 25.183528, 55.264064 25.183918, 55.265169 25.18555, 55.266131 25.184747, 55.265554 25.184138, 55.26599 25.182784, 55.268712 25.185967, 55.26842 25.187902, 55.271319 25.187264, 55.276622 25.18356, 55.280665 25.183741, 55.283699 25.185967, 55.28336 25.187161, 55.280144 25.184609, 55.279113 25.184747, 55.279991 25.186325, 55.281287 25.186576, 55.280816 25.188406, 55.282456 25.190442, 55.283648 25.190496, 55.284033 25.18925, 55.285381 25.192203, 55.289423 25.194063, 55.292348 25.191454, 55.291716 25.189015, 55.293081 25.188406, 55.293304 25.184747, 55.292742 25.184093, 55.294139 25.183109, 55.293821 25.191454, 55.294813 25.192393, 55.295941 25.191454, 55.295391 25.190844, 55.296096 25.190176, 55.296834 25.189615, 55.29753 25.190215, 55.296498 25.191149, 55.296338 25.192834, 55.295198 25.193544, 55.302026 25.199379, 55.30003 25.198926, 55.295685 25.195542, 55.289971 25.194998, 55.29049 25.198414, 55.292446 25.199989, 55.291242 25.200415, 55.291895 25.201208, 55.291216 25.201818, 55.293057 25.202187, 55.293101 25.204866, 55.293723 25.205475, 55.293466 25.208001, 55.292231 25.207913, 55.293255 25.207723, 55.292792 25.206288, 55.289183 25.206694, 55.289423 25.207556, 55.290771 25.206974, 55.292087 25.207913, 55.291074 25.209133, 55.291445 25.212485, 55.290379 25.210961, 55.290097 25.208262, 55.282012 25.208875, 55.281756 25.209364, 55.28336 25.210795, 55.28214 25.211571, 55.282237 25.212384, 55.281253 25.212258, 55.278911 25.209742, 55.278573 25.206085, 55.277743 25.20466, 55.276531 25.204783, 55.275782 25.207304, 55.276948 25.209133, 55.276622 25.209883, 55.274953 25.208814, 55.27326 25.20486, 55.272434 25.206085, 55.275949 25.211593, 55.274435 25.211112, 55.272735 25.207773, 55.269885 25.205942, 55.263619 25.20895, 55.262474 25.211397, 55.261126 25.210588, 55.259105 25.211205, 55.258836 25.210961, 55.260291 25.209742, 55.260453 25.208557, 55.261126 25.209488, 55.264007 25.208081, 55.264125 25.206694, 55.263403 25.205853, 55.261789 25.206085, 55.262698 25.204256, 55.264517 25.204236, 55.26411 25.205475, 55.264978 25.206867, 55.265843 25.206922, 55.267671 25.204256, 55.266685 25.203037, 55.26719 25.20258, 55.268537 25.204649, 55.268702 25.203037, 55.265322 25.198021, 55.262474 25.195785, 55.261079 25.196374, 55.258971 25.194623, 55.257973 25.192479, 55.255421 25.194216, 55.255063 25.195666, 55.254805 25.194735, 55.253947 25.194712, 55.253757 25.195149, 55.253042 25.195417, 55.252705 25.195112, 55.253589 25.194997, 55.253645 25.194439, 55.254726 25.194197, 55.254354 25.192032, 55.255736 25.193035, 55.257337 25.192292, 55.258038 25.190844, 55.25641 25.189236, 55.255041 25.189035, 55.255616 25.187796, 55.251504 25.1837, 55.251286 25.182678, 55.248999 25.181247, 55.247711 25.182362, 55.246304 25.182613, 55.246297 25.182302, 55.246828 25.182173, 55.246918 25.181645, 55.248073 25.18147, 55.248824 25.18048, 55.248702 25.179529, 55.247604 25.178693, 55.247584 25.178102, 55.247146 25.178041, 55.247673 25.178021)))",
            "start_point": {
                "lon": 55.272799993546045,
                "lat": 25.199180003614458
            },
            "attract_points": [
                {
                    "lon": 55.27284580762553,
                    "lat": 25.199175045379135
                }
            ]
        }
    ],
    "format": "wkt",
    "transport": "driving",
    "status": "OK",
    "generation_time": 0
}