Skip to main content
Blog|
How-to guides

HTTP 431 Request Header Fields Too Large: what it means and how to fix it

|
Apr 10, 2026|10 min read
HOW-TO GUIDESHTTP 431 Request Header FieldsToo Large: what it means andhow to fix itHOSTNEYhostney.comApril 10, 2026

A 431 means the server refused to process your request because the HTTP headers are too large. Either a single header exceeds the server’s limit, or the combined size of all headers together is too much. The request never reaches the application – the server rejects it at the protocol level before parsing the body.

This is almost always caused by accumulated cookies, oversized JWT tokens, or a flood of custom headers added by proxies, extensions, or middleware. The server is protecting itself from requests that consume too much memory to parse.

Quick reference#

SymptomLikely causeFix
431 in browser on one specific siteCookies accumulated over timeClear cookies for that domain
431 in browser on all sitesBrowser extension injecting large headersDisable extensions and test in incognito
431 on API calls with Bearer tokensJWT token too large (too many claims)Reduce token payload or switch to opaque tokens with server-side sessions
431 after deploying a reverse proxyProxy adding forwarded headers on each hopFix duplicate header appending in proxy chain
“bad message 431” in Java/Jetty logsJetty’s default header limit (8KB) exceededIncrease requestHeaderSize in Jetty config
431 on Node.js serverNode’s default header limit (16KB) exceededStart with --max-http-header-size flag
431 intermittent, only some usersThose users have more cookies than othersAudit cookie size per user segment

What the HTTP specification says#

HTTP 431 is defined in RFC 6585, Section 5. The specification says the server is unwilling to process the request because its header fields are too large. The request may be resubmitted after reducing the size of the request header fields.

The specification distinguishes two cases:

  • An individual header field is too large (for example, a single Cookie header that is 32KB)
  • The total set of header fields is too large (many headers that individually are fine but collectively exceed the limit)

The server should indicate which case applies in the response body, though most implementations do not.

HTTP/1.1 431 Request Header Fields Too Large
Content-Type: text/html
Connection: close

A 431 is different from a 400 Bad Request. A 400 means the request is malformed – bad syntax, invalid encoding, or broken protocol. A 431 means the request syntax is fine but the headers are too large for the server to handle. Some servers (notably Nginx) return 400 instead of 431 for oversized headers because Nginx predates RFC 6585. If you see 400 Bad Request: Request Header Or Cookie Too Large in Nginx, it is the same underlying issue.

The two limit types#

Single header too large

One header exceeds the server’s per-header buffer. The most common offender is the Cookie header, which contains every cookie set for the domain concatenated into a single value:

Cookie: session_id=abc123; analytics_1=...; analytics_2=...; tracking=...; 
preferences=...; ab_test_1=...; ab_test_2=...; (continues for 16KB)

Every analytics tool, A/B testing platform, chat widget, and marketing pixel that sets a cookie adds to this header. On a site with 15 third-party scripts, each setting 2-3 cookies, the Cookie header can easily reach 8-16KB.

Total headers too large

No single header is oversized, but the sum of all headers exceeds the server’s total limit. This happens with:

  • Reverse proxy chains that append X-Forwarded-For , X-Forwarded-Proto , X-Request-ID , and custom headers at each hop
  • API gateways that inject authentication, rate limit, and routing headers
  • Browser extensions that add custom headers to every request
  • Application frameworks that set many small headers (CORS, security, caching)

Common causes#

Cookies accumulating over time

The most frequent cause by far. Cookies for a domain persist in the browser until they expire or are cleared. Over weeks or months of visiting a site, cookies from analytics, advertising, session management, and feature flags accumulate:

# Check your cookie size in DevTools console
document.cookie.length

If the number is above 4000, you are getting close to typical server limits. Above 8000, most servers will reject the request.

Subdomains make this worse. A cookie set on .example.com is sent to every subdomain: www.example.com , app.example.com , api.example.com , cdn.example.com . Third-party scripts that set cookies on the root domain pollute every subdomain’s requests.

The fix for users: clear cookies for the affected domain. The fix for developers: audit cookies regularly, set appropriate expiration times, scope cookies to specific paths and subdomains, and move analytics to server-side tracking where possible.

