Fix 413 Request Entity Too Large on Nginx and Apache
Updated 5 November 2026 · By Brent Alexis
Short answer: a 413 Request Entity Too Large means an upload was bigger than a size limit somewhere between the visitor and your app. On Nginx it's almost always client_max_body_size, which defaults to just 1 MB: set it in the server block, for example client_max_body_size 64m;, then test and reload. For WordPress and other PHP sites, raise PHP's upload_max_filesize and post_max_size too, because PHP rejects big uploads without a 413.
Every Nginx, PHP and Apache case on this page was reproduced in the lab: the official nginx Docker image (Nginx 1.30.6) in front of a test app, Debian 12's packages (Nginx 1.22.1, PHP 8.2.35) with ProxyForge's WordPress output, and the official Apache image (2.4.68) with a reverse proxy and a local CGI script: 45 checks. The Cloudflare limits come from Cloudflare's documentation. How it's tested
- Which limit refused it?
- Nginx: client_max_body_size
- PHP and WordPress: no 413, just an empty upload
- Apache: LimitRequestBody
- Cloudflare: 100 MB on Free and Pro
- Check the fix
Which limit refused it?
Every layer has its own limit, and the first one that's too small wins. The response usually tells you which layer it was:
| Layer | Default limit | What you see |
|---|---|---|
| Cloudflare (proxied site) | 100 MB on Free and Pro | A 413 page from Cloudflare, before your server sees anything |
| Nginx | 1 MB | A plain 413 page with nginx at the bottom, and a line in the Nginx error log |
| Apache | 1 GB (2.4.54 and newer) | An Apache 413 page, but only for requests Apache handles itself (in our lab, not for a reverse proxy) |
| PHP | 2 MB per file, 8 MB per request | No 413: the upload arrives with an error or empty, and the page loads normally |
| Your app | Varies by framework | Whatever error the app returns or logs |
Nginx: client_max_body_size
Nginx refuses any request body over 1 MB unless you raise client_max_body_size. The error log says:
[error] 52#52: *3 client intended to send too large body: 1100000 bytes
Fix: set it in the server block of the site, then test and reload:
server {
# ...
client_max_body_size 64m;
}
sudo nginx -t && sudo systemctl reload nginx
- Put it in the
serverblock, not onelocation. In the lab,client_max_body_size 10minsidelocation /let a 2 MB upload to/through, but a 2 MB upload to/api/upload, which had its ownlocation, got a 413: that location was still on the 1 MB default. Moving the line up to theserverblock fixed it. client_max_body_size 0;turns the limit off. In the lab a 20 MB upload went through with it. Better to pick a number a bit above your largest real upload.- Chunked uploads count too. An upload sent without a
Content-Lengthheader (chunked) got the same 413 once it passed the limit. - In the Config Generator, the Max upload size field sets it for a reverse proxy, WordPress or a PHP-FPM app. It puts the line inside
location /for a reverse proxy and in theserverblock for WordPress and PHP-FPM. Until 5 November 2026 the WordPress and PHP-FPM output had no upload line at all, so uploads over 1 MB failed with a 413. If you generated one of those before then, addclient_max_body_sizeto itsserverblock.
PHP and WordPress: no 413, just an empty upload
Once Nginx lets the upload through, PHP applies its own two limits. Their defaults are small, and neither gives a 413:
| Setting | Default | Over the limit |
|---|---|---|
upload_max_filesize | 2M | The upload reaches PHP, but PHP drops the file and sets error 1 (UPLOAD_ERR_INI_SIZE). The page still returns 200. |
post_max_size | 8M | PHP drops the whole request body: no file and no form fields at all. Still a 200. |
For the second one, the Nginx error log gets a line from PHP:
[error] 6870#6870: *9 FastCGI sent in stderr: "PHP message: PHP Warning: POST Content-Length of 9000209 bytes exceeds the limit of 8388608 bytes in Unknown on line 0" while reading response header from upstream
Fix: raise both, keeping post_max_size at least as big as upload_max_filesize, and keep Nginx's client_max_body_size at or above them. For a PHP-FPM pool, add these lines to its pool file (/etc/php/8.X/fpm/pool.d/www.conf on Debian and Ubuntu, /etc/php-fpm.d/www.conf on RHEL), or set the same values in php.ini:
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M
Then restart PHP-FPM (for example sudo systemctl restart php8.2-fpm, or php-fpm on RHEL). Check the values PHP-FPM is really using with php-fpm8.2 -i | grep -E "upload_max_filesize|post_max_size": the php command on the terminal can read a different php.ini than PHP-FPM. Checked on Debian 12 (PHP 8.2.35) with Nginx at 10 MB: with PHP's defaults a 1.5 MB upload worked, a 3 MB file came through as error 1 and a 9 MB upload arrived empty. After adding the two pool lines and restarting PHP-FPM, the 9 MB upload went through.
WordPress shows PHP's message for the first case: "The uploaded file exceeds the upload_max_filesize directive in php.ini."
Apache: LimitRequestBody
Since Apache 2.4.54, LimitRequestBody defaults to 1 GB (before that it was unlimited). Set it lower in the server config, a virtual host or a <Location>, in bytes:
LimitRequestBody 10485760
In our lab on Apache 2.4.68, LimitRequestBody 10485760 stopped an 11 MB upload to a script Apache runs itself (a CGI script) with a 413, wherever it was set: server config, virtual host or <Location>. At Apache's default log level nothing about the limit reaches the error log; the CGI script only logged AH01270: Error reading request entity data. To see the reason, set LogLevel info for a while. Then the error log says:
AH01588: Requested content-length of 11000000 is larger than the configured limit of 10485760
Put LogLevel back to warn afterwards, because info logs a lot.
It didn't limit a reverse proxy. In the same lab, an 11 MB upload to an app behind ProxyPass went through in all three places, with or without a Content-Length header, and a request announcing 2 GB got no 413 either: Apache just waited for the body. Apache's source code used to say so, in a comment reading "LimitRequestBody does not affect Proxy requests". That comment and the matching documentation note were removed in 2.4.54, when the 1 GB default arrived, but proxied uploads still weren't limited in our test. So for a reverse proxy, set the limit in the app itself, or put Nginx in front with client_max_body_size.
On shared hosting where you only have .htaccess, the limit you'll hit is usually PHP's, not Apache's. The host's control panel often has a PHP settings page for upload_max_filesize and post_max_size.
Cloudflare: 100 MB on Free and Pro
If your site is proxied through Cloudflare (orange cloud), Cloudflare refuses uploads over 100 MB on the Free and Pro plans and 200 MB on Business. Enterprise starts at 500 MB and can be raised to 5 GB from the zone's Network page (source: Cloudflare's 413 page, checked 5 November 2026). Your server never sees those requests, so no Nginx or Apache setting helps. Options are to upload in smaller chunks, send uploads to a hostname that isn't proxied (DNS only), or move to a bigger plan. This part isn't lab-tested.
Check the fix
Upload a file a little bigger than the old limit through your real upload form, then look at the response and the logs:
sudo tail -n 5 /var/log/nginx/error.log
No new client intended to send too large body line means Nginx let it through. If the upload still fails without a 413, the limit is in PHP or the app. If a config change seems to do nothing, check the reload applied: see nginx -s reload said OK, but my change didn't apply.
Generate a config with the upload size you need →
How to use ProxyForge · FAQ: common errors · Guides · What's new · About