NAME
Net::API::Nominatim - Perl client for local or public OpenStreetMap
Nominatim Geocoding service. Open source, unrestricted and free.
VERSION
Version 0.02
!NOMINATIM!
Nominatim uses OpenStreetMap
data to find coordinates for locations
on Earth by name and address (geocoding). It can also do the reverse,
find an address for any location on the planet, given coordinates.
Nominatim provides a public, free and un-restricted service, subject to
fair usage, at https://nominatim.openstreetmap.org/ui/search.html for
all of your geocoding needs.
Most importantly, a Nominatim server can be easily installed locally if
you intend to geocode heavily or you do not have network access.
Nominatim uses open source geocoding data provided by OpenStreetMap
. When you install Nominatim locally,
you also install this geocoding data locally. The data is broken into
different geographical locations so you can geocode for just your
district, your country, your continent or the whole planet without
relying on the closely guarded and prohibitevely copyrighted (really?)
data provided by the usual big Capitalist players.
If you decided to install Nominatim locally for your own geocoding
needs it is also worth installing a Map Tile Server in order to provide
your own open source maps! All the data open source, courtesy of
OpenStreetMap . Have a look at the guide
at switch2osm.org for how to completely break free and never again have
to rely on the usual big Capitalist players.
For local installations, Nominatim can be accessed via a UNIX socket.
This should be the fastest method to geocode locally. Unless you have
implemented intermediate caching. Alternatively, for local or public
Nominatim service, you can make a simple HTTP/GET query.
This module offers both local UNIX socket and HTTP/GET queries.
Remember, Capitalism is changing really fast, to the uglier, to the
hungrier, to the scummier, by the day. Right now it is very hungry. It
will become even more so. It is not a matter of "immoral", "stupid",
"greedy" leaders "running" (yeah! right) the show, it is a matter of
processes. The processes will continue irrespective of leaders. To the
End.
As a matter of life or death, break away from Capitalism NOW.
SYNOPSIS
The current module provides functionality to query a Nominatim server,
either via a local UNIX socket, if Nominatim is installed locally, or
via HTTP/GET requests if you rely on the public Nominatim service. The
Nominatim API
is extensive. But the current module covers only basic forward and
reverse geocoding queries only with /search, /reverse and /status.
Example usage:
use Net::API::Nominatim;
my $cparams = {
'server' => {
'url' => 'https://nominatim.openstreetmap.org',
},
# optional debug
'debug' => {
'verbosity' => 666,
},
# optional logger
'log' => {
'logger-file' => Mojo::Log->new,
}
};
my $client = Net::API::Nominatim->new($cparams);
my $addresses = $client->search({
q => 'Leika',
});
# we now have an ARRAY_REF of
# Net::API::Nominatim::Model::Address objects back
# these objects contain many useful things including
# proper address, coordinates and bounding box!
# Thank you OpenStreetMap!
print $_->toString()."\n" for @$addresses;
# or just get the JSON string back
my $jsonresponse = $client->search({
q => 'Leika',
'want-json' => 1,
});
# You can be more specific with a structured query
my $addresses = $client->search({
street => 'Leika',
city => 'Honolulu',
# county, country, etc.
});
# a structured query allows you to search for amenities
my $addresses = $client->search({
amenity => 'restaurant',
city => 'Honolulu',
# county, country, etc.
});
# Reverse geo-coding: from coordinates to address
my $address = $client->reverse({
lon => '15.014879', # quote them, you never know with floats ...
lat => '38.022967',
});
# it returns a single Net::API::Nominatim::Model::Address object
print $address->toString()."\n";
# server status
print "alive!\n" if $client->status();
METHODS
new()
The constructor.
The full list of arguments, provided as a hashref, is as follows:
* server : a HASH_REF with one of these keys:
* url : specify the Nominatim server URL, for example the public
service is located at
https://nominatim.openstreetmap.org/ui/search.html.
* unix-socket : alternatively, if you have installed Nominatim
locally, you may want to query it directly via its UNIX socket.
This should then be the fullpath to the local UNIX socket (which
must have the appropriate permissions for the current user).
* log : a HASH_REF with one of these keys:
* logger-file : a filename to log into, or,
* logger-object : an already existing logger object which
implements methods info(string), warn(string) and error(string).
* lwpuseragent : only applicable if doing HTTP queries (and not UNIX
socket). This is HASH_REF with some of these keys:
* cookies-object : specify a cookies object for loading and saving
session cookies, optional and most likely unused,
* lwpuseragent-object : specify an already existing LWP::UserAgent
object to use. WARNING: this object will have its UserAgent String
altered to comply with Nominatim's usage policy which states it
must be a string to identify the client. So, this will be our
client's UserAgent String. If you intend to use the specified
LWP::UserAgent object then save its agent string (my $oldstr =
$ua->agent;) and reload it later ($ua->agent($oldstr);).
* useragent-string : DO NOT SPECIFY your own UserAgent String
PLEASE. There is already a default for this which identifies this
current client uniquely. So, you do not need to set this. But if
you wish to do so, then nobody stops you.
The constructor will return undef on failure (but will not die).
Caveat
The user-specified HASH_REF of parameters into the constructor will be
modified. Some fields will be added and some fields will be deleted. It
would be ideal if it was cloned but since it can contain OBJECT
references I find it difficult to tell Clone or Storable to skip
cloning objects.
search()
It does free-form or structured address search. The full list of
arguments, provided as a hashref, is as follows:
* The search can be free-form or structured. In case of free-form
search you need to specify only q as a free-form address string. In
case of a structured search you must NOT specify q at all but specify
some of the other fields as specified below. Note that all strings
will be url-encoded internally, taking into account if are unicode'd,
do not url-encode them yourself.
* q : a free-form address string. It will be url-encoded when
making the query so do not encode it yourself.
* alternatively use some of these for a structured search: amenity,
street, city, county, state, country, postalcode. See the
structured search API
for more details.
* want-json : optionally, specify whether you want to have the raw
server response back as a JSON string. This will save some time
decoding the JSON into Net::API::Nominatim::Model::Address objects.
* query-params : optionally specify extra query params to your search
as a HASH_REF. See the Nominatim Search API
for what
these parameters can be. By default, you do not need to specify any
of these extra parameters.
It returns undef on communication failure.
It returns back an ARRAY_REF of zero, one or more
Net::API::Nominatim::Model::Address objects on success. Unless the
option want-json was set to 1, in which case the return will be a JSON
(array-of-hashes) string of results.
Warning
Do not mix free-form query parameter (q) with structured query
parameters (e.g. street, country, etc.).
A structured query can return many results depending on how specific it
is. For example, if you specify only amenity=restaurant there can be
hundreds of results but the public Nominatim service has a default
limit of returning only 10 results with a hard-limit of 40.
reverse()
It does a reverse geocoding search. That is, it returns an address when
coordinates are specified.
The full list of arguments, provided as a hashref, is as follows:
* lat : latitude
* lon : longitude
* want-json : optionally, specify whether you want to have the raw
server response back as a JSON string. This will save some time
decoding the JSON into Net::API::Nominatim::Model::Address objects.
* query-params : optionally specify extra query params to your search
as a HASH_REF. See the Nominatim Search API
for what
these parameters can be. By default, you do not need to specify any
of these extra parameters.
It returns undef on communication failure.
It returns back a single Net::API::Nominatim::Model::Address object on
success. Unless the option want-json was set to 1, in which case the
return will be a JSON (hash) string of results.
It differs from search() in that it returns a single address object and
not an ARRAY_REF of objects. The returned JSON will be a hash
containing a single address and not an array.
TODO
The Nominatim API
contains a
lot more "verbs" than the three implemented in this module. Feel free
to provide implementations if you find any of those useful and they
will be incorporated in this module.
CAVEATS
Queries can return many results depending on how specific they are,
especially the structured query. For example, if you specify only
amenity=restaurant there can be hundreds of results but the public
Nominatim service has a default limit of returning only 10 results with
a hard-limit of 40. This is specified in the Nominatim API
under limit.
RELATED OPEN SOURCE SOFTWARE
First of all, OpenStreetMap data is freely available for downloading,
for the whole planet or for specific geographical areas from GeoFabrik
in the form of .osm.pbf files. This
data is understood by Nominatim, the Map tile server and GeoDesk-Gol
mentioned below. This data can also be inserted into a PostGIS
database and make your own queries on it.
I have already mentioned in the INTRODUCTION that it is quite easy and,
definetely, not discouraged to host a Nominatim server locally. It will
be totally self-sufficient in the sense that it will not need to access
any external resources. All addresses for your geographical area or the
whole planet are stored in a local PostGIS ,
powered by the amazing elephant-in-the-server-room PostgreSQL
. Check for what resources are required
though. For small geographical areas, resources are moderate.
You can also host your own map tiles and serve your own high-quality
maps, styled as you like, without relying ever again on the big
Capitalist players. Have a look at the guide offered at Switch2osm
for how you can get started with this,
although far more resources are needed and assembling the toolchain is
more complicated than with Nominatim. But it works, just follow the
guide.
Another open source project is GeoDesk
and the command line query tool
GeoDesk-Gol . This tool takes
OpenStreetMap data for any geographical location, in the form of
.osm.pbf files (see above on where to download them from) and
constructs a portable, file-based database (called Gol, as in scoring a
goal!) which you can then enquire with the provided command line tool.
There is no need to create a PostGIS database
and insert data into it. The Gol file is all you need for doing queries
like, find all restaurants in this neighbourhood, list all street names
in this district, list all bus-stops, etc. It is pretty amazing and
more so because it is portable, no database setup is required. Of
course it is open source and kudos to their creator Clarisma, which
by-the-way I am not affiliated in any way, just a fan.
TESTING
Basic testing (make test) does not require, and, will not attempt
online access. It tests instantiating the client and the other
auxiliary classes.
Live testing needs network access to a public Nominatim server or a
local installation of Nominatim. It comes in two flavours:
* make livetesturl : tests HTTP/GET queries to the public Nominatim
server at https://nominatim.openstreetmap.org/ui/search.html.
* make livetestlocal : tests socket queries to a local Nominatim
installation via its local UNIX socket whose path can be set in all
the test files in directory xt/live/local-socket/ via the $sockpath
variable, currently pointing to /run/nominatim/nominatim.sock.
RESPONSIBLE USE
Be responsible in using the public Nominatim service and please observe
their usage policy, summarised as
* Uniquely and persistently identify your client.
* No more than one request per second.
The first clause we observe here by setting the default User-Agent
string.
The second clause is up to you. Please be responsible and do not forget
that if you are going to do a lot of geocoding install your own
Nominatim server locally. Then you can query it to your heart's
content.
AUTHOR
Andreas Hadjiprocopis,
BUGS
Please report any bugs or feature requests to bug-net-api-nominatim at
rt.cpan.org, or through the web interface at
https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-API-Nominatim. I
will be notified, and then you'll automatically be notified of progress
on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Net::API::Nominatim
You can also look for information at:
* RT: CPAN's request tracker (report bugs here)
https://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-API-Nominatim
* CPAN Ratings
https://cpanratings.perl.org/d/Net-API-Nominatim
* Search CPAN
https://metacpan.org/release/Net-API-Nominatim
ACKNOWLEDGEMENTS
LICENSE AND COPYRIGHT
This software is Copyright (c) 2025 by Andreas Hadjiprocopis.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)