Become a Patron!

My Amazon wishlist can be found here.

Life Line

Address lookups with Leaflet and Nominatim

I recently wrote a patch for to add a map of an event's location to the event detail page. With the same patch, I also replaced the location part of the event edit page with a solution that uses JQuery, Leaflet as map API, OpenStreetMap tiles and Nominatim for doing address lookups. This article forms a small tutorial on how to use this same set-up yourself.

The Basics

To start, we create a new directory for our project:

mkdir addresses
cd addresses

Then I downloaded the Leaflet and jQuery libraries and extracted them in the js directory of the project:

mkdir js
curl -L -o
mv CloudMade-Leaflet-*/dist/* js
rm -rf CloudMade-Leaflet-*
curl -o js/jquery-1.8.2.min.js

As first step, we are simply going to show a map on a web page. The map is going to be full screen, and will not have any bells and whistles. The code to embed a map is small, but we will separate it into three files for clarity: a CSS file for our styles (site.css), an HTML file for the structure (index.html) and a JS file for all our JavaScript functions (js/map.js).

Let's start with the HTML file:

    <title>Leaflet and Nominatim example</title>

    <link rel="stylesheet" href="js/leaflet.css" />
    <!--[if lte IE 8]><link rel="stylesheet" href="js/" /><![endif]-->
    <link rel="stylesheet" type="text/css" href="site.css">

    <script src="js/leaflet.js"></script>
    <script src="js/jquery-1.8.2.min.js"></script>
    <div id="map"/>
    <script src="js/map.js"></script>

This HTML file includes the Leaflet and jQuery libraries, as well as the default CSS file that Leaflet needs. We are also including our own CSS file (site.css):

body {
  margin: 0;
div#map {
  width: 100%;
  height: 100%;

In the body of the HTML file, we place a <div> as contained for the map, and then include a JavaScript file that is responsible for embedding them map:

var map;

function load_map() {
  map = new L.Map('map', {zoomControl: false});

  var osmUrl = 'http://{s}{z}/{x}/{y}.png',
    osmAttribution = 'Map data &copy; 2012 <a href="">OpenStreetMap</a> contributors',
    osm = new L.TileLayer(osmUrl, {maxZoom: 18, attribution: osmAttribution});

  map.setView(new L.LatLng(51.538594, -0.198075), 12).addLayer(osm);

window.onload = load_map;

If you request the index.html page now through the browser, you will see something like:

Adding the Address Search

In order to add an address lookup form, we need to add more HTML. Our HTML will feature an input box (for the address), a submit button, and a place holder to show our results in. We add this code between the <div id="map"/> and the <script... tags:

<div id="search">
  <input type="text" name="addr" value="" id="addr" size="10" />
  <button type="button" onclick="addr_search();">Search</button>
  <div id="results"/>

To style this, we add the following at the end of our CSS file:

div#search {
  background-color: white;
  position: absolute;
  bottom: 40px;
  left: 40px;
  width: auto;
  height: auto;
  padding: 10px;
div#search input {
  width: 200px;
div#results {
  font-style: sans-serif;
  color: black;
  font-size: 75%;

If we reload the page in our browser, we will see something like:

Now the only thing left to do is to implement the addr_search function. In our JS file (js/map.js) we add before window.onload = load_map; the following lines (split over multiple sections in this tutorial):

function addr_search() {
  var inp = document.getElementById("addr");

  $.getJSON('' + inp.value, function(data) {

This above line uses jQuery's AJAX capabilities to request a URL, parse the JSON result and issue a callback if it worked. We query Nominatim here, with as format json and limiting the result to 5 items. Nominatim also supports other parameters, which are documented here.

var items = [];

$.each(data, function(key, val) {
    "<li><a href='#' onclick='chooseAddr(" + + ", " + val.lon + ");return false;'>" + val.display_name +

For each of the items in our result, we create an <li> element which has an <a href containing a call to a JavaScript function (chooseAddr). This function is responsible for re-centering the map according to the picked latitude and longitude.

    if (items.length != 0) {
      $('<p>', { html: "Search results:" }).appendTo('#results');
      $('<ul/>', {
        'class': 'my-new-list',
        html: items.join('')
    } else {
      $('<p>', { html: "No results found" }).appendTo('#results');

This processes the results that came back from Nominatim. If there are results, we shows those including a Search results: header, and if there are no results, we show No results found.

Then we need to add one more function, the chooseAddr function which looks like:

function chooseAddr(lat, lng, type) {
  var location = new L.LatLng(lat, lng);

  if (type == 'city' || type == 'administrative') {
  } else {

We simply use the latitude and longitude from the function invocation, and in order to make things slightly nicer we zoom in a bit less if the item type is either a city or an administrative border. As each of the returned results actually includes a full bounding box, we probably can use that to zoom in better, but I will leave that for your own experiments - you'd want the panInsideBounds() method of Leaflet's Map class for that.

In the end, if we click on the Search button, a list is presented of all our search results:

And after clicking one of the links, we see the map centered on Paris:

The code for this example is available on github in my osm-tools repository at


This article has a short URL available:


Thanks man, this tutorial help me a lot! Well explained and detailed.

Nice...thanks a lot!!!

Thank you so much

Add Comment


Will not be posted. Please leave empty instead of filling in garbage though!

Please follow the reStructured Text format. Do not use the comment form to report issues in software, use the relevant issue tracker. I will not answer them here.

All comments are moderated