X-Forwarded-For (XFF)

Networking

An HTTP header containing the original client IP address and any intermediate proxy IPs. Format: X-Forwarded-For: client, proxy1, proxy2. Each proxy appends its predecessor's IP to the list.

Updated Apr 3, 2026

Full Explanation

X-Forwarded-For (XFF) is an HTTP header that tracks the original client IP address as a request passes through proxies, load balancers, and CDNs. Each proxy in the chain appends the IP address it received the connection from, building a comma-separated list. The format is X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip.

The tricky part is trust. The leftmost IP in the list is supposed to be the original client, but anyone can set or spoof the X-Forwarded-For header on the initial request. The only IP you can truly trust is the one added by infrastructure you control. In practice, you start from the right side of the list and count back through proxies you trust. If you know your request passes through your CDN and then your load balancer (two trusted hops), the third entry from the right is the real client IP.

XFF is critical for rate limiting, geo-targeting, logging, fraud detection, and access control. Without it, your application would only see the IP of the last proxy in the chain. Note that XFF is a de facto standard, not an official one. The standardized replacement is the Forwarded header defined in RFC 7239, which uses a structured format like Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43. In practice, most systems still use XFF.

// Client (203.0.113.50) sends request to CDN
GET /api/users HTTP/1.1
Host: api.example.com

// CDN (198.51.100.1) forwards to load balancer, adds client IP
GET /api/users HTTP/1.1
Host: api.example.com
X-Forwarded-For: 203.0.113.50

// Load balancer (10.0.0.1) forwards to app, adds CDN IP
GET /api/users HTTP/1.1
Host: api.example.com
X-Forwarded-For: 203.0.113.50, 198.51.100.1

// App sees: client=203.0.113.50, CDN=198.51.100.1, LB=connection IP

Examples

Here is how to configure Nginx to extract the real client IP from XFF when sitting behind a trusted CDN.

# Nginx: trust your CDN and load balancer IPs
set_real_ip_from 198.51.100.0/24;  # CDN IP range
set_real_ip_from 10.0.0.0/8;       # Internal LB range
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# Now $remote_addr contains the actual client IP
log_format main '$remote_addr - $request';

Video Explanation

Frequently Asked Questions

An HTTP header containing the original client IP address and any intermediate proxy IPs. Format: X-Forwarded-For: client, proxy1, proxy2. Each proxy appends its predecessor's IP to the list.

Here is how to configure Nginx to extract the real client IP from XFF when sitting behind a trusted CDN.

# Nginx: trust your CDN and load balancer IPs
set_real_ip_from 198.51.100.0/24;  # CDN IP range
set_real_ip_from 10.0.0.0/8;       # Internal LB range
real_ip_header X-Forwarded-For;
real_ip_recursive on;

# Now $remote_addr contains the actual client IP
log_format main '$remote_addr - $request';