Back to HTTP Headers

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: N where N > 0 → Decrement to N-1 and forward with Max-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.

Related Headers