Large JWT tokens

JWT (JSON Web Token) authentication sends the full token in the Authorization header on every request. A JWT contains claims – user data, roles, permissions, metadata – and every claim increases the token size:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIx
MjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZXMiOlsiYWRtaW4iLCJlZGl0
b3IiLCJ2aWV3ZXIiXSwicGVybWlzc2lvbnMiOlsicmVhZDp1c2VycyIsIndyaXRlOnVzZ
XJzIiwicmVhZDpwb3N0cyIsIndyaXRlOnBvc3RzIiwiZGVsZXRlOnBvc3RzIl19...

A minimal JWT is around 300 bytes. But tokens that embed full permission sets, user profiles, or organization hierarchies can grow to 4-8KB. Multiply that by a few requests in flight and the header budget is consumed.

The fix: keep JWTs small. Store only essential claims (user ID, role names) in the token. Look up detailed permissions server-side. If your token needs to be large, consider opaque tokens (a random string that references a server-side session) instead of self-contained JWTs.

Proxy and CDN header accumulation

Each layer in a request chain adds headers:

Client -> CDN -> Load Balancer -> Reverse Proxy -> Application

CDN adds: CF-Connecting-IP, CF-Ray, CF-IPCountry, CF-Visitor
LB adds: X-Forwarded-For, X-Forwarded-Proto, X-Request-ID
Proxy adds: X-Real-IP, X-Forwarded-Host, X-Nginx-Proxy

This is normally fine. But misconfigured proxies can append instead of replace headers on each hop, causing them to grow with each request through the chain. A X-Forwarded-For header that should contain one IP ends up with a chain of IPs from every proxy:

X-Forwarded-For: 203.0.113.50, 10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4

In extreme cases with many proxy hops or request retries, this can cause a 431.

Browser extensions

Extensions can inject headers into every request. Privacy extensions, ad blockers, VPN extensions, and developer tools each add their own headers. With enough extensions active, the combined header size crosses the limit.

Test by opening the site in an incognito window with all extensions disabled. If it works in incognito, an extension is the cause.

Server-specific limits and configuration#

Nginx

Nginx uses large_client_header_buffers to control header size limits:

# Default: 4 buffers of 8KB each
large_client_header_buffers 4 8k;

This means: Nginx allocates up to 4 buffers of 8KB each for request headers. A single header line (like the Cookie header) must fit in one buffer (8KB). The total of all headers must fit in the combined buffer space (32KB).

Note: Nginx returns 400 Bad Request for oversized headers, not 431 . The 400 Bad Request: Request Header Or Cookie Too Large error is Nginx’s version of a 431.

To increase the limit:

http {
    large_client_header_buffers 4 16k;
}

After changing, test and reload:

nginx -t && systemctl reload nginx

Increasing buffer sizes is a valid fix but it consumes more memory per connection. On high-traffic servers, doubling the header buffer from 8k to 16k across thousands of concurrent connections adds up. Fix the root cause (reduce cookie/header size) rather than just increasing limits.

Apache

Apache uses LimitRequestFieldSize for individual headers and LimitRequestFields for the number of headers:

# Default: 8190 bytes per header, 100 headers max
LimitRequestFieldSize 16384
LimitRequestFields 100

Apache returns 400 Bad Request for oversized headers by default. Some configurations with mod_security or custom error handlers may return 431.

Node.js

Node.js has a default maximum header size of 16KB (raised from 8KB in Node 12):

# Check current limit
node -e "console.log(require('http').maxHeaderSize)"

# Start with a larger limit
node --max-http-header-size=32768 app.js

For Express applications, you can also set this in the server options:

const server = app.listen(3000, {
    maxHeaderSize: 32768
});

Java/Jetty

The “bad message 431” error is specific to Jetty. Jetty’s default request header size is 8KB:

<!-- In jetty.xml or jetty-http.xml -->
<Set name="requestHeaderSize">16384</Set>

For Spring Boot applications using embedded Jetty:

server.max-http-request-header-size=16384

Tomcat

Tomcat’s default is 8KB for header size:

<!-- In server.xml, Connector element -->
<Connector port="8080" maxHttpHeaderSize="16384" />

For Spring Boot with embedded Tomcat:

