Forwarded: the standardised proxy header
Forwarded is the standardised way for a proxy to record who the request came from, which interface received it, and which host and scheme the client used.
At a glance
- Direction
- Request, added by proxies.
- Defined in
- RFC 7239
- When absent
- Look for the older X-Forwarded-For and X-Forwarded-Proto headers, which are still far more widely deployed.
- Parameters
- for, by, host and proto, as name equals value pairs
- Multiple hops
- Comma separated entries, oldest first, each one appended by a proxy
- Quoting
- Required for IPv6 and for a port: for="[2001:db8::1]:4711"
- Obfuscation
- A value may be an opaque token such as _hidden instead of a real address.
In detail
One header replaces a family of ad hoc ones. Where the older approach needed X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host, this carries all three as parameters in a single entry per hop, which removes the ambiguity of three independent lists that can disagree about how many hops there were.
The syntax is stricter than the older headers, and that is the point. An IPv6 address or an address with a port must be quoted and bracketed, so a parser has an unambiguous grammar to work with rather than splitting on commas and hoping. The by parameter records the interface the proxy received on, which the older set could not express at all.
Obfuscated identifiers are part of the design. A proxy that wants to preserve the chain without publishing internal addresses can substitute a token beginning with an underscore, which keeps the structure of the path visible while hiding the topology. That is not available in the older headers, where anything other than an address is simply malformed.
Trust is the same problem as ever. A client can send this header itself, so anything present before your own edge is client supplied. The rule that works is to have the outermost proxy you control overwrite it, and to count hops inward from that entry rather than reading the first one you see.
Examples
Forwarded: for=203.0.113.7; by=198.51.100.1; host=example.com; proto=httpsForwarded: for="[2001:db8:cafe::17]:4711", for=198.51.100.17Oldest first, so the client is the leftmost entry and the nearest proxy is the rightmost.
Things that catch people out
- Support is thinner than for the X-Forwarded set, so a load balancer may pass this header through untouched while rewriting the older ones.
- IPv6 addresses must be bracketed and quoted. A parser written for the older comma separated format mangles them.
- Anything arriving before your own edge is client supplied and forgeable, which makes the leftmost entry the least trustworthy one in the list.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →X-Forwarded-For: the client address behind a proxy
How the X-Forwarded-For list is built, why the leftmost address is not trustworthy, how to count trusted hops, and what breaks rate limiting behind a proxy.
X-Forwarded-Proto: the scheme the client actually used
Why an application behind a proxy cannot see the client scheme, how X-Forwarded-Proto restores it, and the redirect loop that follows from ignoring it.
Via: the proxies a message passed through
How Via records each intermediary, what the protocol and pseudonym fields mean, how it detects request loops, and why it is useful when debugging a cache.
Host: which site the request is for
Why Host is mandatory in HTTP/1.1, how it maps to the authority in HTTP/2 and HTTP/3, and why trusting it to build URLs creates a real vulnerability.
Connection: keep-alive, close and hop by hop headers
What the Connection header controls, how it lists hop by hop headers, why HTTP/1.1 keeps connections open by default, and why HTTP/2 forbids it.
Upgrade: switching protocols on an open connection
How the Upgrade header negotiates a protocol switch, what a 101 response means, why proxies break WebSocket handshakes, and what HTTP/2 does instead.
Tools for this
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body