Skip to main content

Mailwoman

TypeScript-first address parser + geocoder. Runs in Node and the browser.

Neural address parser

ONNX-runtime sequence classifier over a SentencePiece tokenizer. Emits BIO-labeled components (country / region / locality / postcode / street / venue / …). Trained on a corpus stitched from TIGER, NAD, BAN, OpenAddresses + curated rows. Ships per-locale weight bundles as separate npm packages.

WOF-backed resolver

Parsed components are resolved to Who's On First place IDs + WGS-84 coordinates via FTS5 + R*Tree over pre-indexed SQLite shards. Pure node:sqlite, no SpatiaLite, no native build deps. Multi-shard ATTACH routes postcode queries to the postalcode shard automatically.

Pure-TypeScript runtime

Mailwoman runs on Node 22+ today; the resolver + classifier are being ported to sqlite-wasm + onnxruntime-web so the same pipeline can run client-side without an API server.

Quick start

Library

npm install mailwoman @mailwoman/neural @mailwoman/neural-weights-en-us
import { NeuralAddressClassifier } from "@mailwoman/neural"

const neural = await NeuralAddressClassifier.loadFromWeights({ locale: "en-US" })
const components = await neural.parseJson("1600 Pennsylvania Ave NW, Washington DC")
// → { house_number: "1600", street: "Pennsylvania Ave NW", locality: "Washington", region: "DC" }

CLI

# parse + resolve in one shot
MAILWOMAN_WOF_DB=/path/to/wof.db npx mailwoman parse \
--neural --resolve --format xml \
"Springfield, Illinois"
<address raw="Springfield, Illinois">
<region src="resolver:region:85688697" lat="40.27" lon="-89.19">Illinois
<locality src="resolver:locality:85940429"
lat="39.80" lon="-89.65"
place="wof:85940429">Springfield</locality>
</region>
</address>