GraphHopper Routing Engine 3.0 Released

Today we are happy to announce the new release of our open source routing engine. It is again packed with new features, bug fixes and nice improvements. This time we put our main focus on the custom routing feature that we already included in version 1.0 about a year ago. With the GraphHopper engine you can calculate ideal routes for different motorized vehicles, bikes and walking modes for every city and country in the world, because it builds on the comprehensive map data provided by OpenStreetMaps.

With custom routing you can take this one step further and adjust the route calculations to your personal preferences, properties of your vehicle or peculiarities of the map data in your region. For example it is now easy to avoid motorways, ferries, toll roads or entire areas. You can also use certain OpenStreetMap properties like surface, max_speed, hazmat (hazardous materials), max_weight etc. to specify on which roads you like to drive or to adjust your typical driving speed.
And the best part: all this is possible without any programming knowledge!

Now let’s take a look at the most important changes in our new release 3.0:

Custom Routing

As you might already know the custom routing feature is based on a set of rules that you can use to specify the speed and priority depending on the road attributes. These rules are written in the simple JSON syntax and for the new release we made the syntax a lot more powerful and readable. For example you can now easily combine road attributes to set rules like “lower the speed on tertiary gravel roads” or limit a rule to a certain area. With these changes we are now confident that the syntax covers most use-cases and we are already planning to include more possibilities like setting up turn costs or including elevation data.

We also made it a lot more comfortable for you to enter custom routing rules. Our GraphHopper Maps app now includes an interactive text editor that guides you when writing a custom model. It not only notifies you about syntax errors, but also shows auto-complete suggestions about what kind of rules you can set up and what kind of road attributes are contained in the underlying map data used by your GraphHopper instance.

Try it out on GraphHopper Maps!

The custom model editor in the sidebar of GraphHopper Maps helps you write custom routing rules. Here we see that the road attributes road_access,road_class,road_class_link,road_environment are available in the current context. Use Ctrl+Space or Alt+Enter to open this popup.

The custom model rules you can see in the above screenshot are now simply written as a separate custom_model field in the routing request that you can send to the POST /route endpoint of the GraphHopper server. We removed the /route-custom endpoint as it is no longer needed and /route now fully supports custom routing. For more details please take a look at the documentation and if you’d like to use custom routing for our commercial GraphHopper Directions API please contact us.

There is one more thing we’d like to point out: Custom routing models can not only be used on a per-request basis, but you can copy and paste your favorite model to your server-side configuration and use it with GraphHopper’s speed-up techniques like Contraction Hierarchies and Landmarks as well to achieve blazing fast response times.

Give it a try and read our updated blog post with many more details and examples for GraphHopper Maps.

Path Details

We improved the visualization of path details in GraphHopper Maps and this is especially useful in combination with custom routing. With path details you can show the different road attributes along your route.

The path details are shown if used in the custom model. Switch between them via the black triangle up/down buttons in the bottom right corner.

Improved performance

GraphHopper should not only be highly customizable, but one of our main goals is that it also works really fast. In this release we made big improvements in this direction again:

  • A 30% faster OpenStreetMap import, see #2191.
  • A 25% faster speed mode (we fixed AStar for edge-based CH routing and made it the default again), see #2215.
  • Reduced memory usage during preparation and 20-30% less memory used per speed mode profile (CH profiles), see #2169 and #2174.
  • Reduced data size for /spt (#2192)

Map Matching

We moved our previously separate repository “graphhopper/map-matching” for the “snap to road” feature into “graphhopper/graphhopper” to make usage and development easier. See the new documentation.

See the “snap to road” feature in action. Black is the original GPS track and green the snapped result.


We added a new demo app to show the results of our /isochrone and /spt endpoints. With this you can now see the shortest path tree or isochrones (line of points with equal distances from an origin point) in your browser. It does not support custom routing requests, yet, but you can already use it with custom models defined in your server configuration.

We integrated a simple demo for the reachable area. I.e. you can open this UI on your server and click on the map to see which area from this point is reachable for your (customized) profile. © OpenStreetMap contributors

Other changes and improvements

We merged over 70 pull requests. Some of the most noteworthy changes are:

  • We moved our examples from the documentation directly into our code. This way they are always up-to date and you can easily run them on your own and start working with GraphHopper from there. It’s all in the graphhopper-example module. (#2143)
  • We rehauled our LocationIndex code. This makes sure your query points are properly snapped onto the actual road network (#2216)
  • We now use a dedicated subnetwork encoded value to identify isolated fragments of the road network (#2290)
  • Custom models can now be written directly in config.yml or put into separate JSON or YAML files in an arbitrary directory (#2232)
  • There is a new tolerance parameter for the /isochrone endpoint (#2126)
  • Public transport fares are now multi-feed aware.
  • The GH server now has a /health endpoint (#2148)
  • We improved the border handling of spatial rules (#2188)
  • New encoded values like mtb_scale and sac_scale and path details like get_off_bike (#2138, #2158)
  • Handling of no_entry turn restrictions
  • Improved location lookup for map-matching (#2262)
  • Subnetwork search now always runs edge-based (#2280)
  • We moved the reader-osm and isochrone modules into core
  • Updated to the latest dropwizard (#2183) and made it running with the latest JDK 16 (#2187).
  • Many bug-fixes like server-side custom models not working with turn costs (#2176)
  • Several more refactoring changes, see our changelog for breaking changes.
  • Two security bugs were fixed, backported to 2.x and released. You should use the new releases now, even if you use the GraphHopper routing engine behind a proxy. Please note that we support only the latest stable version with security updates and so it is highly recommended to upgrade to 3.x as fast as possible.
  • We removed the Dockerfile as it wasn’t really maintained. You can still install GraphHopper in two simple steps and use that for your Dockerfile.


Thanks to all contributors:

easbar, michaz, joe-akeem, GProbo, otbutz, karussell, boldtrn, HarelM, hoofstephan, braito4

Last but not least we made it even easier to contribute to our open source projects. Just add yourself to the contributor list in your first contribution and you are done. No need to sign a CLA, even though we never used the CLA to change ownership or similar. See this issue for more details. Of course you still have to agree that your contribution stands under the Apache License 2.0.

Try it today

You can try the GraphHopper routing engine via GraphHopper Maps or install it locally.

Happy routing!