Max-Forwards general request
Limits how many times a request can be forwarded through proxies — used exclusively with TRACE and OPTIONS.
What it does
Max-Forwards limits how many times a request can be forwarded through proxies or gateways. Each proxy that forwards the request decrements the value by 1. When it reaches 0, the proxy stops forwarding and responds directly — even if it would normally pass the request along.
It's only meaningful on TRACE and OPTIONS requests. On any other method, proxies ignore it.
Syntax
Max-Forwards: <integer>
A non-negative decimal integer:
Max-Forwards: 0
Max-Forwards: 5
Max-Forwards: 10
How proxies handle it
- Received
Max-Forwards: 0→ Do not forward. Respond directly as if you were the final recipient. - Received
Max-Forwards: Nwhere N > 0 → Decrement to N-1 and forward withMax-Forwards: N-1. - Not present → Forward normally with no restriction.
Use with TRACE
TRACE is HTTP's built-in diagnostic method — it asks the final recipient (or the proxy that stops forwarding) to echo back the request as received. Combined with Max-Forwards, you can probe specific hops in a proxy chain:
TRACE /path HTTP/1.1
Host: example.com
Max-Forwards: 0
Max-Forwards: 0 means "the very next proxy should respond, not the origin." You get back what that proxy received, which tells you exactly what headers it adds, modifies, or strips.
TRACE /path HTTP/1.1
Host: example.com
Max-Forwards: 1
Reaches one proxy further — the second hop responds. Incrementing Max-Forwards lets you probe each layer of a proxy chain independently.
TRACE and security
TRACE was disabled on most production servers for years due to Cross-Site Tracing (XST) attacks — a now-largely-theoretical vulnerability where JavaScript could use TRACE to read HttpOnly cookies that were echoed back in the response body.
Modern browsers block JavaScript from sending TRACE requests, but many security configurations still disable TRACE at the server level (TraceEnable Off in Apache, no explicit enable in nginx). If you need TRACE for debugging, use it on a non-production environment or behind network-level access controls.
Use with OPTIONS
Max-Forwards on OPTIONS also limits how far the request travels — letting you ask a specific proxy what methods it supports rather than asking the origin server:
OPTIONS * HTTP/1.1
Host: example.com
Max-Forwards: 0
OPTIONS * with Max-Forwards: 0 asks the next proxy directly about its own capabilities. Useful for diagnosing proxy behaviour.
Real-world examples
Probing the first proxy in the chain:
TRACE / HTTP/1.1
Host: example.com
Max-Forwards: 0
HTTP/1.1 200 OK
Content-Type: message/http
TRACE / HTTP/1.1
Host: example.com
Max-Forwards: 0
Via: 1.1 proxy.corp.example.com
X-Internal-Header: value-added-by-proxy
The echoed request reveals what headers the proxy added — useful for debugging header injection or stripping.
Probing the full chain:
TRACE / HTTP/1.1
Host: example.com
Max-Forwards: 10
FAQ
Is Max-Forwards used in practice?
Rarely. Most network debugging today uses dedicated tools (traceroute, curl with verbose flags, proxy debug logs, distributed tracing systems like Zipkin/Jaeger). Max-Forwards + TRACE is an old-school technique from the pre-observability era that's mostly been superseded.
What happens if Max-Forwards reaches 0 at a non-proxy?
The origin server simply responds normally — Max-Forwards: 0 reaching the origin is identical to the origin receiving the request without Max-Forwards. The decrement-to-0 behaviour is for proxies, not for endpoints.
Does Max-Forwards work on POST or GET?
No — the spec states proxies must ignore Max-Forwards on methods other than TRACE and OPTIONS. Sending it on a GET request has no effect.
Fun fact
Max-Forwards and TRACE were designed to give HTTP a network-layer diagnostic tool analogous to traceroute — the ability to probe each hop in a path and see what it does to your packets (or in HTTP's case, your headers). The concept was sound, but TRACE's ability to echo request bodies and headers created the XST attack vector that led to TRACE being disabled nearly everywhere. It's now something of an HTTP archaeology artefact — specified, correct, and almost never used in production.