Short answer
431 Request Header Fields Too Large means the request headers, almost always the Cookie header, are bigger than the server accepts. As a visitor, delete that one site’s cookies and reload. As the owner, find which server in the chain answered (usually Node.js, whose limit is 16 KB), shrink the cookies, or raise the limit with --max-http-header-size.Where to start
- If Chrome shows HTTP ERROR 431 on someone else's sitedelete that site’s cookies
- If your own dev server on localhost answers 431raise Node’s limit or clear localhost cookies
- If you get 431 even in a private window with no cookieslook for a proxy that forwards to itself
- If an ASP.NET Core, Spring Boot or Jetty app refuses big headersraise Kestrel’s, Tomcat’s or Jetty’s limit
- If the same oversized request gets 400 instead of 431nginx or Apache answered first
- If the site runs behind Cloudflarethe edge allows 128 KB, so your origin is the limit
What does HTTP error 431 mean?
Status 431 was added to HTTP in 2012 by RFC 6585, section 5. A server sends it when it refuses to read the request because the header section as a whole, or one single header field, is larger than it is willing to process. The client is allowed to try again with smaller headers. Nothing is wrong with the URL, the page or the server’s health: the request was simply too big before the body even started.
Three neighbouring codes are easy to mix up: 413 Content Too Large means the request body is too big (an upload), 414 URI Too Long means the URL is too long (nginx, Apache, Kestrel and Jetty send it for an oversized request line), and 431 means the headers are too big.
In practice the oversized header is usually the Cookie header. Browsers send every cookie stored for a host with every request to it, and RFC 6265 asks browsers to support cookies of at least 4,096 bytes each and at least 50 per domain. Five cookies of 4 KB are already more than 16 KB, which is exactly where Node.js stops. The rest are long Referer URLs full of tracking parameters, big single sign-on or Kerberos tokens, and proxies that keep adding forwarding headers.
Key facts
- Status line
- 431 Request Header Fields Too Large
- Defined in
- RFC 6585, section 5 (2012)
- Chrome shows
- HTTP ERROR 431
- Usual cause
- Too many or too large cookies
- Node.js default limit
- 16 KB (16,384 bytes), all headers togetherSince Node 13.13.0; 8 KB before
- nginx default
- 4 buffers of 8 KB, answers 400 or 414, never 431
- Apache default
- 8,190 bytes per field, 100 fields, answers 400
- Cloudflare edge
- 128 KB of request headersRaised from 32 KB in October 2025
- Also send 431
- Kestrel (32 KB), Jetty (8 KB), Go, Python http.server
- Answer 400 instead
- Tomcat and Spring Boot (8 KB), IIS (16 KB)
So the status code itself tells you something: a 431 almost always comes from an application server, not from the web server in front of it. The servers that send it, and the ones that send something else for the same problem, with the defaults checked against each project’s documentation or source on November 2, 2026:
| Server | Default limit | Status when exceeded | Setting |
|---|---|---|---|
| Node.js (Express, Next.js, Vite, Nuxt dev servers) | 16 KB for the request line and all headers | 431, empty body | --max-http-header-size, maxHeaderSize |
| Go net/http | 1 MB (DefaultMaxHeaderBytes) | 431 | http.Server{MaxHeaderBytes: ...} |
| ASP.NET Core Kestrel | 32 KB for all headers, 100 headers, 8 KB request line | 431 (414 for the request line) | Limits.MaxRequestHeadersTotalSize |
| Jetty | 8 KB for the request line and all headers | 431 (414 for the request line); Jetty 9 to 11 show Bad Message 431 | requestHeaderSize |
| Python http.server | 65,536 bytes per line, 100 headers | 431 Line too long / 431 Too many headers (414 for the request line) | none (development server) |
| nginx | 8 KB per header line, 4 buffers of 8 KB | 400, or 414 for a long request line | large_client_header_buffers |
| Apache httpd 2.4 | 8,190 bytes per field, 100 fields, 8,190 for the request line | 400 (414 for the request line) | LimitRequestFieldSize, LimitRequestFields |
| Tomcat, Spring Boot (default server) | 8 KB for the request line and all headers | 400, logged as Request header is too large | maxHttpHeaderSize, server.max-http-request-header-size |
| IIS (HTTP.sys) | 16 KB per header, 16 KB for request line plus headers | 400 | MaxFieldLength, MaxRequestBytes in the registry |
| Cloudflare | 128 KB of request headers in total | 413 per Cloudflare's changelog; a reset connection in our test | not configurable |
How do I fix HTTP error 431 in Chrome?
Chrome shows its own “This page isn’t working” screen with HTTP ERROR 431 underneath, because Node.js sends the status with an empty body and the browser has nothing else to display. The fix on your side is the same as for a cookie-sized 400:
- Test in an incognito window. It starts without your cookies. If the page loads there, your stored cookies for that site are the problem.
- Delete the cookies of that one site. Click the icon to the left of the address bar, open the cookies or site settings entry, and delete the data for that site. You can also open
chrome://settings/content/all, search for the domain and delete its data there. You do not need to clear your whole browser history. - Sign out and sign in again. A fresh login replaces piled-up session and token cookies with new, usually smaller ones. If the error shows up right after a single sign-on login (Google, Microsoft, Okta and the like), that is the typical pattern: the identity provider’s redirect adds large cookies or state to the request, and the site’s own cookies push it over the limit.
- Shorten the link. If you came from a link with a very long query string, open the plain address without everything after the
?. The long URL travels in theRefererheader of the next requests. - Turn off extensions that add headers (header editors, some VPN and privacy add-ons) and reload.
If the site still fails in a fresh private window, the problem is on the server side and only its operator can fix it.
Reproduce 431 with curl
Before you change any limit, make the error happen on demand. A cookie made of a few thousand a characters does it. The status codes below are the ones a default Node.js 26 server returned in our test:
# a 16,000-character cookie still fits, 20,000 does not
curl -s -o /dev/null -w '%{http_code}\n' \
-H "Cookie: big=$(head -c 16000 /dev/zero | tr '\0' a)" http://127.0.0.1:3000/
200
curl -s -o /dev/null -w '%{http_code}\n' \
-H "Cookie: big=$(head -c 20000 /dev/zero | tr '\0' a)" http://127.0.0.1:3000/
431The full response shows how little Node.js says about it: a status line, a Connection: close and no body, no Server header, no hint which header was too big.
HTTP/1.1 431 Request Header Fields Too Large
Connection: close
Real browser cookies trip it the same way. Four cookies of 4,000 bytes (16,018 bytes in the Cookie header) still got a 200 from the default server; a fifth one turned it into 431. To see what a real browser sends, open the developer tools, Network tab, right-click the failing request and choose Copy as cURL. The -H 'cookie: ...' part is your cookie header, and pasting the command into a terminal reproduces the error with the exact same headers. Count its size like this:
# paste the cookie value between the quotes
printf '%s' 'session=...; _ga=...; consent=...' | wc -cdocument.cookie.length in the console is a quick first look, but it leaves out HttpOnly cookies, which are often the biggest ones (sessions, tokens). Copy as cURL includes them. For more ways to send custom headers from the command line, see the curl examples.
Fix 431 in Node.js (Express, Next.js, Vite)
Node.js is the most common sender of 431, and it is behind most “431 localhost” reports, because Express, Next.js, Vite and Nuxt all serve your app through Node’s HTTP server. Its limit, --max-http-header-size, defaults to 16,384 bytes since Node 13.13.0 (it was 8 KB before, which is why older articles still say 8 KB). The limit covers the request line and all headers together, not one header: in our test a 17,000-character URL with no cookie at all also got 431, where nginx would have answered 414.
Check the value your Node.js uses:
node -p "require('http').maxHeaderSize"
16384Raise it for one process
node --max-http-header-size=32768 server.jsFor tools you do not start with node yourself (next dev, vite, npm start), pass the flag through NODE_OPTIONS, which accepts it. Every Node process started from that shell inherits it:
NODE_OPTIONS='--max-http-header-size=32768' npm run dev$env:NODE_OPTIONS = "--max-http-header-size=32768"
npm run devset NODE_OPTIONS=--max-http-header-size=32768
npm run devTo keep it with the project, put the flag into the script in package.json, for example "start": "node --max-http-header-size=32768 server.js", or into the Environment= line of the systemd unit that runs the app.
Raise it in code for one server
http.createServer takes a maxHeaderSize option that overrides the flag for that server only. With Express, create the server yourself instead of calling app.listen:
const http = require("http");
const express = require("express");
const app = express();
app.get("/", (req, res) => res.send("ok"));
http.createServer({ maxHeaderSize: 32768 }, app).listen(3000);In our test the server with 32,768 accepted a 32,000-character cookie and answered 431 at 33,000, and NODE_OPTIONS with 65,536 moved the line to just under 64 KB. Prefer 16 KB steps over a huge number: every connection may hold that much header data in memory, and a server that accepts megabytes of headers is easier to tie up. If 32 KB is not enough, the cookies are the bug.
Why localhost collects so many cookies
Cookies are not separated by port. RFC 6265 says so in section 8.5, and browsers follow it: every app you have run on localhost:3000, localhost:5173 or localhost:8080 stores its cookies for the host localhost, and all of them are sent to whichever dev server you open next. A few auth libraries, an analytics snippet and an old project’s session cookie add up fast. Two clean ways out:
- Clear the site data for
localhost(developer tools, Application tab, Storage, Clear site data). The 431 disappears at once if cookies were the cause. - Give each project its own host name:
127.0.0.1keeps a separate cookie jar fromlocalhost, and Chrome resolves names likeshop.localhostto your own machine, so every project gets its own cookies.
431 with no cookies at all: a proxy loop
If the error stays in a private window with every cookie gone, check the proxy setting of your dev server. A proxy entry whose target is the dev server itself (the same port, or a host name that resolves back to it) makes the request travel in a circle. Proxy middleware that adds X-Forwarded-For and similar headers makes the request a little longer on every pass, until Node’s 16 KB limit stops it and the 431 comes back to the browser. Point the proxy at the API’s real port, and the error is gone without touching any limit. A raised limit only makes such a loop run longer.
Fix 431 in ASP.NET Core and Java (Kestrel, Jetty, Tomcat, Spring Boot)
These limits and status codes come from each project’s source and documentation, checked on November 2, 2026, not from our own test. ASP.NET Core’s Kestrel answers 431 when all request headers together pass MaxRequestHeadersTotalSize (32 KB) or when there are more than 100 of them, and 414 when the request line passes MaxRequestLineSize (8 KB). Raise it in Program.cs:
builder.WebHost.ConfigureKestrel(options =>
{
options.Limits.MaxRequestHeadersTotalSize = 65536;
});Behind IIS, HTTP.sys reads the request before your app does, and it answers 400 at its own 16 KB per header (MaxFieldLength, MaxRequestBytes under HKLM\System\CurrentControlSet\Services\HTTP\Parameters). The 400 guide covers that registry change.
In Java, the answer depends on the embedded server. Jetty counts the request line and all headers against requestHeaderSize, 8 KB by default, and sends 431 (414 while it is still reading the URL); Jetty 9 to 11 show the page as Bad Message 431. Tomcat, which Spring Boot uses unless you swap it, has the same 8 KB but answers 400, and its log shows Request header is too large. So a Spring Boot app gives 400 on Tomcat and 431 on Jetty for the same request. Spring Boot sets both through one property, called server.max-http-header-size before Spring Boot 3.0. A proposal to raise the 8 KB default to 16 KB was declined in 2025, so it is still 8 KB:
server.max-http-request-header-size=16KB<Connector port="8080" protocol="HTTP/1.1"
maxHttpHeaderSize="16384" />java -jar $JETTY_HOME/start.jar jetty.httpConfig.requestHeaderSize=16384Behind nginx: why you see 400, not 431
nginx never sends 431. It reads request headers into a 1 KB buffer and then into large_client_header_buffers, 4 buffers of 8 KB by default. A header line longer than one buffer gets 400 Request Header Or Cookie Too Large, and a request line longer than one buffer gets 414. Since the limits also apply to HTTP/2 and HTTP/3, switching protocols changes nothing. That variant has its own guide: 400 Request Header Or Cookie Too Large.
With nginx in front of a Node.js app, the smallest limit in the chain answers, with its own status code. One cookie line over 8 KB: nginx answers 400 and Node never sees the request. Headers of 20 KB spread over lines that each fit in 8 KB: nginx passes them on, Node.js refuses with 431, and nginx hands that 431 to the browser. Raise both, and keep Node’s limit at least as large as what nginx lets through:
large_client_header_buffers 4 16k;sudo nginx -t && sudo systemctl reload nginxSet it in the http block. Set only inside one server block, nginx may use the default server’s value for connections on that address, and the change seems to do nothing. To tell who answered, look at the response: nginx’s 400 page is a short HTML page that carries nginx (often with its version) in the footer, while Node’s 431 has no body and no Server header. If you are setting up the proxy itself, the nginx reverse proxy guide has the full server block.
Apache: 400 “Size of a request header field exceeds server limit”
Apache httpd also answers oversized headers with 400, not 431, and says why on the page: Size of a request header field exceeds server limit. The limits are LimitRequestFieldSize (8,190 bytes per header field), LimitRequestFields (100 fields) and LimitRequestLine (8,190 bytes for the method and URL). Apache’s own documentation points out that SPNEGO (Kerberos) authentication headers alone can reach 12,392 bytes, so Windows domain logins (Kerberos) can trip the limit on their own.
LimitRequestFieldSize 16380
LimitRequestLine 16380sudo apachectl configtest && sudo systemctl reload apache2Put the directives in the main server config. With name-based virtual hosts Apache takes the value from the first virtual host for that IP address and port, so a line inside a later VirtualHost is silently ignored. Apache in front of Node.js with mod_proxy behaves like the nginx chain above: whichever limit is smaller answers.
Behind Cloudflare
Cloudflare raised its request header limit to 128 KB in total in October 2025; before that it was 32 KB in total and 16 KB per header, the figures many older guides still quote. Its changelog says requests over the limit get a 413. We sent growing cookies to our own Cloudflare-proxied site over HTTP/1.1: a 100 KB cookie passed the edge, and at 140 KB the connection was reset without any status page. Either way, 128 KB is far above what nginx, Apache or Node.js accept by default, so a 431 on a site behind Cloudflare almost always comes from your origin. Check the response: the server: cloudflare header is set on everything the edge relays, so look at the body and your origin’s logs to find who refused.
The opposite direction has its own error. When your origin sends response headers that are too big, for example dozens of Set-Cookie lines, Cloudflare shows error 520 instead.
Stop 431 from coming back: shrink the cookies
Raising a limit buys time; small headers fix the cause. On your own application:
- Keep a session ID in the cookie, not the session. Store user data, carts and feature flags on the server, keyed by a short ID. A JWT that gains a claim for every role or setting is the typical cookie that grows until it breaks.
- Scope cookies tightly. A cookie set with
Domain=example.comgoes to every subdomain; leave outDomainto keep it on one host, and set aPathwhere only part of the site needs it. - Expire what nobody reads. Give every cookie a
Max-Ageand remove cookies of features you retired by setting them again withMax-Age=0. - Audit third-party tags. Analytics, A/B testing and consent tools each add cookies on your domain. List them in the developer tools (Application tab, Cookies) and sort by size.
- Watch cross-origin calls. A 431 from your API carries no
Access-Control-Allow-Originheader, so the browser reports it as a CORS error and hides the real status. Check the Network tab before you touch your CORS settings.
Symptom, cause, fix
Symptom: Chrome: “This page isn’t working”, HTTP ERROR 431
- Cause
- The cookies stored for that site are larger than the server accepts.
- Fix
- Open the page in incognito; if it loads, delete that one site's cookies and reload.
Symptom: 431 from your dev server on
localhost- Cause
- Cookies from every app you ran on localhost, on any port, exceed Node's 16 KB.
- Fix
- Clear site data for localhost, or start the server with
NODE_OPTIONS='--max-http-header-size=32768'.
Symptom: 400 Request Header Or Cookie Too Large from nginx
- Cause
- One header line is over 8 KB, nginx's buffer size.
- Fix
nginx.conf · http block large_client_header_buffers 4 16k;
Symptom: Still 431 after raising nginx's buffers
- Cause
- The app behind nginx (Node.js) has the smaller limit and answers first.
- Fix
- Raise Node too:
node --max-http-header-size=32768 server.js.
Symptom: Spring Boot or Tomcat: 400, log says Request header is too large
- Cause
- Tomcat's 8 KB limit for the request line and headers was exceeded.
- Fix
- Set
server.max-http-request-header-size=16KB(Spring Boot) ormaxHttpHeaderSizeon the Connector.
Symptom: 400: Size of a request header field exceeds server limit
- Cause
- Apache's LimitRequestFieldSize (8,190 bytes) was exceeded, often by Kerberos tokens.
- Fix
- Set
LimitRequestFieldSize 16380in the main server config and reload.
A 431 is one of several 4xx answers that are about the request rather than the page. If the server accepts the headers but refuses the HTTP method, you get 405 Method Not Allowed.
On your own server you control every limit in the chain. On a Standard KVM with root access you set nginx’s buffers and the Node.js flag yourself, and the Node.js install is covered in how to install Node.js.
How we tested
- OS image
- Debian 12
- Versions
- Node.js 26.12.1curl 7.88.1Python 3.11.2
- Tested on
- Where
- Test servers bound to 127.0.0.1 on our own Linux host; the Cloudflare check against vmheaven.io
- Method
- Default, flag, NODE_OPTIONS and maxHeaderSize servers hit with growing Cookie headers from curl; thresholds found by bisection
Frequently asked
What does HTTP error 431 mean?
431 Request Header Fields Too Large means the server refused the request because its headers, all together or one single header, are bigger than it accepts. The oversized header is usually Cookie: too many or too large cookies stored for that site. The page and the server are fine; a request with smaller headers goes through.
How do I fix HTTP error 431 in Chrome?
Open the page in an incognito window. If it loads there, sign out and sign in again, or delete the cookies of that one site through the icon to the left of the address bar (or chrome://settings/content/all) and reload. If you arrived through a very long link, open the plain address without the query string. If incognito fails too, only the site's operator can fix it.
Why do I get error 431 on localhost?
Your dev server runs on Node.js, which refuses more than 16 KB of request headers by default, and cookies are not separated by port: every app you ever ran on localhost sends its cookies to every other one. Clear the site data for localhost, or start the server with NODE_OPTIONS='--max-http-header-size=32768'. If it happens with no cookies at all, check for a dev-server proxy that forwards to itself.
How do I increase the max header size in Node.js?
Start Node with --max-http-header-size=32768 (bytes), set the same flag in NODE_OPTIONS for tools like next dev or vite, or pass { maxHeaderSize: 32768 } to http.createServer for one server. The default has been 16,384 bytes since Node 13.13.0. Check the active value with: node -p "require('http').maxHeaderSize".
Is 431 the same as 400 Request Header Or Cookie Too Large?
Same problem, different server. nginx and Apache answer oversized headers with 400 (nginx with the message Request Header Or Cookie Too Large) and never send 431, and so do Tomcat (the default server of Spring Boot) and IIS. Node.js, ASP.NET Core Kestrel, Jetty, Go and Python's http.server send 431. Behind a reverse proxy, the smallest limit in the chain answers, so raise nginx's large_client_header_buffers and the app server's limit together.