< HTTP/1.1 413 Content Too Large413 Payload Too Large (Content Too Large): Causes and Fixes
413 Content Too Large (formerly Payload Too Large): find which layer rejected the upload and raise the limit in nginx, Apache, Cloudflare, Express and more.
- Cacheable
- Only with explicit freshness
- Retry?
- No: send a smaller body
- Usually sent by
- Reverse proxy, CDN or origin
- Often confused with
- 414
On this page
TL;DR: Some layer between the client and your app (nginx, a CDN, an API gateway or the framework’s body parser) rejected the body for being over its size cap. Find which layer answered, then raise the limit there, or send the file by another route such as chunking or a presigned URL.
What it means
The request was syntactically fine, but its body (the “content” in RFC 9110 terms) exceeded what the server will accept. The server may close the connection to stop the client from sending the rest. Because every hop has its own default limit, raising the limit in one place often just moves the 413 to the next hop.
HTTP/1.1 413 Request Entity Too Large
Server: nginx/1.25.5
Content-Type: text/html
Content-Length: 183
Connection: close
nginx still emits the pre-RFC 9110 phrase, and its error log says exactly what happened:
2026/10/04 09:12:41 [error] 31#31: *874 client intended to send too large body: 5242880 bytes, client: 203.0.113.9, server: example.com, request: "POST /upload HTTP/1.1", host: "example.com"
Who sent it?
| Signal | Likely sender |
|---|---|
Server: nginx and the log line above | nginx (or ingress-nginx in Kubernetes) |
Server: cloudflare plus CF-Ray | Cloudflare, plan limit exceeded |
{"message":"Request Entity Too Large"} with an x-amzn-ErrorType header | API Gateway |
PayloadTooLargeError: request entity too large in the app log | Express body-parser / express.json() |
FUNCTION_PAYLOAD_TOO_LARGE in the body, X-Vercel-Error header | Vercel (4.5 MB request cap on functions) |
Plain Request Entity Too Large page, Server: Apache | Apache LimitRequestBody, or PHP limits |
Reproduce and see who answers. curl sends Expect: 100-continue for large POST bodies on HTTP/1.1, and nginx answers 413 before the body is uploaded, which is the fast way to confirm:
head -c 5M /dev/zero > big.bin
curl -sv -o /dev/null -X POST --data-binary @big.bin https://example.com/upload 2>&1 | grep -iE '^[<>] (POST|HTTP|server|cf-ray|via|expect)'
Fix it by stack
nginx
Default is 1m. Set it where the request lands (http, server or location), then nginx -t && nginx -s reload:
server {
client_max_body_size 50m;
location /upload {
client_max_body_size 500m;
proxy_request_buffering off; # stream to the upstream instead of buffering to disk
proxy_pass http://app;
}
}
client_max_body_size 0; disables the check entirely, which is rarely what you want on a public endpoint.
ingress-nginx (Kubernetes)
The ingress controller enforces its own limit before traffic reaches your pod. Per Ingress:
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
Or cluster-wide with proxy-body-size in the controller ConfigMap. If you also run nginx inside the pod, raise that one too.
Apache and PHP
LimitRequestBody defaults to 0 (unlimited); the maximum is 2147483647. If you did not set it, the cap is probably PHP’s:
LimitRequestBody 52428800
; php.ini: post_max_size must be >= upload_max_filesize
upload_max_filesize = 50M
post_max_size = 55M
Express, Node and Go
express.json() and express.urlencoded() default to 100kb. The error is PayloadTooLargeError: request entity too large with err.status === 413:
app.use(express.json({ limit: '2mb' }))
For file uploads use a streaming parser (multer with limits.fileSize, busboy) instead of raising the JSON limit. In Go, wrap the body with http.MaxBytesReader(w, r.Body, 10<<20); reads past the limit fail with http: request body too large and you choose the status code.
Next.js, Vercel, Django
- Next.js Pages Router API routes:
export const config = { api: { bodyParser: { sizeLimit: '4mb' } } }. Server Actions default to 1 MB and are raised withserverActions.bodySizeLimitinnext.config. - Vercel functions reject request bodies over 4.5 MB regardless of your code. Upload directly to blob storage with a presigned or client-upload token.
- Django enforces
DATA_UPLOAD_MAX_MEMORY_SIZE(2.5 MB, file parts excluded) and raisesRequestDataTooBig, which Django turns into a 400, not a 413.
Cloudflare and cloud gateways
- Cloudflare proxy: 100 MB (Free, Pro), 200 MB (Business), 500 MB (Enterprise) by default. A DNS-only (grey cloud) record bypasses it.
- API Gateway: 10 MB payload limit. Lambda synchronous invocation payloads cap at 6 MB, and an ALB with a Lambda target at 1 MB.
- ALB to an instance or container target: the ALB does not impose a body size limit, so a 413 behind an ALB comes from your own stack.
For anything above a few MB, upload straight to object storage (S3 presigned PUT or multipart, GCS resumable) and send only the object key to your API.
Related codes
- 400 Bad Request: malformed request, not merely large.
- 414 URI Too Long: the target URI is oversized, not the body.
- 431 Request Header Fields Too Large: the headers or cookies are oversized.
- 408 Request Timeout: a slow upload can die this way instead.
- 415 Unsupported Media Type: wrong format rather than wrong size.
Frequently asked questions
What does 413 Content Too Large mean?
The server, or a proxy in front of it, refused the request because the body is larger than it is willing to process. RFC 9110 renamed the code from "Payload Too Large" (and the older "Request Entity Too Large") to "Content Too Large"; the number did not change, and nginx still prints the old text.
How do I fix nginx 413 Request Entity Too Large?
Set client_max_body_size in the http, server or location block, for example client_max_body_size 50m;, then run nginx -t and reload. The default is 1m. If nginx sits behind another proxy or in Kubernetes, that layer has its own limit too.
What is the upload limit for Cloudflare?
Cloudflare accepts request bodies up to 100 MB on Free and Pro, 200 MB on Business and 500 MB on Enterprise by default. Larger uploads must bypass the proxy, use chunked or multipart upload to object storage, or use a presigned URL.
Does Apache LimitRequestBody default to 2 GB?
No. LimitRequestBody defaults to 0, which means unlimited. 2147483647 bytes (2 GB) is the maximum value you can set. If Apache returns 413, someone configured the directive, or PHP (upload_max_filesize, post_max_size) rejected the file instead.
Should a 413 response include Retry-After?
Only if the limit is temporary, for example a quota that resets. RFC 9110 says a server that knows the condition is temporary should send Retry-After. For a fixed size cap the client must send less data, not wait.
Sources
Related
400 Bad Request
400 Bad Request means the server could not parse your request. Find which layer sent it, fix bad JSON and oversized cookies or headers, and reproduce with curl.
405 Method Not Allowed
405 Method Not Allowed means the URL exists but not for that method. Read the Allow header, then fix redirects turning POST into GET, static hosting and WAFs.
406 Not Acceptable
The server cannot produce a response matching the client's Accept headers. Learn about content negotiation and how to handle format mismatches.
408 Request Timeout
408 Request Timeout means the server gave up waiting for the client to finish sending. Tune nginx, Apache, Node and ALB timeouts and tell it apart from 504.