The public Nominatim API at nominatim.openstreetmap.org is run by the OpenStreetMap Foundation on donated servers, and its usage policy (read 22 Oct 2026) sets an absolute maximum of 1 request per second, requires an identifying User-Agent, forbids client-side autocomplete, discourages bulk geocoding and may change without notice. For a product with real users you need your own instance or a hosted geocoder. This guide lists the options and shows how to move a Nominatim call to geolith.
What the public policy says
"No heavy uses (an absolute maximum of 1 request per second)." — OpenStreetMap Foundation, Nominatim Usage Policy
From the OSMF Nominatim usage policy, read on 22 Oct 2026:
- No heavy use: an absolute maximum of 1 request per second.
- A valid HTTP Referer or User-Agent that identifies the application; stock library User-Agents are not enough.
- Clear attribution, and the data is under the ODbL.
- Auto-complete search is not supported, and implementing it on the client side with the API is forbidden.
- Bulk geocoding of larger amounts of data is not encouraged; small one-time jobs must be single-threaded on one machine, and scripts that run at regular intervals are limited to 4 requests per minute.
- Results must be cached on your side.
- The policy may change without notice, and access can be withdrawn.
None of that is unreasonable for a free community service. It just is not a production API.
The options
| Option | What you run | Notes |
|---|---|---|
| Self-host Nominatim | PostgreSQL/PostGIS and a full OSM import | Mature, best-known OSM geocoder; no autocomplete |
| Self-host Photon | A Java service and a search index | Search-as-you-type on OSM data |
| Self-host Pelias | Elasticsearch plus importers and services | Flexible, many data sources |
| Self-host geolith | One .glx file and a small server | No database; answered with range reads |
| Hosted geolith | Nothing | 100,000 requests a month free; results may be stored |
On the same India data in Docker (20 Oct 2026, 200 queries per set), top-1 accuracy was:
| Set | geolith | Nominatim | Photon | Pelias |
|---|---|---|---|---|
| OSM places | 95.0 | 85.0 | 80.5 | 77.0 |
| OSM addresses | 95.0 | 50.5 | 88.5 | 61.5 |
| OSM POIs | 84.5 | 68.5 | 85.5 | 61.0 |
| Overture POIs | 93.0 | 6.0 | 12.5 | 7.0 |
| Autocomplete | 82.5 | n/a | 42.5 | 32.5 |
| Near a point | 96.0 | 44.5 | 52.0 | 39.0 |
| Reverse | 99.5 | 100 | 98.5 | 98.0 |
Moving a Nominatim call to geolith
A typical Nominatim call:
// Before: public Nominatim
const res = await fetch(
'https://nominatim.openstreetmap.org/search?' +
new URLSearchParams({ q: 'Connaught Place, New Delhi', format: 'json', limit: '1' }),
{ headers: { 'User-Agent': 'my-app/1.0 (me@example.com)' } },
);
const [hit] = await res.json();
const lat = Number(hit.lat); // strings in Nominatim
const lon = Number(hit.lon);
const label = hit.display_name;
The same with geolith:
// After: geolith
const res = await fetch(
'https://api.geolith.app/v1/search?' +
new URLSearchParams({ text: 'Connaught Place, New Delhi', size: '1' }),
{ headers: { Authorization: 'Bearer YOUR_API_KEY' } },
);
const { features } = await res.json();
const [lon, lat] = features[0].geometry.coordinates; // numbers, GeoJSON order
const label = features[0].properties.label;
Parameter mapping:
| Nominatim | geolith |
|---|---|
/search?q= | /v1/search?text= |
limit | size (1 to 40) |
countrycodes=in,np | boundary.country=IN,NP |
accept-language=hi | lang=hi |
/reverse?lat=&lon= | /v1/reverse?point.lat=&point.lon= |
/lookup?osm_ids= | /v1/place?ids= (geolith gids from earlier results) |
display_name | properties.label |
lat, lon (strings) | geometry.coordinates = [lon, lat] (numbers) |
| no autocomplete | /v1/autocomplete?text= |
A reverse call moves the same way:
# Before
curl -A "my-app/1.0 (me@example.com)" \
"https://nominatim.openstreetmap.org/reverse?lat=18.922&lon=72.8346&format=json"
# After
curl "https://api.geolith.app/v1/reverse?point.lat=18.922&point.lon=72.8346&size=1" \
-H "Authorization: Bearer YOUR_API_KEY"
Before you switch
- Coverage. The hosted geolith API is worldwide: one planet index of 678,043,458 OpenStreetMap and Overture places.
- Attribution. Keep it:
© OpenStreetMap contributors (ODbL), Overture Maps Foundation. - Storage. You may store geolith results permanently, so a one-time migration of your cached Nominatim data is not required; re-geocode as rows change.
Get a free key (100,000 requests a month) or read the full comparison.
Sources
- Nominatim Usage Policy, OpenStreetMap Foundation (read 2026-10-22)
- geolith search benchmarks: engines, geolith (read 2026-10-22)