server.max-http-header-size=16384

How to diagnose#

Step 1 – Check cookie size

Open browser DevTools, go to the Console tab, and run:

document.cookie.length

Then check the Application tab (Chrome) or Storage tab (Firefox) to see individual cookies and their sizes. If the total is above your server’s limit, cookies are the cause.

Step 2 – Check the full request headers

In the Network tab of DevTools, find the failed request and look at the Request Headers section. Look for:

  • A Cookie header that is several KB
  • An Authorization header with a large JWT
  • Many X- headers from proxies or middleware
  • Unusual headers from browser extensions

Step 3 – Test in incognito

An incognito window starts with no cookies and most extensions disabled. If the request works in incognito, the cause is accumulated cookies or an extension.

Step 4 – Test with curl

curl sends no cookies by default (unless you specify a cookie jar). If the request works with curl but fails in the browser, the browser is sending extra data (cookies, extension headers) that pushes the request over the limit:

curl -I https://example.com/page-that-fails

Step 5 – Check server error logs

The server’s error log usually reports the specific reason:

# Nginx
tail -20 /var/log/nginx/error.log
# Look for: "client sent too long header line" or "too long request header"

# Node.js
# Look for: "Parse Error: Header overflow"

# Jetty
# Look for: "Header too large" or "bad message 431"

Fixing on the client side#

Clear cookies

The fastest fix. Clear cookies for the affected domain:

  • Chrome: DevTools > Application > Cookies > right-click domain > Clear
  • Firefox: Settings > Privacy & Security > Cookies and Site Data > Manage Data > find domain > Remove
  • All browsers: incognito window bypasses the issue immediately

Disable browser extensions

If clearing cookies does not help, disable extensions one at a time to find which one is injecting large headers.

Reduce JWT token size

If you control the application:

  • Remove unnecessary claims from the token
  • Store detailed permissions server-side, reference them by role name in the token
  • Consider opaque tokens for server-to-server communication where self-contained tokens are not needed
  • Set shorter token expiry and refresh frequently rather than embedding everything to avoid round trips

Fixing on the server side#

Audit and reduce cookies

The permanent fix. Audit every cookie your site sets:

# List all cookies in DevTools console
document.cookie.split(';').forEach(c => {
    const [name, val] = c.trim().split('=');
    console.log(name, val ? val.length : 0, 'bytes');
});

For each cookie, ask:

  • Is this cookie still needed?
  • Can it be scoped to a specific path instead of the root domain?
  • Can it be set on a subdomain instead of the root domain?
  • Can the data be stored server-side (in a session or database) with only a session ID in the cookie?
  • Can the expiration be shortened?

Increase server header limits

A valid short-term fix while you audit the root cause. See the server-specific sections above for Nginx, Apache, Node.js, Jetty, and Tomcat configuration.

Do not set limits excessively high. Large header limits increase memory usage per connection and can make the server more vulnerable to slowloris-style attacks where an attacker sends very large headers to exhaust server memory.

Fix proxy header duplication

If headers grow through a proxy chain, ensure each proxy replaces rather than appends:

# Nginx - set (replace) instead of add (append)
proxy_set_header X-Forwarded-For $remote_addr;

# Not this (appends on each hop):
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Use $proxy_add_x_forwarded_for only on the first proxy in the chain. Subsequent proxies should use $remote_addr to avoid the header growing with each hop.

Status codeWhat happened
400 Bad RequestRequest is malformed – bad syntax, encoding errors
400 Request Header Or Cookie Too LargeNginx-specific version of 431 (Nginx predates RFC 6585)
431 Request Header Fields Too LargeHeaders exceed server limits – clear cookies or reduce header size
413 Request Entity Too LargeThe request body (not headers) is too large – increase upload limits

The key distinction: 431 is about request headers (metadata sent before the body). 413 is about the request body (the actual content being uploaded). They have completely different causes and fixes.

Summary#

A 431 Request Header Fields Too Large means the server rejected your request because the HTTP headers are too big. The most common cause is accumulated cookies – clear them and the error goes away immediately. For a permanent fix, audit your cookies, reduce JWT token sizes, or fix proxy header duplication. Increasing server header limits is a valid workaround but address the root cause first.