# Forwarded

> Learn how the Forwarded header preserves original client information (IP, protocol, host) that would otherwise be lost when requests pass through proxies.

Source: https://howhttpworks.com/headers/forwarded
Last reviewed: 2026-10-05

> **TL;DR:** `Forwarded` is the standard header proxies use to pass along who the client was: `for` (the previous peer, usually the client IP), `by` (the proxy), `host`, and `proto`. Commas separate hops and semicolons separate parameters. Quote bracketed IPv6 addresses, and trust only the parts your own proxies added.

## What is Forwarded?

[RFC 7239](https://www.rfc-editor.org/rfc/rfc7239) defines this header, and it's still the current spec; RFC 9110 didn't replace it. Every parameter is optional. `for` doesn't have to hold a client IP either: it can be `unknown` or an obfuscated identifier.

## Syntax

The headers and output on this page are examples.

```http
Forwarded: for=192.0.2.60;proto=https;host=example.com
Forwarded: for="[2001:db8::1]:4711";proto=https;host="example.com:8443"
```

IPv6 addresses need brackets **and** quotes. Quote any value that contains a colon, including a hostname with a port. Parameter names are case-insensitive, and each parameter appears at most once per element.

## Example

A two-hop chain:

```http
Forwarded: for=192.0.2.60;proto=https, for=198.51.100.7;by=203.0.113.5
```

Each proxy that supports the header appends its own element on the right. Plenty of proxies don't, so the list may be missing hops.

## Parsing and Trust

The client can send the first element itself. A trusted proxy connection vouches only for what that proxy added, not for anything earlier in the list. Before you use Forwarded for authorization or to decide a client's address, find out which of your proxies strip it, append to it, or regenerate it. [RFC 7239 §8.1](https://www.rfc-editor.org/rfc/rfc7239#section-8.1) covers these limits.

## Implementation

If nginx is your IPv4 edge and receives requests straight from clients, this replaces whatever Forwarded value came in. Add it to an existing proxy location:

```nginx
proxy_set_header Forwarded 'for="$remote_addr";proto=$scheme';
proxy_pass http://127.0.0.1:3000;
```

It sends only `for` and `proto`, and it's **IPv4-only**: on an IPv6 listener you need to wrap the address in brackets before putting it in `for`. If TLS terminates in front of nginx, `$scheme` describes the inner connection, not what the browser used. See [nginx proxy_set_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header).

To see what reaches your app, add a diagnostic Express endpoint that echoes the raw header:

```javascript
app.get('/forwarding', (req, res) => {
  res.json({ forwarded: req.get('forwarded') ?? null })
})
```

Then send a forged value through the nginx config above:

```bash
curl -H 'Forwarded: for=192.0.2.60;proto=https' http://localhost/forwarding
```

You should see nginx's value, not the one you sent. Change the URL to match your proxy listener. This confirms nginx rewrites the header; it doesn't test a multi-hop parser.

## Forwarded vs X-Forwarded-*

Forwarded gives everyone one grammar, but frameworks won't read it just because it exists. Express's [trust proxy documentation](https://expressjs.com/en/guide/behind-proxies/), for example, covers the X-Forwarded fields. Check what your app consumes before you change what your proxy sends.

## Common Mistakes

Splitting the header on every comma and semicolon breaks on quoted strings, which can contain those delimiters and escapes. Use a parser that understands quoting. Another trap: preferring a client-supplied Forwarded value over a trusted proxy's X-Forwarded value just because Forwarded is the standard name.

At each trust boundary, pick one source of truth for scheme, host, and client address. If you support both header families, decide what happens when they conflict. Neither family cryptographically proves where a request came from.

## Related Headers

- [X-Forwarded-For](https://howhttpworks.com/headers/x-forwarded-for)
- [X-Forwarded-Proto](https://howhttpworks.com/headers/x-forwarded-proto)
- [Via](https://howhttpworks.com/headers/via)
