# 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 %.

## Request mapping

| 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=…` |  |

## Response mapping

| 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` |  |

## Before and after

Before: Nominatim:

```js
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;
```

After: geolith:

```js
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;
```

## 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

### 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 %.

Get a free API key (100,000 requests a month): https://console.geolith.app/signup
