Introduction
One of the most common requirements in modern web development is identifying a visitor's public IP address. Developers rely on IP detection to implement geofencing, calculate local shipping rates, analyze traffic patterns, and enforce security policies (such as blocking multiple failed login attempts from a single source).
However, retrieving a user's IP in JavaScript depends heavily on where the code runs:
- Client-Side (in the Browser): Browsers cannot directly access a user's network interfaces for security reasons. Frontend JavaScript must query an external server to reveal the public IP.
- Server-Side (in Node.js/Deno/Bun): The server has direct access to the incoming network socket. However, if your server sits behind a CDN, reverse proxy, or load balancer, reading the socket IP returns the proxy's address, requiring you to parse forwarded headers.
In this guide, we will cover complete, production-ready solutions for getting a client's IP in both frontend and backend JavaScript environments.
Client-Side: Getting the IP inside the Browser
Because the browser sandbox restricts direct access to system-level network details (such as your local Wi-Fi router's gateway details), the only way to determine a visitor's public IP is by making an asynchronous HTTP request (fetch) to an external lookup service.
Here is a modern, clean implementation using ES6 async/await to get the user's IP address and display it on your web page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Get User IP Example</title>
</head>
<body>
<h1>Welcome to our site!</h1>
<p>Your detected IP address is: <span id="user-ip">Detecting...</span></p>
<script>
async function fetchUserIP() {
const ipDisplayElement = document.getElementById('user-ip');
try {
// Calling a JSON-formatted IP detection endpoint
const response = await fetch('https://tracethatip.com/json');
if (!response.ok) {
throw new Error(`Network response was not ok: ${response.status}`);
}
const data = await response.json();
ipDisplayElement.textContent = data.ip;
} catch (error) {
console.error('Failed to resolve client IP:', error);
ipDisplayElement.textContent = 'Unable to detect IP (Ad-blocker active or offline).';
}
}
// Run detection on page load
window.addEventListener('DOMContentLoaded', fetchUserIP);
</script>
</body>
</html>
Important Browser Gotcha: Ad Blockers
Some privacy-focused extensions and ad blockers proactively block standard third-party geolocation endpoints. To make your frontend lookups resilient, wrap your lookup requests in try-catch statements and gracefully fail by falling back to default styling/currency layouts if the network query is blocked.
To verify what your own browser reports to our tracking tools, you can visit our public What's My IP screen.
Server-Side: Getting the IP in Node.js (Express)
In a backend server environment, you do not need to query external third-party services. When a client requests a page, Node.js opens a TCP socket connection, which natively holds the client's IP address.
The Basic Method (Direct Socket Query)
If your Node.js application is connected directly to the internet (with no intermediary proxy), you can read the client's IP address from the request socket:
const express = require('express');
const app = express();
app.get('/api/my-ip', (req, res) => {
// Read the remote IP address from the socket connection
const clientIp = req.socket.remoteAddress;
res.send({ ip: clientIp });
});
app.listen(3000, () => console.log('Server running on port 3000'));
The Real-World Method: Handling Proxies and CDNs
In modern production deployments, your application server rarely communicates directly with the user. It is almost always hidden behind:
- CDNs (like Cloudflare, Fastly, or Akamai)
- Load Balancers (like AWS ALB or Google Cloud Load Balancing)
- Reverse Proxies (like Nginx, HAProxy, or Traefik)
When a request travels through these intermediaries, the source IP of the TCP socket changes to the proxy's IP. To pass along the original visitor's address, proxies append custom HTTP headers.
The standard header is X-Forwarded-For (XFF). It contains a comma-separated list of IP addresses that the request has traveled through:
X-Forwarded-For: client-ip, proxy1-ip, proxy2-ip
Here is a robust, production-ready Express middleware helper to extract the real visitor IP:
const express = require('express');
const app = express();
// Enable express proxy trust flag if your server is behind a trusted reverse proxy
// This automatically configures Express to parse x-forwarded-for headers.
app.set('trust proxy', true);
app.get('/debug-connection', (req, res) => {
// 1. Read IP via Express' built-in proxy resolver
let ip = req.ip;
// 2. Fallback manual resolution if 'trust proxy' is not supported
if (!ip) {
const xForwardedFor = req.headers['x-forwarded-for'];
if (xForwardedFor) {
// Take the first IP in the comma-separated chain (original client)
ip = xForwardedFor.split(',')[0].trim();
} else {
ip = req.socket.remoteAddress;
}
}
res.json({
resolvedIp: ip,
headers: {
'x-forwarded-for': req.headers['x-forwarded-for'] || null,
'x-real-ip': req.headers['x-real-ip'] || null,
'cf-connecting-ip': req.headers['cf-connecting-ip'] || null // Cloudflare specific
}
});
});
app.listen(3000, () => console.log('Secure server running on port 3000'));
IP Address Parsing Security: IP Spoofing Risks
When resolving visitor IPs on the backend, be extremely careful about security:
- Header Spoofing: Because HTTP headers can be easily manipulated by clients, never blindly trust
X-Forwarded-Forunless you know for a fact your server sits behind a trusted reverse proxy that overrides this header. - Security Rule: If you are running an internal server with no proxy, ignore
X-Forwarded-Forcompletely and rely strictly onreq.socket.remoteAddressto avoid spoofed requests.
For security validation, you can test how different server setups parse headers and formatting styles in our developer IP Formatter section.
Summary
In frontend JavaScript, finding the client IP requires fetching an external JSON endpoint. In backend Node.js architectures, you can inspect the request socket directly or parse headers like X-Forwarded-For if your server runs behind reverse proxies. By implementing correct headers checks and security sanitization, you can reliably capture client network configurations.
Explore more developer guides:
- Read about structured developer outputs on our IP Formatter page.
- Troubleshoot IP location anomalies using our IP Lookup dashboard.
