How to Fix Nginx 413 Request Entity Too Large: Complete Guide
A 413 Request Entity Too Large response from Nginx means the server refused to process a request because the body the client sent was bigger than the maximum Nginx is configured to accept. The upload or POST never reaches your application — Nginx rejects it at the front door.
This threshold is controlled by a single directive: client_max_body_size. Out of the box, Nginx ships with a default of 1 megabyte, which is fine for ordinary form submissions and API calls but far too small for media uploads, theme archives, database imports, or large JSON payloads. The good news is that the fix is almost always a one-line configuration change — provided you also align the limits on every layer in the stack: Nginx, PHP, and your application.
What is Nginx 413 Request Entity Too Large?
HTTP 413 is a client error status code defined in RFC 9110 as 413 Content Too Large (Nginx still uses the legacy reason phrase Request Entity Too Large). Nginx returns it the moment the incoming request body — including form data, file uploads, or JSON — exceeds the value of client_max_body_size. Crucially, Nginx checks this size as it buffers the request, so a 413 can be returned before the request ever reaches PHP-FPM, Node.js, or your upstream application.
Because the check happens at the Nginx layer, you will typically see a plain 413 page or an empty response rather than an application-level error. In the Nginx error log the offending request shows up with the message client intended to send too large body, which is the definitive signature of this issue.
Common Causes
- Default 1 MB limit:
client_max_body_sizedefaults to1m. Any single upload larger than one megabyte is rejected. - Large file uploads: Media libraries, theme ZIPs, and database imports easily exceed the default.
- PHP limits not aligned:
upload_max_filesizeandpost_max_sizeinphp.iniare smaller than the Nginx limit (or vice versa), so the request is blocked at one layer even after the other is raised. - WordPress media upload: The Add New Media screen enforces its own limit derived from the smallest of the Nginx and PHP settings.
- Reverse proxy not forwarding size: A front-end Nginx proxy has its own
client_max_body_sizethat was never raised, so it rejects the body before it reaches the backend. - Client body buffered to disk: When
client_body_buffer_sizeis exceeded, large bodies are written to a temp file; if the temp path is full or the absolute size cap is hit, a 413 follows.
Step-by-Step Fix Guide
Follow these six steps in order. They move from locating the right file, through raising the limit at the right scope, to aligning PHP and any reverse proxy, and finally verifying the result.
Step 1: Locate the active Nginx configuration file
Before editing anything, find the file Nginx actually loads. Settings can live in nginx.conf, a site file under sites-enabled, or a conf.d include. Editing the wrong file is the single most common reason a fix "does not work".
# Print the full compiled configuration and search for the directive
sudo nginx -T 2>/dev/null | grep -n client_max_body_size
# Common locations to check
ls -la /etc/nginx/nginx.conf
ls -la /etc/nginx/conf.d/
ls -la /etc/nginx/sites-enabled/
Step 2: Increase client_max_body_size in the http block
Open nginx.conf and set the directive inside the http block so it applies globally. Choose a value that covers your largest expected upload.
# /etc/nginx/nginx.conf
http {
# Allow uploads up to 64 MB
client_max_body_size 64m;
# ... rest of your http config
}
A value of 64m covers most media uploads. Use 128m or higher for video or backups. Avoid 0 (unlimited) in production — it leaves you with no protection against abusive requests that could exhaust memory or fill the disk.
Step 3: Apply the limit per server or location
For tighter control, set client_max_body_size only where uploads happen, such as a dedicated upload location. A location-level value overrides the http-level one, so you can keep a small global default while permitting large bodies on a single endpoint.
server {
listen 80;
server_name example.com;
# Global default for this site
client_max_body_size 32m;
location /upload {
# Only this endpoint accepts large files
client_max_body_size 256m;
proxy_pass http://backend;
}
}
Step 4: Align PHP upload limits
If Nginx forwards the request to PHP-FPM, PHP enforces its own caps. Raise both upload_max_filesize and post_max_size so they meet or exceed the Nginx limit. post_max_size must be the larger of the two because it covers the whole POST body, not a single file.
# Find the php.ini the FPM process actually loads
php -i | grep "Loaded Configuration File"
# Edit the FPM ini (CLI and FPM use separate files)
sudo nano /etc/php/8.2/fpm/php.ini
; /etc/php/8.2/fpm/php.ini
upload_max_filesize = 64M
post_max_size = 128M
memory_limit = 256M
max_execution_time = 300
# Apply the PHP changes
sudo systemctl restart php8.2-fpm
Step 5: Configure the reverse proxy to forward large bodies
When Nginx sits in front of another Nginx or app server, the proxying server applies its own client_max_body_size. If only the backend was raised, the front proxy still returns 413. Set the limit on the proxy and let it pass the body through.
# Front-end proxy server
server {
listen 443 ssl;
server_name example.com;
# Match the backend capacity
client_max_body_size 64m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_request_buffering on;
}
}
Step 6: Test the configuration and reload Nginx
Always validate before reloading so a typo does not take the site offline. Then reload gracefully and verify with a real upload.
# Validate syntax
sudo nginx -t
# Reload without dropping connections
sudo nginx -s reload
# Verify a large POST succeeds (replace with your endpoint)
curl -v -X POST -F "file=@large-file.zip" https://example.com/upload
Expect HTTP/1.1 200 OK. If you still see 413, recheck that you edited the file Nginx actually loads (Step 1) and that no more specific server or location block overrides your value.
Nginx Diagnostic Commands
These commands help confirm the running limit and reproduce the 413 so you know which layer is rejecting the request.
# Show the effective client_max_body_size from the loaded config
sudo nginx -T 2>/dev/null | grep -i client_max_body_size
# Confirm which config path Nginx uses
sudo nginx -V 2>&1 | grep -o '\-\-conf-path=[^ ]*'
# Watch the error log while you trigger an upload
sudo tail -f /var/log/nginx/error.log
# Reproduce the 413 with a body larger than the default 1 MB
curl -v -X POST -d "$(head -c 2000000 /dev/zero | tr '\0' 'a')" \
-H "Content-Type: application/octet-stream" \
http://localhost/upload
# Check PHP's effective limits from the CLI
php -i | grep -E "upload_max_filesize|post_max_size|memory_limit"
You should see client intended to send too large body in the error log at the exact moment of the 413, which confirms Nginx — not PHP — is the rejecting layer. If instead the PHP log reports PostExceededSize, the limit needs to be raised in php.ini.
Quick Reference Table
| Symptom | Cause | Fix |
|---|---|---|
| 413 on any upload over 1 MB | Default client_max_body_size is 1m |
Set client_max_body_size 64m in the http block |
| 413 only in WordPress media upload | PHP upload_max_filesize smaller than Nginx limit |
Raise upload_max_filesize and post_max_size in php.ini, restart PHP-FPM |
| 413 behind a reverse proxy | Front proxy keeps the small default | Set client_max_body_size on the proxying server too |
| 413 on JSON API but not forms | JSON body exceeds the 1 MB default | Raise client_max_body_size for the API location |
Log: client intended to send too large body |
Nginx blocked the request at the buffer stage | Confirm with nginx -T and increase the limit |
PHP log reports PostExceededSize |
PHP cap below Nginx cap | Set post_max_size larger than upload_max_filesize |
Pro tip: If you use Cloudflare in front of Nginx, remember that Cloudflare also enforces a maximum upload size per plan (100 MB on the free tier). A 413 from Cloudflare will not appear in your Nginx log, so check the response headers — a Server: cloudflare header points back to the CDN layer.
FAQ
What is the default client_max_body_size in Nginx?
The default is 1 megabyte (1m). Any single request body larger than one megabyte is rejected with a 413 unless you raise the directive. This default is safe but too small for almost any modern upload workflow.
Should I set client_max_body_size to 0 for unlimited?
It is possible — a value of 0 disables the check — but it is not recommended in production. With no limit, a single oversized request can exhaust memory or fill the disk with buffered bodies. Pick an explicit ceiling based on your largest legitimate upload.
Why do I still get 413 after raising client_max_body_size?
The most common reasons are editing the wrong file (check with nginx -T), a more specific server or location block overriding the http-level value, or a front-end reverse proxy that still uses the 1 MB default. Reload with nginx -s reload and confirm the effective value with the diagnostic commands above.
Does client_max_body_size affect GET requests?
client_max_body_size applies to any request with a body. GET requests normally carry no body, so the directive rarely affects them, but it does apply to POST, PUT, and PATCH — the methods used for uploads. A large GET with a body is unusual and usually indicates a misbehaving client.
Conclusion
The 413 Request Entity Too Large error is one of the easiest Nginx problems to solve once you understand that a single directive — client_max_body_size — controls the threshold. Raise it to match your real upload needs, align PHP's upload_max_filesize and post_max_size, and remember to set the same limit on any reverse proxy in the path. Validate with nginx -t, reload gracefully, and confirm with curl. With those four habits, 413 stops being a recurring incident and becomes a one-time configuration task.