# Add address autocomplete and route planning with free APIs

Page: https://free-web-services.com/guides/address-autocomplete-and-routes/

Suggest addresses while a visitor types, then show the driving distance and time between two of them. It uses OpenStreetMap data through Photon and OSRM, without an API key, straight from the browser.

## What you need

[Photon](https://free-web-services.com/web-services/geo/location-info/photon.html) is a geocoder made for search-as-you-type: it tolerates typos and answers fast. The [OSRM demo server](https://free-web-services.com/web-services/geo/location-info/osrm-api.html) calculates routes on OpenStreetMap roads. Both are free without a key on their public servers, within fair use, and both allow calls from web pages.

Why not [Nominatim (OpenStreetMap)](https://free-web-services.com/web-services/geo/location-info/nominatim-openstreetmap.html)? Its usage policy does not allow autocomplete on the public server, and it allows at most one request per second. Use Nominatim to look up a full address once, Photon while people type.

## Step 1: suggestions while typing

Photon answers with GeoJSON: each suggestion is a feature with `properties` (name, street, house number, postcode, city, country) and `geometry.coordinates` as longitude, latitude. `limit` sets the number of suggestions, `lang` the language of place names, and `lat` and `lon` favour results near a point.

```sh
curl 'https://photon.komoot.io/api/?q=Damrak%201&limit=5&lang=en&lat=52.37&lon=4.89'
```

## Step 2: the route

OSRM takes the start and end as `longitude,latitude;longitude,latitude` in the address. `overview=false` leaves out the route's shape when you only need numbers. The answer gives `distance` in metres and `duration` in seconds. The public demo server routes cars, is meant for light, non-commercial use and allows one request per second.

```sh
curl 'https://router.project-osrm.org/route/v1/driving/4.8913,52.3731;5.1214,52.0907?overview=false'
```

## Step 3: the complete page

Two address fields with suggestions. The script waits until someone stops typing for 300 milliseconds before it asks Photon, so a fast typist does not send a request per key, and it only asks from the third character. When both addresses are chosen it asks OSRM for the route.

```html
<label>From <input id="from" autocomplete="off"></label>
<ul id="from-list"></ul>
<label>To <input id="to" autocomplete="off"></label>
<ul id="to-list"></ul>
<p id="route"></p>
<p><small>Data © OpenStreetMap contributors</small></p>

<script>
const chosen = {};

function label(properties) {
  const street = [properties.street || properties.name, properties.housenumber].filter(Boolean).join(' ');
  return [street, properties.postcode, properties.city, properties.country].filter(Boolean).join(', ');
}

function autocomplete(field) {
  const input = document.getElementById(field);
  const list = document.getElementById(field + '-list');
  let timer = null;
  input.addEventListener('input', () => {
    clearTimeout(timer);
    delete chosen[field];
    if (input.value.trim().length < 3) {
      list.replaceChildren();
      return;
    }
    timer = setTimeout(async () => {
      const url = 'https://photon.komoot.io/api/?limit=5&lang=en&q=' + encodeURIComponent(input.value);
      const data = await (await fetch(url)).json();
      list.replaceChildren(...data.features.map((feature) => {
        const item = document.createElement('li');
        const button = document.createElement('button');
        button.type = 'button';
        button.textContent = label(feature.properties);
        button.addEventListener('click', () => {
          input.value = button.textContent;
          chosen[field] = feature.geometry.coordinates;
          list.replaceChildren();
          showRoute();
        });
        item.append(button);
        return item;
      }));
    }, 300);
  });
}

async function showRoute() {
  if (!chosen.from || !chosen.to) {
    return;
  }
  const points = chosen.from.join(',') + ';' + chosen.to.join(',');
  const data = await (await fetch('https://router.project-osrm.org/route/v1/driving/' + points + '?overview=false')).json();
  const output = document.getElementById('route');
  if (data.code !== 'Ok') {
    output.textContent = 'No route found.';
    return;
  }
  const route = data.routes[0];
  output.textContent = 'By car: ' + (route.distance / 1000).toFixed(1) + ' km, about '
    + Math.round(route.duration / 60) + ' minutes.';
}

autocomplete('from');
autocomplete('to');
</script>
```

## Going further

Credit OpenStreetMap wherever you show its data, as the page above does. For a busy or commercial site, do not lean on the public servers: Photon and OSRM are open source and can run on your own server.

Prefer a hosted service? [Geoapify](https://free-web-services.com/web-services/geo/location-info/geoapify.html) offers autocomplete, routing and more on OpenStreetMap data with a free key, 3,000 credits a day, also for commercial use. For walking, cycling, trucks or wheelchairs, use [OpenRouteService](https://free-web-services.com/web-services/geo/location-info/openrouteservice.html), which has profiles for each.

## The APIs in this guide

- [Photon](https://free-web-services.com/web-services/geo/location-info/photon.md)
- [OSRM demo server](https://free-web-services.com/web-services/geo/location-info/osrm-api.md)
- [Nominatim (OpenStreetMap)](https://free-web-services.com/web-services/geo/location-info/nominatim-openstreetmap.md)
- [Geoapify](https://free-web-services.com/web-services/geo/location-info/geoapify.md)
- [OpenRouteService](https://free-web-services.com/web-services/geo/location-info/openrouteservice.md)

Updated November 1st, 2026
