Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsIn a plain Node.js HTTP server, read req.socket.remoteAddress. It gives you the address of the network peer connected directly to your server. If a reverse proxy, load balancer, or CDN sits in front of Node.js, that peer is usually the intermediary—not the visitor. In Express, use req.ip with a trust proxy policy that matches your actual deployment. Never treat a forwarded header as trustworthy just because it contains an IP address.
First decide what address you need
“Client IP” can mean either the direct network peer or an address that a proxy says originated the request. Those are different values. A Node server connected directly to a browser sees the browser’s network address as its peer; a server behind a proxy sees the proxy’s address unless the application is configured to use trusted forwarding information.
- For connection diagnostics: use the direct peer from
req.socket.remoteAddress. - For an application behind proxies: derive the visitor address from forwarding metadata only after deciding which proxies are trusted and how they handle incoming headers.
- For access control or rate limiting: use only a value validated through that trusted proxy path. A header supplied or influenced by the requester is not an authentication signal.
An IP address identifies a network endpoint as observed by infrastructure; it does not reliably identify a person or device. Shared networks, VPNs, carrier networks, and changing addresses can all affect what it represents.
Six ways to get an address in Node.js
1. Plain Node.js: read the connected peer
For a built-in HTTP server without a framework, req.socket.remoteAddress is the direct peer address documented by Node.js HTTP documentation. This is the right starting point when Node.js is directly exposed or when you explicitly need the proxy’s address.
#1 Best Overall
const http = require('node:http');
const server = http.createServer((req, res) => {
const peerAddress = req.socket.remoteAddress;
res.writeHead(200, { 'content-type': 'text/plain' });
res.end(`Connected peer: ${peerAddress ?? 'unavailable'}n`);
});
server.listen(3000, () => {
console.log('Listening on http://localhost:3000');
});
The socket may report an IPv4-mapped IPv6 form such as ::ffff:192.0.2.10. That is a representation detail, not proof of a different visitor. If you normalize addresses for storage or comparison, use a vetted IP parsing library and define how IPv4-mapped IPv6 values should be handled; do not strip text based on assumptions.
2. Express with no trusted proxy
In Express, req.ip is the framework-level convenience property. With the default trust proxy setting disabled, Express derives it from the direct socket peer. Use it when the application is directly reachable and no trusted proxy is providing visitor metadata.
const express = require('express');
const app = express();
app.get('/whoami', (req, res) => {
res.json({ ip: req.ip });
});
app.listen(3000);
Do not read X-Forwarded-For independently and assume it improves this result. Without a trustworthy proxy boundary, a requester can send a value of their choosing.
3. Express behind a known proxy topology
When Express is behind a proxy, configure trust proxy to match the actual network path. Express then evaluates the socket address and forwarded chain, stopping at the first untrusted address; req.ip is the derived address and req.ips exposes the address chain. The framework’s guidance is in its behind-proxies guide.
Prefer trusting known proxy addresses or subnets, or provide a trust function when your infrastructure requires it. Illustrative configuration for a deployment whose only proxy is at a known private address:
Rank #2
const express = require('express');
const app = express();
// Replace this example address with the real, verified proxy address.
app.set('trust proxy', '10.0.0.12');
app.get('/whoami', (req, res) => {
res.json({ ip: req.ip, chain: req.ips });
});
Do not copy the example address as a production setting. Obtain the addresses or subnet ranges from the operator of your proxy or hosting environment and ensure clients cannot connect to the application while bypassing that proxy.
A hop count is safe only if every possible route to the application has the same number of proxy hops. For example, app.set('trust proxy', 1) means trust the nearest proxy hop, not “trust one particular provider.” If some routes have fewer hops than others, a requester may be able to supply a value that Express accepts. Likewise, app.set('trust proxy', true) trusts forwarded information broadly; use it only when the last trusted proxy reliably overwrites or removes relevant incoming forwarding headers.
4. Parse X-Forwarded-For in a custom Node handler
X-Forwarded-For (XFF) commonly carries a comma-separated list of addresses added as a request passes through proxies. The leftmost value is not automatically authentic: it may have been supplied by the requester. Multiple XFF header fields can also occur, so code should account for the complete field set rather than assume infrastructure always joins them. See MDN’s X-Forwarded-For reference.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →If you own the proxy chain, first establish whether each proxy appends to, overwrites, or removes incoming XFF. For security decisions, start at the server-side end of the chain and walk backward through addresses introduced by proxies you trust; the first address outside that trusted chain is the nearest untrusted peer. That address may itself be an intermediate proxy, not the end-user device.
This deliberately incomplete illustration shows why a header alone is insufficient. It is not a secure client-IP resolver: it does not validate proxy addresses or implement a trust policy.
Rank #3
const xff = req.headers['x-forwarded-for'];
const displayedValues = Array.isArray(xff)
? xff
: typeof xff === 'string'
? xff.split(',')
: [];
// Display or log for diagnosis only; do not use this as trusted identity.
console.log(displayedValues.map(value => value.trim()));
For a production application, use Express’s proxy-aware behavior or implement a parser and trust-chain algorithm based on the documented topology. Do not select the first element as a universal shortcut.
5. Parse the standardized Forwarded header
The HTTP Forwarded header is a separate standard, not a comma-separated alias for XFF. It has structured parameters and quoting rules, and IPv6 values are represented differently. Use a parser that understands its grammar rather than splitting the field on commas or semicolons. As with XFF, the header is useful only when the infrastructure path that supplies it is trusted. See MDN’s Forwarded reference.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
6. Use a trusted provider-specific header
If your origin accepts traffic only through Cloudflare, Cloudflare documents CF-Connecting-IP as a single visitor-address value. Its HTTP-header documentation recommends CF-Connecting-IP or True-Client-IP when a consistently single-address value is needed, rather than depending on a potentially multi-address XFF chain. True-Client-IP must be enabled in the Cloudflare setup. Cloudflare’s header behavior is described in its HTTP headers reference and True-Client-IP documentation.
Example of reading a provider header for display, not a complete security policy:
const providerAddress = req.headers['cf-connecting-ip'];
// Only meaningful as visitor metadata when the request really came
// through your trusted Cloudflare path and the origin is protected.
console.log(providerAddress ?? 'header unavailable');
Cloudflare documents that it adds CF-Connecting-IP on traffic from its edge to the origin. It may append to an existing XFF chain; for a simple request with no existing XFF, XFF matches CF-Connecting-IP. These headers are not trustworthy if a client can bypass Cloudflare and reach the origin with a forged header. Restrict the origin path and configure the provider and application together.
Rank #4
Which approach fits your deployment?
| Approach | Works best when | What the value means | Security condition |
|---|---|---|---|
req.socket.remoteAddress |
Plain Node.js; direct connection or need to identify the peer | Direct TCP peer | Accurate for the peer, but behind a proxy that peer is the proxy |
Express req.ip, default trust setting |
Express app directly exposed without trusted forwarding metadata | Socket peer | Do not use forwarded headers as visitor identity |
Express req.ip with proxy trust |
Known, controlled proxy topology | Address selected from the trusted proxy chain | Trust addresses or topology accurately; prevent bypass paths |
| Custom XFF parsing | Custom Node handler with known proxy behavior | Claimed chain of addresses | Validate the chain from the trusted server-side end |
Forwarded parsing |
Infrastructure uses the standardized header | Structured forwarded parameters | Use a grammar-aware parser and trust the supplying proxies |
| Provider-specific header | Origin is reliably reached through that provider | Provider-reported client address | Protect origin from bypass and forged header values |
Configure proxy trust without creating a spoofing path
- Map the real route. Identify every public entry point, load balancer, CDN, and reverse proxy between the requester and Node.js, including alternate paths.
- Confirm header behavior. Ask which component removes, overwrites, or appends XFF and other forwarding headers. Do not infer this from a sample request alone.
- Restrict direct access. Where possible, make the application reachable only from the trusted proxy or provider. If a client can bypass it, client-supplied forwarding values remain a risk.
- Set the narrowest Express trust policy that matches reality. Use verified proxy IPs/subnets or a trust function. Use a numeric hop count only where all routes have the same known length.
- Verify both normal and hostile cases. Send a request through the intended route, then try supplying your own XFF value. Confirm the application derives the address according to the proxy policy rather than blindly accepting the supplied value.
Express warns that enabling broad proxy trust is safe only when the last trusted proxy overwrites or removes relevant headers. It also warns that fixed hop counts can fail when requests can travel paths of differing lengths. MDN similarly cautions that if an application is reachable directly from the internet, forwarded values cannot be assumed trustworthy simply because a reverse proxy is also present.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Common errors and how to fix them
“I see the proxy IP, not the visitor”
remoteAddress reports the direct socket peer by design. If a proxy is in front, configure the application to trust the proxy and use its forwarded metadata. In Express, set an accurate trust proxy policy before relying on req.ip.
“req.ip changes when I add X-Forwarded-For”
Check whether proxy trust is enabled and what addresses or hops it trusts. Do not solve the mismatch by trusting all forwarded values without checking whether the last proxy sanitizes them.
“The first XFF value looks right, but rate limits are bypassable”
The requester may be able to set the leftmost value. Determine which proxies append or replace XFF, and derive the first untrusted address from the trusted side of the chain—or use Express’s proxy-aware logic with a verified topology.
“My Cloudflare header is missing or can be forged”
Confirm that the request is reaching the origin through Cloudflare and that the origin is not publicly reachable by another route. Check provider configuration and use documented headers only for traffic from that protected path.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute“IPv6 addresses fail a comparison or parser”
Do not assume every address is IPv4 or that an IPv6-mapped IPv4 string can be compared as plain text. Use a parser that supports IPv4 and IPv6, and make normalization rules consistent between trusted proxy ranges and observed addresses.
“Forwarded values arrive as arrays or multiple fields”
HTTP libraries can expose repeated fields differently. Handle the representation your runtime provides and follow the header’s grammar; do not silently discard extra values or assume a proxy always combines them.
Operational and privacy considerations
Log only what your application needs. Forwarding headers can reveal client network information, and retaining full IP addresses may create privacy and data-handling obligations depending on your jurisdiction and use case. Avoid treating an address as a durable user identifier. For abuse controls, combine a correctly derived network address with other signals and account for shared addresses so legitimate users are not treated as one person.
Node’s HTTP API and the Express proxy configuration are built-in implementation choices; no external IP lookup service is required to read the peer address or a properly trusted proxy value. The important reliability property is not a clever header parser but a deployment path whose trust boundaries are understood and enforced.
Or skip the browser setup
If your adjacent workflow needs screenshots of web pages rather than your own request’s network peer, ScreenshotNeo is a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or PDF; the service accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture. Each step can be disabled. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.
cURL example (replace the sample target and use your API key):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free for 1,000 screenshots a month, with no card required.
Frequently Asked Questions
Does an IP address identify a specific user?
No. It is a network address observed by the server or proxy, not a reliable person-level identity.
Free tools Windows power users keep installed
One-click scans. No signup required.
Should I store req.ips or only req.ip in Express?
Use req.ip for the framework-selected address; inspect req.ips only when you have a concrete diagnostic need to examine the trusted chain.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




