Migrate · from Nominatim public API
Migrate from the Nominatim public API to geolith
The public Nominatim server's usage policy allows at most 1 request per second and forbids autocomplete (checked 22 Oct 2026). To move, replace /search?q=…&format=jsonv2 with https://api.geolith.app/v1/search?text= and add your key. On the India benchmark (20 Oct 2026) geolith put the right address first 95.0 % of the time against 50.5 % for Nominatim, and supports autocomplete (82.5 %). Reverse is close: 99.5 % against 100 %.
Requests
Request mapping
GET /search?q=…&format=jsonv2
→ GET /v1/search?text=…
GET /reverse?lat=…&lon=…&format=jsonv2
→ GET /v1/reverse?point.lat=…&point.lon=…
/search?street=…&city=…&postalcode=…
→ GET /v1/search/structured?address=…&locality=…&postalcode=…
GET /lookup?osm_ids=…
→ GET /v1/place?ids=…
geolith gids, not OSM ids.
countrycodes=in
→ boundary.country=IN
limit=5
→ size=5
accept-language=hi
→ lang=hi
Self-hosted server; hosted API planned.
viewbox=…
→ focus.point.lat=…&focus.point.lon=…
A point bias, not a box.
polygon_geojson=1 (on /lookup)
→ /v1/place?ids=…&geometry=true
Countries, regions, counties and area venues.
User-Agent identifying your app
→ api_key=… or Authorization: Bearer …
No autocomplete on the public server
→ GET /v1/autocomplete?text=…
| Nominatim public API | geolith | Note |
|---|---|---|
| GET /search?q=…&format=jsonv2 | GET /v1/search?text=… | |
| GET /reverse?lat=…&lon=…&format=jsonv2 | GET /v1/reverse?point.lat=…&point.lon=… | |
| /search?street=…&city=…&postalcode=… | GET /v1/search/structured?address=…&locality=…&postalcode=… | |
| GET /lookup?osm_ids=… | GET /v1/place?ids=… | geolith gids, not OSM ids. |
| countrycodes=in | boundary.country=IN | |
| limit=5 | size=5 | |
| accept-language=hi | lang=hi | Self-hosted server; hosted API planned. |
| viewbox=… | focus.point.lat=…&focus.point.lon=… | A point bias, not a box. |
| polygon_geojson=1 (on /lookup) | /v1/place?ids=…&geometry=true | Countries, regions, counties and area venues. |
| User-Agent identifying your app | api_key=… or Authorization: Bearer … | |
| No autocomplete on the public server | GET /v1/autocomplete?text=… |
Responses
Response mapping
JSON array [ … ]
→ GeoJSON FeatureCollection, features[]
display_name
→ properties.label
lat, lon (strings)
→ geometry.coordinates [lon, lat] (numbers)
place_id / osm_type + osm_id
→ properties.gid
category, type
→ properties.layer, properties.category[]
importance
→ properties.importance (0 to 1)
boundingbox [s, n, w, e] (strings)
→ bbox [w, s, e, n] (numbers)
address.postcode / city / state / country_code
→ properties.postalcode / locality / region / country_code
| Nominatim public API | geolith | Note |
|---|---|---|
| JSON array [ … ] | GeoJSON FeatureCollection, features[] | |
| display_name | properties.label | |
| lat, lon (strings) | geometry.coordinates [lon, lat] (numbers) | |
| place_id / osm_type + osm_id | properties.gid | |
| category, type | properties.layer, properties.category[] | |
| importance | properties.importance (0 to 1) | |
| boundingbox [s, n, w, e] (strings) | bbox [w, s, e, n] (numbers) | |
| address.postcode / city / state / country_code | properties.postalcode / locality / region / country_code |
Code
Before and after
const url = new URL('https://nominatim.openstreetmap.org/search');
url.searchParams.set('q', 'eiffel tower');
url.searchParams.set('format', 'jsonv2');
url.searchParams.set('countrycodes', 'fr');
url.searchParams.set('limit', '1');
const [hit] = await (await fetch(url, { headers: { 'User-Agent': 'my-app/1.0' } })).json();
return hit ? { label: hit.display_name, lat: Number(hit.lat), lon: Number(hit.lon) } : null;const url = new URL('https://api.geolith.app/v1/search');
url.searchParams.set('text', 'eiffel tower');
url.searchParams.set('boundary.country', 'FR');
url.searchParams.set('size', '1');
const res = await fetch(url, { headers: { Authorization: `Bearer ${GEOLITH_KEY}` } });
const [f] = (await res.json()).features;
return f ? { label: f.properties.label, lat: f.geometry.coordinates[1], lon: f.geometry.coordinates[0] } : null;Detail
What changes
Both serve OpenStreetMap data under the ODbL. geolith adds Overture Maps places, which is why it finds 93.0 % of Overture POIs first against 6.0 % for Nominatim.
- Coordinates are numbers and longitude comes first.
- Attribution grows to: © OpenStreetMap contributors (ODbL), Overture Maps Foundation.
- To stay on your own servers, self-host geolith from one .glx file instead of a 45 GB Postgres import (India benchmark).
Questions
Migrating from Nominatim public API: questions
- Why leave the public Nominatim server?
- Its usage policy allows at most 1 request per second per application and does not allow autocomplete. A keyed API with a monthly quota removes both limits.
- Is reverse geocoding as good as Nominatim?
- Close. On the India reverse benchmark Nominatim scored 100 % and geolith 99.5 %.
Geocode your first address in a minute.
100,000 requests a month free. Commercial use with attribution. No card.