Offline geocoding in Node.js

A Node.js service that geocodes addresses usually calls an API for each one. The npm package reads a country file in the same process instead.

Geocode addresses JavaScript

What you have

npm install gridpin (prebuilt for macOS, Linux and Windows) and a country file. A script with the three calls:

geocode.jsfile
const { Geocoder } = require('gridpin');

const g = new Geocoder('usa.bin');   // or: await sheets.fetch('us'), which downloads and checks it once
const [best] = g.geocode('1600 Pennsylvania Ave NW, Washington, DC 20500', { k: 1 });
console.log(best.precision, best.street, best.housenumber, best.lat, best.lon);

const rows = g.geocodeMany(['233 S Wacker Dr, Chicago, IL 60606', null, 'Nowhere Street 99999, Atlantis']);
console.log(rows.map((hits) => (hits.length ? hits[0].match_level : 'no answer')));

const [near] = g.reverse(41.8787, -87.6359);
console.log(near.street, near.housenumber, Math.round(near.distance_m), 'm');
g.close();

Steps

1. Run it:

terminalCLI
$ node geocode.js
house PENNSYLVANIA Avenue Northwest 1600 38.8976751 -77.036547
[ 'PointAddress', 'no answer', 'no answer' ]
South WACKER Drive 231 3 m

What you get

geocode returns a list of answers, best first, each with precision, match_level, the street, number, postcode, town and point. geocodeMany keeps the input order and gives an empty list for an empty row or an address that is not found. reverse gives the nearest address and its distance.

Why it works

The package is the engine's C interface wrapped for Node-API: the file is memory-mapped once, and each call is a lookup in it, with no network and nothing kept between calls.

Limits

  • geocodeMany runs on the calling thread: put big batches in a worker thread.
  • One country per Geocoder; open one per country you need.
  • sheets.fetch('us') downloads the file once and checks it; GRIDPIN_OFFLINE=1 forbids downloads.

The function: Node.js. In the browser, with no install: address autocomplete.