Integrate A-to-B route planning, turn-by-turn navigation, route optimization, isochrone calculations, location clustering and other tools into your application.
Integrate A-to-B route planning, turn-by-turn navigation, route optimization, isochrone calculations, location clustering and other tools into your application.
Authenticate to the API by passing your key as a query parameter in every request.
You can also try all API parts without registration in our API explorer.
To speed up development and make coding easier, we offer a JavaScript client and a Java client.
You should utilize the SSL session to speed up responses after the initial response or use a library that does this. E.g. for Java the OkHttp library automatically reuses SSL/TLS sessions and also the browser takes care of this automatically. For python you can use the requests
library: first you create a session (session = requests.Session()
) and then do requests only with this session instead of directly using "requests".
If you create your own client, make sure it supports http/2 and gzipped responses for best speed. If you use the Matrix, the Route Optimization API or the and want to solve large problems, we recommend you to reduce bandwidth by compressing your POST request and specifying the header as follows: Content-Encoding: gzip
. This will also avoid the HTTP 413 error "Request Entity Too Large".
The default data source is OpenStreetMap and as an alternative we have also integrated TomTom.
The Route Optimization API can be used to solve traveling salesman or vehicle routing problems. You can use our API Explorer to explore Route Optimization. If you have successfully solved the first problem, we recommend this tutorial - Getting Started with the Optimization API. It shows and describes the essential elements to model your vehicle routing problem.
Further reading:
The Routing API calculates the best path connecting two or more points, where the meaning of ''best'' depends on the vehicle profile and use case. Besides path coordinates it can return turn-by-turn instructions, elevation, path details and other useful information about the route.
Use our API Explorer to explore the Routing API.
For the GET request you specify the parameters in the URL and can try it directly in every browser. However, it has some disadvantages when using many points (URL length limit) and the custom_model
Feature cannot be used. Therefore, our recommended endpoint is the POST route endpoint.
The routing profile. It determines the network, speed and other physical attributes used when computing the route. See the section about routing profiles for more details and valid profile values.
The points for which the route should be calculated. Format: latitude,longitude
. Specify at least an origin and a destination. Via points are possible. The maximum number depends on your plan.
The point_hint
is typically a road name to which the associated point
parameter should be snapped to. Specify no point_hint
parameter or the same number as you have point
parameters.
Optional parameter. 'Snapping' is the process of finding the closest road location for GPS coordinates provided in the point
parameter. The snap_prevention
parameter allows you to prevent snapping to specific types of roads. For example, if snap_prevention
is set to bridge, the routing engine will avoid snapping to a bridge, even if it is the closest road for the given point
. Current supported values: motorway
, trunk
, ferry
, tunnel
, bridge
and ford
. Multiple values are specified like snap_prevention=ferry&snap_prevention=motorway
. Note that once snapped the routing algorithm can still route over bridges (or the other values). To avoid this you need to use the custom_model
.
Optional parameter. It specifies on which side a point should be relative to the driver when she leaves/arrives at a start/target/via point. You need to specify this parameter for either none or all points. Only supported for motor vehicles and OpenStreetMap.
The locale of the resulting turn instructions. E.g. pt_PT
for Portuguese or de
for German.
If true
, a third coordinate, the altitude, is included with all positions in the response. This changes the format of the points
and snapped_waypoints
fields of the response, in both their encodings. Unless you switch off the points_encoded
parameter, you need special code on the client side that can handle three-dimensional coordinates.
Optional parameter. The following path details are available: street_name
, street_ref
, street_destination
, leg_time
, leg_distance
, roundabout
, country
, time
, distance
, max_speed
, max_weight
, max_width
, toll
, road_class
, road_class_link
, road_access
, road_environment
, hazmat
, hazmat_tunnel
, hazmat_water
, lanes
, surface
, smoothness
, hike_rating
, mtb_rating
, foot_network
, bike_network
. Read more about the usage of path details here.
Normally, the calculated route will visit the points in the order you specified them. If you have more than two points, you can set this parameter to "true"
and the points may be re-ordered to minimize the total travel time. Keep in mind that the limits on the number of locations of the Route Optimization API applies, and the request costs more credits.
Allows changing the encoding of location data in the response. The default is polyline encoding, which is compact but requires special client code to unpack. (We provide it in our JavaScript client library!) Set this parameter to false
to switch the encoding to simple coordinate pairs like [lon,lat]
, or [lon,lat,elevation]
. See the description of the response format for more information.
Favour a heading direction for a certain point. Specify either one heading for the start point or as many as there are points. In this case headings are associated by their order to the specific points. Headings are given as north based clockwise angle between 0 and 360 degree. This parameter also influences the tour generated with algorithm=round_trip
and forces the initial direction. Requires ch.disable=true
.
Time penalty in seconds for not obeying a specified heading. Requires ch.disable=true
.
If true
, u-turns are avoided at via-points with regard to the heading_penalty
. Requires ch.disable=true
.
Rather than looking for the shortest or fastest path, this parameter lets you solve two different problems related to routing: With alternative_route
, we give you not one but several routes that are close to optimal, but not too similar to each other. With round_trip
, the route will get you back to where you started. This is meant for fun (think of a bike trip), so we will add some randomness. The round_trip
option requires ch.disable=true
. You can control both of these features with additional parameters, see below.
If algorithm=round_trip
, this parameter configures approximative length of the resulting round trip. Requires ch.disable=true
.
If algorithm=round_trip
, this sets the random seed. Change this to get a different tour for each value.
If algorithm=alternative_route
, this parameter sets the number of maximum paths which should be calculated. Increasing can lead to worse alternatives.
If algorithm=alternative_route
, this parameter sets the factor by which the alternatives routes can be longer than the optimal route. Increasing can lead to worse alternatives.
curl "https://graphhopper.com/api/1/route?point=51.131,12.414&point=48.224,3.867&profile=car&locale=de&calc_points=false&key=api_key"
Routing Result
The number of seconds that you have to wait before a reset of the credit count is done.
The total distance, in meters. To get this information for one 'leg' please read this blog post.
The total travel time, in milliseconds. To get this information for one 'leg' please read this blog post.
The geometry of the route. The format depends on the value of points_encoded
.
The geometry of the route. The format depends on the value of points_encoded
.
The geometry of the route. The format depends on the value of points_encoded
.
The snapped input points. The format depends on the value of points_encoded
.
The snapped input points. The format depends on the value of points_encoded
.
The snapped input points. The format depends on the value of points_encoded
.
Whether the points
and snapped_waypoints
fields are polyline-encoded strings rather than JSON arrays of coordinates. See the field description for more information on the two formats.
The bounding box of the route geometry. Format: [minLon, minLat, maxLon, maxLat]
.
The instructions for this route. This feature is under active development, and our instructions can sometimes be misleading, so be mindful when using them for navigation.
Details, as requested with the details
parameter. Consider the value {"street_name": [[0,2,"Frankfurter Straße"],[2,6,"Zollweg"]]}
. In this example, the route uses two streets: The first, Frankfurter Straße, is used between points[0]
and points[2]
, and the second, Zollweg, between points[2]
and points[6]
. Read more about the usage of path details here.
{ "hints": { "visited_nodes.sum": 58, "visited_nodes.average": 58 }, "info": { "copyrights": [ "GraphHopper", "OpenStreetMap contributors" ], "took": 2 }, "paths": [ { "distance": 1791.011, "weight": 307.852443, "time": 370962, "transfers": 0, "points_encoded": false, "bbox": [ 11.539424, 48.118343, 11.558901, 48.122364 ], "points": { "type": "LineString", "coordinates": [ [ 11.539424, 48.118352 ], [ 11.540387, 48.118368 ], [ 11.54061, 48.118356 ], [ 11.541941, 48.118409 ], [ 11.543696, 48.118344 ], [ 11.547167, 48.118343 ], [ 11.548478, 48.118366 ], [ 11.548487, 48.119329 ], [ 11.548807, 48.119328 ], [ 11.549408, 48.119366 ], [ 11.550349, 48.119508 ], [ 11.550441, 48.119473 ], [ 11.551109, 48.119467 ], [ 11.551553, 48.119445 ], [ 11.551748, 48.119398 ], [ 11.552087, 48.119475 ], [ 11.552236, 48.119542 ], [ 11.552353, 48.119635 ], [ 11.553853, 48.121136 ], [ 11.555448, 48.12039 ], [ 11.555797, 48.120206 ], [ 11.55632, 48.120592 ], [ 11.556716, 48.120919 ], [ 11.557326, 48.121345 ], [ 11.558901, 48.122364 ] ] }, "instructions": [ { "distance": 672.954, "heading": 89.04, "sign": 0, "interval": [ 0, 6 ], "text": "Continue onto Lindenschmitstraße", "time": 144703, "street_name": "Lindenschmitstraße" }, { "distance": 107.145, "sign": -2, "interval": [ 6, 7 ], "text": "Turn left", "time": 22675, "street_name": "" }, { "distance": 140.169, "sign": 2, "interval": [ 7, 10 ], "text": "Turn right onto Oberländerstraße", "time": 28032, "street_name": "Oberländerstraße" }, { "distance": 360.232, "sign": 1, "interval": [ 10, 18 ], "text": "Turn slight right", "time": 72677, "street_name": "" }, { "distance": 177.621, "sign": 2, "interval": [ 18, 20 ], "text": "Turn right onto Thalkirchner Straße", "time": 35524, "street_name": "Thalkirchner Straße" }, { "distance": 332.89, "sign": -2, "interval": [ 20, 24 ], "text": "Turn left onto Thalkirchner Straße", "time": 67351, "street_name": "Thalkirchner Straße" }, { "distance": 0, "sign": 4, "last_heading": 45.67046584987792, "interval": [ 24, 24 ], "text": "Arrive at destination", "time": 0, "street_name": "" } ], "legs": [], "details": {}, "ascend": 6.3294677734375, "descend": 25.0579833984375, "snapped_waypoints": { "type": "LineString", "coordinates": [ [ 11.539424, 48.118352 ], [ 11.558901, 48.122364 ] ] } } ] }
To do a request you send JSON data.
See the GET endpoint for an alternative query method which is slightly simpler to get started but has some disadvantages.
Please note that in contrast to the GET endpoint, points are specified in the order of [longitude, latitude]
and some parameter names use the plural. For example the string point=10,11&point=20,22
will be converted to the points
array (plural):
{ "points": [[11,10], [22,20]] }
So this points
array uses a format similar to GeoJson.
Example:
curl -X POST -H "Content-Type: application/json" "https://graphhopper.com/api/1/route?key=[YOUR_KEY]" -d '{"elevation":false,"points":[[-0.087891,51.534377],[-0.090637,51.467697]],"profile":"car"}'
The routing profile. It determines the network, speed and other physical attributes used when computing the route. See the section about routing profiles for more details and valid profile values.
The points for the route in an array of [longitude,latitude]
. For instance, if you want to calculate a route from point A to B to C then you specify `points: [ [A_longitude, A_latitude], [B_longitude, B_latitude], [C_longitude, C_latitude]]
Optional parameter. Specifies a hint for each point in the points
array to prefer a certain street for the closest location lookup. E.g. if there is an address or house with two or more neighboring streets you can control for which street the closest location is looked up. Make sure you do not include the house number of city name and only the street name to improve the quality of the matching.
Optional parameter. 'Snapping' is the process of finding the closest road location for GPS coordinates provided in the points
array. The snap_preventions
array allows you to prevent snapping to specific types of roads. For example, if the array includes bridge
, then the routing engine will avoid snapping to a bridge, even if it is the closest road for the given point. Note that once snapped the routing algorithm can still route over bridges (or the other values). To avoid this you need to use the custom_model
.
Optional parameter. It specifies on which side a point should be relative to the driver when she leaves/arrives at a start/target/via point. You need to specify this parameter for either none or all points. Only supported for motor vehicle profiles and OpenStreetMap.
The locale of the resulting turn instructions. E.g. pt_PT
for Portuguese or de
for German.
If true
, a third coordinate, the altitude, is included with all positions in the response. This changes the format of the points
and snapped_waypoints
fields of the response, in both their encodings. Unless you switch off the points_encoded
parameter, you need special code on the client side that can handle three-dimensional coordinates.
Optional parameter. The following path details are available: street_name
, street_ref
, street_destination
, leg_time
, leg_distance
, roundabout
, country
, time
, distance
, max_speed
, max_weight
, max_width
, toll
, road_class
, road_class_link
, road_access
, road_environment
, hazmat
, hazmat_tunnel
, hazmat_water
, lanes
, surface
, smoothness
, hike_rating
, mtb_rating
, foot_network
, bike_network
. Read more about the usage of path details here.
Normally, the calculated route will visit the points in the order you specified them. If you have more than two points, you can set this parameter to "true"
and the points may be re-ordered to minimize the total travel time. Keep in mind that the limits on the number of locations of the Route Optimization API applies, and the request costs more credits.
Allows changing the encoding of location data in the response. The default is polyline encoding, which is compact but requires special client code to unpack. (We provide it in our JavaScript client library!) Set this parameter to false
to switch the encoding to simple coordinate pairs like [lon,lat]
, or [lon,lat,elevation]
. See the description of the response format for more information.
Use this parameter in combination with one or more parameters from below.
The custom_model modifies the routing behaviour of the specified profile. See the detailed documentation. Below is a complete request example in Berlin that limits all speeds to 100km/h, excludes motorways and makes shorter routes a bit more likely than the default due to a higher distance_influence. Note that it also includes the "ch.disabled": true
parameter which is required to make use of custom_model
.
{
"points": [
[
13.31543,
52.509535
],
[
13.29779,
52.512434
]
],
"profile": "car",
"ch.disable": true,
"custom_model": {
"speed": [
{
"if": "true",
"limit_to": "100"
}
],
"priority": [
{
"if": "road_class == MOTORWAY",
"multiply_by": "0"
}
],
"distance_influence": 100
}
}
Favour a heading direction for a certain point. Specify either one heading for the start point or as many as there are points. In this case headings are associated by their order to the specific points. Headings are given as north based clockwise angle between 0 and 360 degree. This parameter also influences the tour generated with algorithm=round_trip
and forces the initial direction. Requires ch.disable=true
.
Time penalty in seconds for not obeying a specified heading. Requires ch.disable=true
.
If true
, u-turns are avoided at via-points with regard to the heading_penalty
. Requires ch.disable=true
.
Rather than looking for the shortest or fastest path, this parameter lets you solve two different problems related to routing: With alternative_route
, we give you not one but several routes that are close to optimal, but not too similar to each other. With round_trip
, the route will get you back to where you started. This is meant for fun (think of a bike trip), so we will add some randomness. The round_trip
option requires ch.disable=true
. You can control both of these features with additional parameters, see below.
If algorithm=round_trip
, this parameter configures approximative length of the resulting round trip. Requires ch.disable=true
.
If algorithm=round_trip
, this sets the random seed. Change this to get a different tour for each value.
If algorithm=alternative_route
, this parameter sets the number of maximum paths which should be calculated. Increasing can lead to worse alternatives.
If algorithm=alternative_route
, this parameter sets the factor by which the alternatives routes can be longer than the optimal route. Increasing can lead to worse alternatives.
curl -i -X POST \
'https://graphhopper.com/api/1/route?key=YOUR_API_KEY_HERE' \
-H 'Content-Type: application/json' \
-d '{
"profile": "bike",
"points": [
[
11.539421,
48.118477
],
[
11.559023,
48.12228
]
],
"point_hints": [
"Lindenschmitstraße",
"Thalkirchener Str."
],
"snap_preventions": [
"motorway",
"ferry",
"tunnel"
],
"details": [
"road_class",
"surface"
]
}'
Routing Result
The number of seconds that you have to wait before a reset of the credit count is done.
The total distance, in meters. To get this information for one 'leg' please read this blog post.
The total travel time, in milliseconds. To get this information for one 'leg' please read this blog post.
The geometry of the route. The format depends on the value of points_encoded
.
The geometry of the route. The format depends on the value of points_encoded
.
The geometry of the route. The format depends on the value of points_encoded
.
The snapped input points. The format depends on the value of points_encoded
.
The snapped input points. The format depends on the value of points_encoded
.
The snapped input points. The format depends on the value of points_encoded
.
Whether the points
and snapped_waypoints
fields are polyline-encoded strings rather than JSON arrays of coordinates. See the field description for more information on the two formats.
The bounding box of the route geometry. Format: [minLon, minLat, maxLon, maxLat]
.
The instructions for this route. This feature is under active development, and our instructions can sometimes be misleading, so be mindful when using them for navigation.
Details, as requested with the details
parameter. Consider the value {"street_name": [[0,2,"Frankfurter Straße"],[2,6,"Zollweg"]]}
. In this example, the route uses two streets: The first, Frankfurter Straße, is used between points[0]
and points[2]
, and the second, Zollweg, between points[2]
and points[6]
. Read more about the usage of path details here.
{ "hints": { "visited_nodes.sum": 58, "visited_nodes.average": 58 }, "info": { "copyrights": [ "GraphHopper", "OpenStreetMap contributors" ], "took": 2 }, "paths": [ { "distance": 1791.011, "weight": 307.852443, "time": 370962, "transfers": 0, "points_encoded": false, "bbox": [ 11.539424, 48.118343, 11.558901, 48.122364 ], "points": { "type": "LineString", "coordinates": [ [ 11.539424, 48.118352 ], [ 11.540387, 48.118368 ], [ 11.54061, 48.118356 ], [ 11.541941, 48.118409 ], [ 11.543696, 48.118344 ], [ 11.547167, 48.118343 ], [ 11.548478, 48.118366 ], [ 11.548487, 48.119329 ], [ 11.548807, 48.119328 ], [ 11.549408, 48.119366 ], [ 11.550349, 48.119508 ], [ 11.550441, 48.119473 ], [ 11.551109, 48.119467 ], [ 11.551553, 48.119445 ], [ 11.551748, 48.119398 ], [ 11.552087, 48.119475 ], [ 11.552236, 48.119542 ], [ 11.552353, 48.119635 ], [ 11.553853, 48.121136 ], [ 11.555448, 48.12039 ], [ 11.555797, 48.120206 ], [ 11.55632, 48.120592 ], [ 11.556716, 48.120919 ], [ 11.557326, 48.121345 ], [ 11.558901, 48.122364 ] ] }, "instructions": [ { "distance": 672.954, "heading": 89.04, "sign": 0, "interval": [ 0, 6 ], "text": "Continue onto Lindenschmitstraße", "time": 144703, "street_name": "Lindenschmitstraße" }, { "distance": 107.145, "sign": -2, "interval": [ 6, 7 ], "text": "Turn left", "time": 22675, "street_name": "" }, { "distance": 140.169, "sign": 2, "interval": [ 7, 10 ], "text": "Turn right onto Oberländerstraße", "time": 28032, "street_name": "Oberländerstraße" }, { "distance": 360.232, "sign": 1, "interval": [ 10, 18 ], "text": "Turn slight right", "time": 72677, "street_name": "" }, { "distance": 177.621, "sign": 2, "interval": [ 18, 20 ], "text": "Turn right onto Thalkirchner Straße", "time": 35524, "street_name": "Thalkirchner Straße" }, { "distance": 332.89, "sign": -2, "interval": [ 20, 24 ], "text": "Turn left onto Thalkirchner Straße", "time": 67351, "street_name": "Thalkirchner Straße" }, { "distance": 0, "sign": 4, "last_heading": 45.67046584987792, "interval": [ 24, 24 ], "text": "Arrive at destination", "time": 0, "street_name": "" } ], "legs": [], "details": {}, "ascend": 6.3294677734375, "descend": 25.0579833984375, "snapped_waypoints": { "type": "LineString", "coordinates": [ [ 11.539424, 48.118352 ], [ 11.558901, 48.122364 ] ] } } ] }
Geocoding describes the process of transforming an textual address representation to a coordinate (latitude,longitude
). For example the conversion from Berlin
to 52.5170365,13.3888599
.
Reverse geocoding converts a coordinate to a textual address representation or place name. Find out more about Geocoding itself on Wikipedia.
An isochrone of a location is ''a line connecting points at which a vehicle arrives at the same time'', see Wikipedia. With the same API you can also calculate isodistances, just use the parameter distance_limit instead of time_limit`.
Some possible areas in which this API may be useful to you:
See the clients section in the main documentation, and our API explorer.
You can snap measured GPS points typically as GPX files to a digital road network to e.g. clean data or attach certain data like elevation or turn instructions to it.
See the clients section in the main documentation, and our API explorer.
The cost for one request depends on the number of GPS location and is documented here.
One request should not exceed the Map Matching API location limit depending on the package, see the pricing in our dashboard.
It solves the “capacity clustering problem” by assigning a set of customers to a given number of distinct groups (called clusters). The API “clusters” by minimizing the total distance from each individual customer to its designated group median. It can also consider minimum and maximum capacity restrictions for each group.
Clustering can be used in many practical applications. For example, it can help to plan territories, i.e. territory optimization for field teams with large territories for field workers, or to solve large vehicle routing problems (VRP).
Try Clustering in our API Explorer!
The idea is to divide a certain number of customers, a pre-specified number of clusters. As already written above, a distribution is sought that minimizes the total cost (e.g. distance or time or a function of distance and time). We currently support two approaches.
You can simply define a certain number of clusters via configuration ("clustering" with empty set of "clusters") and additionally how many customers should be in such a cluster. This is defined by an upper and lower limit ("min_quantity" and "max_quantity). The algorithm then searches for suitable clusters and divides the customers into these clusters.
You can explicitly define clusters via "clusters". In this way, each individual cluster can be defined. This approach not only allows each cluster to have its own capacity upper and lower bound, but each cluster can also be assigned a fixed cluster center. In contrast to 1. the algorithm then does not search for a suitable center, but assigns the customers given the fixed centers to each cluster. Note that if you define clusters explicitly, any configuration of "clustering" will be overwritten by these explicit clusters.
A custom model allows you to modify the default routing behavior of a vehicle profile by specifying a set of rules in JSON language. There are three JSON properties to change a profile: priority
, speed
and distance_influence
that are described in great detail in the next sections and you can get a quick overview in this example-driven blog post.
But first we will give an introductory example for each of these JSON properties. Let's start with speed
:
{
"speed": [{
"if": "road_class == MOTORWAY",
"limit_to": "90"
}]
}
As you might have already guessed this limits the speed on motorways to 90km/h. Changing the speed will of course change the travel time, but at the same time this makes other road classes more likely as well, so you can use this model to avoid motorways.
You can immediately try this out in the Browser on GraphHopper Maps. GraphHopper Maps offers an interactive text editor to comfortably enter custom models. You can open it by pressing the "custom" button. It will check the syntax of your custom model and mark errors in red. You can press Ctrl+Space or Alt+Enter to retrieve auto-complete suggestions. Pressing Ctrl+Enter will send a routing request for the custom model you entered. To disable the custom model you click the "custom" button again.
In the second example we show how to avoid certain road classes without changing the travel time:
{
"priority": [{
"if": "road_class == LIVING_STREET || road_class == RESIDENTIAL || road_class == UNCLASSIFIED",
"multiply_by": "0.1"
}]
}
This example avoids certain smaller streets. View it in GraphHopper Maps.
The third example shows how to prefer shortest paths:
{
"distance_influence": 200
}
View this example in GraphHopper Maps.
There is a fourth JSON property areas
that allows you to define areas that can then be used in the if
or else_if
conditions for speed
and priority
. Please read more about this and the other properties below and try some examples in GraphHopper Maps with the help of this blog post.
You can create routing profiles that are customized to your needs. You can take advantage of all the modelling options described in the Custom Model section and use the created custom profile (prefix cp_
) with our Routing, Matrix and Route Optimization APIs.
Important notes
car
, bike
, foot
and ecargobike
. Contact us if you have different requirements. Motor vehicles can be emulated like done for truck
in this post.A curl example:
curl -X POST -H "Content-Type: application/json" "https://graphhopper.com/api/1/profiles?key=YOUR_KEY" -d '{"bounds":{"bbox":[11.45462,48.00954,11.77322,48.2076]},"custom_model":{"priority":[{"if":"road_class == MOTORWAY","multiply_by":"0"}]},"profile":"car"}'
If you plan to tweak your custom_model frequently it is recommended to initially use the Routing API where a different custom model can be specified in every request. Or use GraphHopper Maps and click the gear button.
Creating custom profiles using the API Explorer
Besides using the /profiles
endpoint directly you can also create custom profiles from our API explorer.
id
from the output window (it starts with cp_
)."profile": "car"
(vehicle_types
section) with the profile id
and click "Send":You should now see that the solution no longer uses motorways. Keep in mind that this is a simple example. The custom model language is a lot more powerful than this. Make sure you read the Custom Model section to learn about all the details.
Note that you can use the profile id
just as well for the /matrix
or /route
endpoint. E.g. select "Routing API" and use the profile id
in the request: