get-client-ip
v4.0.0
Published
π A Lightweight Utility for Extracting the Real Client IP Address from Incoming HTTP Requests
Readme
Highlights β¨
- Checks 14 sources (headers + socket) in priority order
- Handles comma-separated, array, and RFC 7239
Forwardedformats - Framework compatibility β supports Express v5/v4 and NestJS (Express adapter)
- Flexible usage β works standalone or as middleware, and auto-populates typed
req.clientIpandreq.clientIps - Zero config β validates IPs using Node.js
net.isIP()
Installation π¦
Requires Node.js >= 18.
npm install get-client-ip
# or
pnpm add get-client-ipQuick Start π
import express from "express";
import { getClientIp } from "get-client-ip";
const app = express();
// Middleware β auto-populates req.clientIp and req.clientIps
app.use(getClientIp);
app.get("/me", (req, res) => {
res.json({ ip: req.clientIp, ips: req.clientIps });
});
// Or standalone β call directly in a specific route
app.get("/ip", (req, res) => {
const ip = getClientIp(req);
res.json({ ip });
});
app.listen(3000);API Reference π
getClientIp(req, res?, next?): string | undefined
Extracts the client's IP address from an incoming request. Works both as a standalone function and as Express middleware. Returns string | undefined.
Side effects: Sets req.clientIp and req.clientIps on the request object when a valid IP is found. Throws if req is undefined.
TypeScript Augmentation
The package augments the Express Request type automatically:
// These properties are available after calling getClientIp
req.clientIp; // string | undefined β first valid IP
req.clientIps; // [string, ...string[]] | undefined β all valid IPs (non-empty array)No manual type declarations are needed.
Header Priority π
Sources are checked in the following order. The first valid IP found is returned.
| Priority | Source | Description |
| -------- | -------------------------- | -------------------------------------- |
| 1 | req.ip | Express trust proxy setting |
| 2 | Forwarded | RFC 7239 (parsed for for= directive) |
| 3 | CF-Connecting-IP | Cloudflare |
| 4 | True-Client-IP | Akamai / Cloudflare Enterprise |
| 5 | Fastly-Client-IP | Fastly CDN |
| 6 | X-Appengine-User-IP | Google App Engine |
| 7 | CF-Pseudo-IPv4 | Cloudflare pseudo-IPv4 |
| 8 | X-Client-IP | General proxy header |
| 9 | X-Forwarded-For | De facto standard proxy header |
| 10 | Forwarded-For | Variant of X-Forwarded-For |
| 11 | X-Forwarded | Microsoft variant |
| 12 | X-Real-IP | Nginx proxy header |
| 13 | X-Cluster-Client-IP | Rackspace / Riverbed |
| 14 | req.socket.remoteAddress | Direct connection fallback |
NestJS π§©
import { Controller, Get, Req } from "@nestjs/common";
import type { Request } from "express";
import { getClientIp } from "get-client-ip";
@Controller()
export class AppController {
@Get("ip")
getIp(@Req() req: Request) {
const ip = getClientIp(req);
return { ip };
}
}Security π‘οΈ
Header trust warning: When
req.ipis not populated, forwarding headers are used only whenreq.socket.remoteAddressappears to be from a local/private proxy range. Public socket peers skip header fallback to reduce spoofing risk.
In production behind a reverse proxy:
- Configure Express's
trust proxysetting so thatreq.ipis correctly populated - This ensures the function returns
req.ipfirst and avoids fallback ambiguity - Without
trust proxy, forwarding headers may still be ignored when the peer is public
CGNAT addresses: Addresses in the
100.64.0.0/10range (RFC 6598) are treated as public, not trusted proxy addresses. Headers are not trusted when the socket peer is a CGNAT address. If your application is behind a load balancer (e.g., AWS ALB), configure Express'strust proxysetting soreq.ipis populated correctly.
Credits π
Inspired by Petar Bojinov's work on client IP detection.
Contributions π€
- Open an issue or feature request
- Submit a PR to improve the package
- Star the repo if you find it useful
Crafted carefully by WolfieLeader
This project is licensed under the MIT License.
