What you need
Photon is a geocoder made for search-as-you-type: it tolerates typos and answers fast. The OSRM demo server 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)? 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.
curl
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.
curl
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 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, which has profiles for each.