@mailwoman/nominatim
v10.3.0
Published
Nominatim drop-in — a Nominatim-compatible HTTP geocoding API (search / reverse / lookup / status) over the Mailwoman engine. Run it with `npx @mailwoman/nominatim serve`.
Readme
@mailwoman/nominatim
A Nominatim-compatible HTTP geocoding API over the Mailwoman engine. Point an existing Nominatim client at it and forward + reverse geocoding work — no PostgreSQL, no osm2pgsql import.
# One-time data fetch (worldwide candidate gazetteer, population-first ranking, ~1.65 GB):
MAILWOMAN_DATA_ROOT="${MAILWOMAN_DATA_ROOT:-/tmp/mailwoman-data}" npx mailwoman data pull candidate
MAILWOMAN_DATA_ROOT="${MAILWOMAN_DATA_ROOT:-/tmp/mailwoman-data}" \
npx @mailwoman/nominatim serve --port 8080
# The pulled candidate.db is auto-detected at $MAILWOMAN_DATA_ROOT/db/wof/candidate.db — no export needed.
# Or point at your own: --candidate-db <path> / $MAILWOMAN_CANDIDATE_DBfrom geopy.geocoders import Nominatim
geo = Nominatim(domain="localhost:8080", scheme="http")
geo.geocode("1600 Pennsylvania Ave NW, Washington DC", addressdetails=True)
geo.reverse((38.8977, -77.0365))Endpoints
| Endpoint | Nominatim interface | Status |
| --------------- | ------------------------------------------------------------- | ------- |
| / | HTML landing page (endpoint index + example queries) | ✓ |
| /search | free-text q + structured forward geocoding | ✓ |
| /reverse | lat/lon → nearest address (WofReverseGeocoder PIP) | ✓ |
| /status | health + data version | ✓ |
| /lookup | resolve known place ids | planned |
| /openapi.json | emitted OpenAPI 3.1 document for search/reverse/lookup/status | ✓ |
Library use
The package is engine-agnostic — embed it in your own server:
import { serveNode } from "@mailwoman/api-kit"
import { createNominatimApp, type NominatimEngine } from "@mailwoman/nominatim"
const engine: NominatimEngine = {/* search, reverse, lookup, status — backed by your Mailwoman pipeline */}
const app = createNominatimApp(engine)
serveNode({ fetch: app.fetch, port: 8080, hostname: "0.0.0.0" })CORS
Browser-embedded geocoder clients call this cross-origin, so the server sends permissive CORS by default — Access-Control-Allow-Origin: * and a 204 answer to preflight OPTIONS. Behind a reverse proxy that already sets the headers, turn it off with --no-cors (or createNominatimApp(engine, { cors: false })).
Annotations
The API returns an OpenCage-style annotations block — coordinate formats (DMS, MGRS, geohash,
Maidenhead, Mercator), qibla direction, sun times, country flag, calling code, and currency, plus the IANA
timezone, UN/LOCODE, and EU NUTS codes when their data bundles are present. Plain Nominatim returns none
of these.
Data freshness
You cannot tell how stale a geocoder's data is from its answers, so /status reports it. data_updated is the
Nominatim-compatible field — the newest build date across the databases this process opened — and the native
mailwoman block names each one:
{
"status": 0,
"message": "OK",
"data_updated": "2026-08-25T17:21:58.254Z",
"mailwoman": {
"artifacts": [
{
"name": "gazetteer",
"path": "…/wof/candidate.db",
"manifest": "present",
"version": "candidate@2026-08-25",
"built": "2026-08-25T17:21:58.254Z",
"sources": [
"admin-global-priority@2026-08-25",
"admin=… postcode-extracts=23 locality-extracts=2 importance=yes",
],
},
],
},
}Every date comes out of the artifact itself — the layer_manifest row its builder wrote before sealing it — never
from a file's timestamp or a record kept alongside. An artifact built without a manifest, and
says so ("manifest": "absent") rather than being left out; when none of them carries one, data_updated is omitted
instead of guessed. A Nominatim client ignores the mailwoman key.
Status
Shipped. /search and /reverse resolve over the live engine and return the enriched block; /lookup
is not yet implemented (returns 501). addressdetails goes down to the house number and road when the
query carries them — 1600 Pennsylvania Avenue NW, Washington, DC 20500 resolves to the rooftop
(38.897, -77.037) with house_number, road, city, state, postcode, and country_code.
For autocomplete / type-ahead, see the companion @mailwoman/photon.
