get-client-ip

中文文档
5.0.0发布于 2026/11/04MITTypeScriptESM + CJS零依赖构建来源已验证

📍 A Lightweight Utility for Extracting the Real Client IP Address from Incoming HTTP Requests

原始使用文档
文档目录15 节
  1. Highlights ✨
  2. Installation 📦
  3. Quick Start 🚀
  4. API Reference 📖
  5. getClientIp(req, options?): string | undefined
  6. getClientIpMiddleware(options?)
  7. Options
  8. req.clientIp and req.clientIps
  9. How the IP Is Resolved 📋
  10. Deployment Recipes 🧭
  11. NestJS 🧩
  12. Security 🛡️
  13. Breaking Changes in v5 ⚠️
  14. Credits 🙏
  15. Contributions 🤝
banner

get-client-ip

Extract the real client IP from HTTP requests, safely behind proxies.
Works standalone or as Express/NestJS middleware.

License npm version npm downloads stars

Highlights ✨

  • Spoof-resistant — walks X-Forwarded-For from the right and stops at the first untrusted hop, like Express trust proxy
  • Works without a framework — raw node:http, Koa ctx.req, Next.js pages API, Express v4/v5, Fastify, NestJS
  • Opt-in vendor headers — cf-connecting-ip, true-client-ip, and similar are read only when you list them
  • RFC 7239 Forwarded — quoted strings, IPv6, ports, unknown, and obfuscated identifiers
  • CIDR trust lists — IPv4 and IPv6, compared as parsed addresses
  • Normalized output — ::ffff:1.2.3.4 becomes 1.2.3.4; IPv6 is lowercase and compressed

Installation 📦

Requires Node.js >= 22.12.

npm install get-client-ip
# or
pnpm add get-client-ip

Quick Start 🚀

import express from "express";
import { getClientIp } from "get-client-ip";

const app = express();

// Middleware — 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 route
app.get("/ip", (req, res) => {
  res.json({ ip: getClientIp(req) });
});

app.listen(3000);

Without a framework:

import http from "node:http";
import { getClientIp } from "get-client-ip";

http.createServer((req, res) => res.end(getClientIp(req))).listen(3000);

API Reference 📖

getClientIp(req, options?): string | undefined

Returns the client IP, or undefined when no address is known. Also sets req.clientIp and req.clientIps. Throws if req is missing or options are invalid.

Passing it straight to app.use(getClientIp) runs it as middleware with default options.

getClientIpMiddleware(options?)

Returns (req, res, next) middleware that uses options. It validates options once, at creation.

import { DEFAULT_TRUSTED_PROXIES, getClientIpMiddleware } from "get-client-ip";

app.use(getClientIpMiddleware({ trustedProxies: [...DEFAULT_TRUSTED_PROXIES, "203.0.113.0/24"] }));

Options

OptionTypeDefaultDescription
trustedProxiesstring[]DEFAULT_TRUSTED_PROXIESIPs or CIDRs of proxies whose forwarding headers you trust. [] trusts none.
forwardedHeader"x-forwarded-for" | "forwarded""x-forwarded-for"The header your proxies append to. The other one is ignored.
trustedHeadersstring[][]Single-IP headers your edge always overwrites, e.g. ["cf-connecting-ip"]. Checked in order.

DEFAULT_TRUSTED_PROXIES is 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, ::1/128, fc00::/7, and fe80::/10. CGNAT (100.64.0.0/10) is not trusted.

req.clientIp and req.clientIps

req.clientIp; // string | undefined — the client IP
req.clientIps; // [string, ...string[]] | undefined — the client, then each trusted hop toward your server

The package augments the Express Request type, so no manual declarations are needed.

How the IP Is Resolved 📋

  1. trustedHeaders — the first valid IP from a listed header, only when the socket peer is a trusted proxy.
  2. req.ip — when it is a valid IP outside trustedProxies. Express and Fastify set it from their own trust settings.
    • If req.ip is itself a trusted proxy (e.g. Express without trust proxy behind nginx), it is the proxy, not the client. The chain is walked as in step 4. req.ip is kept only when no untrusted hop is found.
  3. Socket address — when the socket peer is not a trusted proxy, headers are ignored.
  4. Forwarding chain — read X-Forwarded-For (or Forwarded) from the right. Skip each trusted proxy. Return the first untrusted address.
    • If every hop is trusted, return the leftmost one.
    • An unknown, obfuscated (_hidden), or invalid hop stops the walk. The nearest trusted hop is returned.

