geoip-lite: a synchronous, in-memory GeoIP lookup for Node.js
Native NodeJS implementation of MaxMind's GeoIP API -- works in node 0.6.3 and above, ask me about other versions
At a glance
- What is it?
- geoip-lite converts MaxMind's GeoLite CSV files into its own binary format and reads them fully into RAM, so every lookup is a synchronous in-memory call. It is fast and simple, but it requires Node 24 and a MaxMind licence key to keep the data current.
- Who is it for?
- Adopt geoip-lite if you are on Node 24 or later, you want a synchronous in-memory lookup with no C bindings, and you can run the updatedb script with a MaxMind licence key on a machine with enough RAM. Do not adopt it if you need city or region data for IPv6, if your runtime is pinned below Node 24, or if you cannot schedule and monitor data refreshes.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 107 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem geoip-lite solves for Node services
MaxMind publishes GeoLite data files and C libraries that parse them. Most language bindings wrap that C API. The README describes the author's motivation plainly: building libgeoip on Mac OSX without MacPorts was painful, so the project took a different route. Instead of linking against MaxMind's C library, geoip-lite is a fully native JavaScript implementation. A converter script turns MaxMind's CSV files into an internal binary format, and the module reads that file to resolve an IP address to a country, region and city. The intended user is a Node developer who wants IP geolocation inside a request handler without a native build step and without an asynchronous round trip. The README states the scope reduction directly: it is not as fully featured as libgeoip bindings, and by reducing scope it is significantly faster at lookups. That trade is the whole design.
How the in-memory lookup and data flow work
The data path has two stages. First, a converter script reads MaxMind's CSV files and writes the project's own binary format, which the README notes is different from the binary format MaxMind ships. Second, at process startup the module performs blocking file IO to read and index that binary file into memory. The README says startup may take up to 200ms. After that, lookups never touch disk. The API is completely synchronous, with no callbacks: runtime calls are executed in memory. The README gives average figures of under 0.5 microseconds for an IPv4 lookup and about 1.3 microseconds for IPv6. A lookup returns an object with range, country, region, eu, timezone, city, ll, metro and area fields, or null when the address is not found. Both IPv4 and IPv6 are supported, but the README states that the GeoLite IPv6 database does not currently contain city or region information, so city, region and postal code lookups are IPv4 only. That is a data limitation from upstream, not a bug in the module.
Installing geoip-lite and running a first lookup
The package requires Node.js >= 24.0.0, per both the README requirements section and the engines field in package.json. Install it from npm:
npm install geoip-liteThe README warns that you must update the data files after installation, because the MaxMind licence does not allow the latest data to be distributed with the package. Updating needs a free licence key from MaxMind and a machine with enough RAM; the README says the update is known to fail on a Digital Ocean or AWS micro instance and that there are no plans to change this. Run the update from inside the installed package:
cd node_modules/geoip-lite && npm run-script updatedb license_key=YOUR_LICENSE_KEYA minimal lookup looks like the README synopsis. Pass a dotted quad, an IPv6 address without surrounding brackets, or a 32 bit unsigned integer:
var geoip = require('geoip-lite');
var ip = "207.97.227.239";
var geo = geoip.lookup(ip);
console.log(geo);For that address the README shows a result with country 'US', region 'TX', timezone 'America/Chicago', city 'San Antonio' and an ll pair. If the address is not in the database, lookup returns null, so the calling code has to handle that case rather than assuming an object.
Keeping the database current without restarting your server
Because the data is held in memory, a refresh after an update is a real operational concern. The project provides three routes. The updater itself has two aliases: npm run-script updatedb downloads only when checksums have changed, and updatedb-force downloads regardless. The package stores checksums of MaxMind data and by default only downloads when they differ. For a running server, you can call geoip.reloadDataSync() to reload synchronously, or geoip.reloadData(callback) to reload asynchronously after a scheduled update. There is also geoip.startWatchingDataUpdate(), which watches the data directory and refreshes the in-memory data when a file changes. The README does not document rollback if a freshly downloaded dataset is bad, and it does not describe a validation step between download and reload. On a long-running service that is the gap to plan around: keep the previous data files so you can restore them, and treat the watcher as something that reacts to whatever the updater wrote.
Where geoip-lite is the wrong tool
Three constraints are worth stating before you pick it. The first is memory. The README is explicit that geoip-lite stores all data in RAM in order to be fast, that the update requires a lot of RAM, and that it is known to fail on small cloud instances. If your deployment target is a 512MB container, this is the wrong package. The second is IPv6 depth. Country-level answers work for IPv6, but city, region and postal code do not, because the upstream GeoLite IPv6 database lacks that information. If your product needs city accuracy for IPv6 clients, look elsewhere. The third is the runtime floor. Node.js >= 24.0.0 is a hard requirement in package.json, so an application pinned to an older LTS cannot use this release at all. Finally, the accuracy radius field (area) is an approximation around a latitude and longitude, and the README presents it as such; treating the returned city as an exact location misreads what the data provides.
geoip-lite compared with maxmind/geoip2-node and hosted APIs
The nearest alternative is MaxMind's own Node client, commonly installed as maxmind/geoip2-node, which reads MaxMind's official MMDB format rather than a converted file. The practical difference is where the conversion happens: geoip-lite runs its own converter over CSV at update time and reads a format of its own design, while an MMDB reader consumes MaxMind's published binary directly, so you can drop in databases MaxMind ships without a conversion step. Hosted services such as ipinfo are a different trade again: no local database, no RAM cost, no update script, but a network call per lookup and an external dependency in the request path. geoip-lite's pitch is the opposite of that: everything local and synchronous, at the cost of memory and a manual update routine. The README's own framing supports this reading, describing the package as not as fully featured as libgeoip bindings but faster at lookups because of the reduced scope.
Licence, maintenance and the cost of staying current
The repository's package.json declares Apache-2.0, while the repository metadata reports the licence as NOASSERTION; treat the package.json field as the project's stated position and confirm the terms yourself if you redistribute. The data is separate from the code. The README states that this product includes GeoLite data created by MaxMind, and that the MaxMind licence does not allow the latest data files to be distributed with the package. That is why the post-install update step exists and why it needs your own licence key. The MaxMind rate limits downloads on their servers, per the README, so the checksum-based default in updatedb is doing real work: frequent forced updates will hit limits. On maintenance, the last push was on 2026-06-17, with v2.0.3 released the same day, so the project is being touched, but the upgrade cost is not only the npm version. The Node >= 24.0.0 floor means a major runtime upgrade may be a prerequisite, and every data refresh is an operational task with a RAM requirement attached.
Editorial conclusion
Adopt geoip-lite if you are on Node 24 or later, you want a synchronous in-memory lookup with no C bindings, and you can run the updatedb script with a MaxMind licence key on a machine with enough RAM. Do not adopt it if you need city or region data for IPv6, if your runtime is pinned below Node 24, or if you cannot schedule and monitor data refreshes. Before committing, verify that the bundled data files are current for your use case by running the updater, and check that your host has enough memory to hold the converted database.
Frequently asked questions
What is geoip-lite used for?
It maps an IP address to geographic data inside a Node.js process. The README's synopsis shows a lookup returning country, region, timezone, city and latitude/longitude for a given address.
Is geoip-lite free to use?
The package is published under Apache-2.0 according to package.json, and the data comes from MaxMind's GeoLite product. The README states that the MaxMind licence does not allow the latest data files to be distributed with the package, which is why you must run the updater with your own licence key.
Is GeoIP legal to use with geoip-lite?
The README does not address legal questions. It only states the licence constraint on redistributing the latest MaxMind data files and requires you to obtain a licence key from MaxMind to update them.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/geoip-lite-node-geoip)