3 The Nominatim search frontend is implemented as a Python library and can as
4 such directly be used in Python scripts and applications. You don't need to
5 set up a web frontend and access it through HTTP calls. The library gives
6 direct access to the Nominatim database through similar search functions as
7 offered by the web API. In addition, it will give you a more complete and
8 detailed view on the search objects stored in the database.
12 The Nominatim library is used for accessing a local Nominatim database.
13 It is not meant to be used against web services of Nominatim like the
14 one on https://nominatim.openstreetmap.org. If you need a Python library
15 to access these web services, have a look at
16 [GeoPy](https://geopy.readthedocs.io). Don't forget to consult the
17 usage policy of the service you want to use before accessing such
22 To use the Nominatim library, you need access to a local Nominatim database.
23 Follow the [installation](../admin/Installation.md) and
24 [import](../admin/Import.md) instructions to set up your database.
26 The Nominatim frontend library is contained in the Python package `nominatim-api`.
27 You can install the latest released version directly from pip:
29 pip install nominatim-api
31 To install the package from the source tree directly, run:
33 pip install packaging/nominatim-api
35 Usually you would want to run this in a virtual environment.
37 ### A simple search example
39 To query the Nominatim database you need to first set up a connection. This
40 is done by creating an Nominatim API object. This object exposes all the
41 search functions of Nominatim that are also known from its web API.
43 This code snippet implements a simple search for the town of 'Brugge':
46 === "NominatimAPIAsync"
50 import nominatim_api as napi
52 async def search(query):
53 async with napi.NominatimAPIAsync() as api:
54 return await api.search(query)
56 results = asyncio.run(search('Brugge'))
58 print('Cannot find Brugge')
60 print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
65 import nominatim_api as napi
67 with napi.NominatimAPI() as api:
68 results = api.search('Brugge')
71 print('Cannot find Brugge')
73 print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
76 The Nominatim library is designed around
77 [asyncio](https://docs.python.org/3/library/asyncio.html). `NominatimAPIAsync`
78 provides you with an interface of coroutines.
79 If you have many requests to make, coroutines can speed up your applications
82 For smaller scripts there is also a synchronous wrapper around the API. By
83 using `NominatimAPI`, you get exactly the same interface using classic functions.
85 The examples in this chapter will always show-case both
86 implementations. The documentation itself will usually refer only to
87 'Nominatim API class' when both flavours are meant. If a functionality is
88 available only for the synchronous or asynchronous version, this will be
91 ### Defining which database to use
93 The [Configuration](../admin/Import.md#configuration-setup-in-env)
94 section explains how Nominatim is configured using the
95 [dotenv](https://github.com/theskumar/python-dotenv) library.
96 The same configuration mechanism is used with the
97 Nominatim API library. You should therefore be sure you are familiar with
100 There are three different ways, how configuration options can be set for
101 a 'Nominatim API class'. When you have set up your Nominatim database, you
102 have normally created a [project directory](../admin/Import.md#creating-the-project-directory)
103 which stores the various configuration and customization files that Nominatim
104 needs. You may pass the location of the project directory to your
105 'Nominatim API class' constructor and it will read the .env file in the
106 directory and set the configuration accordingly.
108 You may also configure Nominatim by setting environment variables.
109 Normally Nominatim will check the operating system environment. Lets
110 say you want to look up 'Brugge' in the special database named 'belgium' instead of the
111 standard 'nominatim' database. You can run the example script above like this:
114 NOMINATIM_DATABASE_DSN=pgsql:dbname=belgium python3 example.py
117 The third option to configure the library is to hand in the configuration
118 parameters into the 'Nominatim API class'. Changing the database would look
122 === "NominatimAPIAsync"
125 import nominatim_api as napi
128 'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
131 async def search(query):
132 async with napi.NominatimAPIAsync(environ=config_params) as api:
133 return await api.search(query)
135 results = asyncio.run(search('Brugge'))
140 import nominatim_api as napi
143 'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
146 with napi.NominatimAPI(environ=config_params) as api:
147 results = api.search('Brugge')
150 When the `environ` parameter is given, then only configuration variables
151 from this dictionary will be used.
153 ### Presenting results to humans
155 All search functions return full result objects from the database. Such a
156 result object contains lots of details: names, address information, OSM tags etc.
157 This gives you lots of flexibility what to do with the results.
159 One of the most common things to get is some kind of human-readable label
160 that describes the result in a compact form. Usually this would be the name
161 of the object and some parts of the address to explain where in the world
162 it is. To create such a label, you need two things:
164 * the address details of the place
165 * all names for the label adapted to the language you wish to use for display
167 Again searching for 'Brugge', this time with a nicely formatted result:
170 === "NominatimAPIAsync"
174 import nominatim_api as napi
176 async def search(query):
177 async with napi.NominatimAPIAsync() as api:
178 return await api.search(query, address_details=True)
180 results = asyncio.run(search('Brugge'))
182 locale = napi.Locales(['fr', 'en'])
183 for i, result in enumerate(results):
184 address_parts = result.address_rows.localize(locale)
185 print(f"{i + 1}. {', '.join(address_parts)}")
190 import nominatim_api as napi
192 with napi.NominatimAPI() as api:
193 results = api.search('Brugge', address_details=True)
195 locale = napi.Locales(['fr', 'en'])
196 for i, result in enumerate(results):
197 address_parts = result.address_rows.localize(locale)
198 print(f"{i + 1}. {', '.join(address_parts)}")
201 To request information about the address of a result, add the optional
202 parameter 'address_details' to your search:
205 >>> results = api.search('Brugge', address_details=True)
208 An additional field `address_rows` will set in results that are returned.
209 It contains a list of all places that make up the address of the place. For
210 simplicity, this includes name and house number of the place itself. With
211 the names in this list it is possible to create a human-readable description
212 of the result. To do that, you first need to decide in which language the
213 results should be presented. As with the names in the result itself, the
214 places in `address_rows` contain all possible name translation for each row.
216 The library has a helper class `Locale` which helps extracting a name of a
217 place in the preferred language. It takes a single parameter with a list
218 of language codes in the order of preference. So
221 locale = napi.Locale(['fr', 'en'])
224 creates a helper class that returns the name preferably in French. If that is
225 not possible, it tries English and eventually falls back to the default `name`
228 The `Locale` object can be applied to a name dictionary to return the best-matching
232 >>> print(locale.display_name(results[0].names))
236 The `address_row` field has a helper function to apply the function to all
237 its members and save the result in the `local_name` field. It also returns
238 all the localized names as a convenient simple list. This list can be used
239 to create a human-readable output:
242 >>> address_parts = results[0].address_rows.localize(locale)
243 >>> print(', '.join(address_parts))
244 Bruges, Flandre-Occidentale, Flandre, Belgique
247 This is a fairly simple way to create a human-readable description. The
248 place information in `address_rows` contains further information about each
249 place. For example, which OSM `admin_level` was used, what category the place
250 belongs to or what rank Nominatim has assigned. Use this to adapt the output
251 to local address formats.
253 For more information on address rows, see
254 [detailed address description](Result-Handling.md#detailed-address-description).