Example: nginx on 10.0.0.5 appends the peer it saw. A client sends X-Forwarded-For: 6.6.6.6, so your app receives 6.6.6.6, 203.0.113.9. The result is 203.0.113.9, not the spoofed 6.6.6.6.

Deployment Recipes 🧭

SetupConfiguration
nginx, HAProxy, or a load balancer on a private IPDefaults
Express behind a proxyDefaults work; setting Express trust proxy also works
Cloudflare in front of a private load balancer{ trustedHeaders: ["cf-connecting-ip"] }
Proxy that writes RFC 7239 Forwarded{ forwardedHeader: "forwarded" }
Proxy on a public IP{ trustedProxies: [...DEFAULT_TRUSTED_PROXIES, "<proxy CIDR>"] }
Directly on the internet{ trustedProxies: [] }

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) {
    return { ip: getClientIp(req) };
  }
}

Security 🛡️

  • List only headers your edge overwrites. A trustedHeaders entry is client-controlled unless every request passes through that edge. Make your origin reachable only through it.
  • Pick the header your proxy writes. If your proxy appends X-Forwarded-For, a client-sent Forwarded header is ignored, and vice versa.
  • Clients inside a trusted range can spoof. A host on a trusted network can send any X-Forwarded-For. Narrow trustedProxies to your proxies' addresses when that matters.
  • An untrusted req.ip is trusted as-is. If your framework's proxy trust is looser than trustedProxies, req.ip can come from a client-supplied header.

Breaking Changes in v5 ⚠️

  • Requires Node.js >= 22.12.
  • X-Forwarded-For is read from the right. v4 returned the leftmost entry, which any client can set. Now the first untrusted hop from the right is returned.
  • Vendor headers need opt-in. cf-connecting-ip, true-client-ip, fastly-client-ip, x-appengine-user-ip, cf-pseudo-ipv4, x-client-ip, x-real-ip, x-cluster-client-ip, forwarded-for, and x-forwarded are ignored unless listed in trustedHeaders.
  • A trusted req.ip no longer wins. When req.ip is inside trustedProxies (Express without trust proxy behind a private or loopback proxy), the forwarding chain is walked. v4 returned the proxy's address. Pass trustedProxies: [] to keep the v4 result.
  • Forwarded needs opt-in. Set forwardedHeader: "forwarded". X-Forwarded-For is then ignored.
  • The second argument is now options. getClientIp(req, res) no longer means middleware; use getClientIp(req, res, next), app.use(getClientIp), or getClientIpMiddleware().
  • req.clientIps changed meaning. It is the client followed by the trusted hops toward your server, ending with the socket peer. v4 listed every header entry.
  • Output is normalized. IPv4-mapped IPv6 (::ffff:1.2.3.4) becomes IPv4, including req.ip. IPv6 is lowercase and compressed, and its zone ID is dropped (fe80::1%eth0 becomes fe80::1).
  • A quoted X-Forwarded-For entry is an invalid hop. v4 stripped the quotes from "203.0.113.9". Proxies never quote it, so a quoted entry is client-written and stops the walk.
  • The middleware always sets req.clientIp. It is undefined when no address resolves. v4 left the property untouched.
  • IPv6 trust uses real CIDR matching. fc::1 is no longer trusted (it is not in fc00::/7). fe80::/10 now covers fe80::–febf::.
  • 0.0.0.0 and :: are invalid hops.

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.

版本与发布记录

get-client-ip 共发布 30 个版本,首次发布于 2022/10/12;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
5.0.0latest2026/11/04今天
4.0.02026/02/278 个月前
4.0.0-beta.2beta2026/02/218 个月前
4.0.0-beta.12026/02/218 个月前
4.0.0-beta.02026/02/158 个月前
3.0.42025/10/081.1 年前

关于 get-client-ip 的常见问题

get-client-ip 是什么?

📍从传入HTTP请求中提取真实客户端IP地址的轻量级实用程序

如何安装 get-client-ip?

在项目目录运行 npm install get-client-ip,或使用 pnpm add / yarn add / bun add。

get-client-ip 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

get-client-ip 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

get-client-ip 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

get-client-ip 可以商用吗?

get-client-ip 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

get-client-ip 还在维护吗?

最新版本 5.0.0 发布于 2026/11/04(今天);至今共发布 30 个版本,其中过去 12 个月发布了 5 个;首次发布于 2022/10/12。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。