Skip to content

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

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

Code

Before and after

Before: Nominatim
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
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.