Express IP Geolocation Middleware

raw JSON →
1.0.4 verified Thu Apr 23 auth: no javascript abandoned

express-ip is an Express.js middleware designed to integrate IP geolocation capabilities into web applications. It leverages the `geoip-lite` library to enrich the incoming `req` object with `ipInfo`, containing location data such as country, region, and city. The current stable version, 1.0.4, was last published over six years ago, indicating that the package is no longer actively maintained. This middleware relies on `geoip-lite`, which is a native Node.js API using MaxMind's GeoLite data. While `geoip-lite` offers fast, synchronous, in-memory lookups after an initial data load, users must manually update its geolocation database, and the free GeoLite data it uses is less accurate and less comprehensive than commercial alternatives. This package provides a straightforward way to add basic IP-based geolocation to Express applications but comes with the caveats of its unmaintained status and the limitations of its underlying data source.

error TypeError: Cannot read properties of undefined (reading 'ipInfo')
cause The `express-ip` middleware (`expressip().getIpInfoMiddleware`) was not applied using `app.use()` before the route handler attempted to access `req.ipInfo`.
fix
Ensure app.use(expressip().getIpInfoMiddleware); is called before any routes that attempt to read req.ipInfo.
error `req.ip` returns `::1` or `127.0.0.1` when testing locally.
cause This is the expected loopback address for IPv6 (::1) or IPv4 (127.0.0.1) when making requests from localhost. It is not an issue with `express-ip` but a common point of confusion.
fix
This is normal behavior. To test with public IPs, deploy the application or use tools that simulate external requests. The express-ip middleware will still process the loopback IP and return information (though limited for loopback).
breaking The `express-ip` package is unmaintained, with its last publish date over six years ago. This means no new features, bug fixes, or security updates will be provided, making it potentially vulnerable or incompatible with newer Node.js/Express versions.
fix Consider migrating to a more actively maintained IP geolocation solution or fork the repository for custom maintenance.
gotcha The underlying `geoip-lite` library requires manual updates for its MaxMind GeoLite data. The free GeoLite data is also less accurate and less complete than commercial alternatives, potentially providing outdated or imprecise geolocation information.
fix Refer to the `geoip-lite` documentation for instructions on how to manually update its data files. For higher accuracy, consider integrating a commercial GeoIP service.
gotcha When running behind a proxy (e.g., Nginx, Cloudflare), `req.ip` (and thus `req.ipInfo`) might reflect the proxy's IP address or be `undefined` instead of the client's real IP. Express's 'trust proxy' setting must be configured correctly.
fix Set `app.set('trust proxy', true);` or configure it with a specific IP range for trusted proxies in your Express application to correctly derive the client's IP.
gotcha The `geoip-lite` library's GeoLite IPv6 database does not contain city or region information. For IPv6 addresses, only country-level data will be available. City, region, and postal code lookups are primarily supported for IPv4.
fix Be aware of this limitation when expecting detailed geolocation for IPv6 clients. More comprehensive IPv6 data typically requires commercial GeoIP databases.
npm install express-ip
yarn add express-ip
pnpm add express-ip

This example demonstrates how to integrate `express-ip` middleware and access IP geolocation data on the `req.ipInfo` object within an Express.js route.

const express = require('express');
const expressip = require('express-ip');
const app = express();
const PORT = process.env.PORT ?? 7000;

// Apply the express-ip middleware
app.use(expressip().getIpInfoMiddleware);

// Define a route that uses the IP info
app.get('/', function (req, res) {
    // req.ipInfo will contain geolocation data if available
    if (req.ipInfo) {
        res.send(`Your IP: ${req.ip}, Country: ${req.ipInfo.country}, City: ${req.ipInfo.city}`);
    } else {
        res.send(`Your IP: ${req.ip}, No geolocation info available.`);
    }
});

app.listen(PORT, function () {
    console.log(`Express started on http://localhost:${PORT}; press Ctrl-C to terminate.`);
});