How to Fix 413 Request Entity Too Large on Nginx and PHP
In this article8 sections
A 413 Request Entity Too Large error means the server refused the upload before your application even saw it. You will see it when a WordPress media upload, a form with a file field, or an API call with a big body fails. The fix is simple once you know which layer rejected the request. A typical stack has three size limits in a row: the web server, PHP, and the application. A file has to pass all three, so raising only one often changes nothing. This guide shows how to find the layer that rejected the request and how to raise each limit safely.
What the error means and where it comes from
The status code is generated by the web server, not by PHP or WordPress. Nginx returns the 413 page itself, and Apache does too, with the same meaning. If PHP rejects an upload because it is too large, the usual symptom is a blank page, a warning, or a generic upload failure, not a 413. So the first step is to look at the server’s own log.
Step 1: Confirm which layer rejected the request
Check the Nginx error log for the request. Nginx logs a 413 with the message client intended to send too large body:
sudo grep "too large" /var/log/nginx/error.log | tail -5
If the log shows that message, the web server rejected the upload, and you start with Step 2. If the error log is silent but the page still shows a 413, check the Apache log instead:
sudo tail -20 /var/log/apache2/error.log
If neither log shows the error, and the upload fails with a blank page or a “failed to upload” message, the rejection happened in PHP or in the application. Then go to Step 3.
Step 2: Raise the web server limit
Nginx
Nginx limits the request body with client_max_body_size. Its default is 1 MB, which is why most uploads over 1 MB fail. The directive can be set in the http, server or location block. Set it in the site’s server block, and raise it only for the paths that really need it:
server {
server_name example.com;
root /var/www/example;
client_max_body_size 64m;
location /upload/ {
client_max_body_size 256m;
}
}
Setting the value to 0 turns the check off completely. Do not do that on a public site, because it removes the protection against oversized requests. Choose the largest file you really accept and set that number.
Test the configuration, then reload:
sudo nginx -t && sudo systemctl reload nginx
Expected: syntax is ok and test is successful, then the reload finishes with no output.
Apache
Apache limits the request body with LimitRequestBody, which is set in the virtual host or a directory block. Its default is large, so Apache rarely causes a 413 unless someone has lowered the value. Check the directive page for your Apache version before setting a value, and set it in the site’s virtual host:
<VirtualHost *:443>
ServerName example.com
LimitRequestBody 67108864
</VirtualHost>
The value is in bytes, so 67108864 is 64 MB. Reload Apache with sudo apache2ctl configtest && sudo systemctl reload apache2.
Step 3: Raise the PHP limits
PHP has two limits that matter for uploads, and both must allow the file:
upload_max_filesizeis the largest single file. Its default is 2 MB.post_max_sizeis the largest whole request body, including all the fields and files in a form. Its default is 8 MB.
The PHP manual states that post_max_size must be larger than upload_max_filesize, because the file is part of the request. Keep memory_limit larger than post_max_size as well. A common working set for a site that takes files up to 64 MB is:
upload_max_filesize = 64M
post_max_size = 72M
max_file_uploads = 20
memory_limit = 256M
Find the file that PHP is actually reading for the workers that serve your site, because the command-line and web settings can differ:
php -i | grep -E "upload_max_filesize|post_max_size"
sudo grep -nE "^\s*(upload_max_filesize|post_max_size|memory_limit)" /etc/php/8.4/fpm/php.ini
Edit the fpm/php.ini file for PHP-FPM, then restart the service. Editing the cli/php.ini file changes only the command line, so the browser upload keeps failing:
sudo systemctl restart php8.4-fpm
On PHP-FPM, a pool can also set these values with php_admin_value in its file under /etc/php/8.4/fpm/pool.d/. If a value is set there, it overrides php.ini, so check the pool files when a change seems to have no effect.
Step 4: Check the application
Some applications set their own limit, separate from the server and PHP. WordPress shows the effective maximum on the Media Library upload screen, and it takes the smallest of the server and PHP limits. A plugin can lower that further. If the upload screen shows the size you configured but the upload still fails, check the plugin list and the application’s settings.
Applications that accept large files through an API often have their own body limit as well. The n8n webhook case, for example, has a second limit beyond Nginx. The steps are in how to fix n8n webhooks behind Nginx.
Step 5: Test with a real file
Test with a file just under your new limit, then one just over it. A small file that passes does not prove the large one will. The expected result for the file under the limit is a successful upload. For the file over the limit, expect a clear error at the application, not a blank page.
To test the web server limit without using the browser, send a request body of a known size with curl:
dd if=/dev/zero of=/tmp/test-50mb.bin bs=1M count=50
curl -s -o /dev/null -w "%{http_code}\n" -F "file=@/tmp/test-50mb.bin" https://example.com/upload-test/
Expected: the status code is the one your application returns for a successful upload, not 413. Replace the path with a real upload endpoint on your site, and delete the test file afterwards with rm /tmp/test-50mb.bin.
Common mistakes
- Raising only
upload_max_filesize.post_max_sizestill rejects the request, which is the most common cause of a silent failure. - Editing the CLI
php.ini. The web workers read the FPM file, so the browser behaves as before. - Forgetting to restart PHP-FPM. PHP reads these values at startup, so a change has no effect until the service restarts.
- Setting every limit to a very large value. A large limit lets one client tie up memory and disk for every request. Keep the limit for the paths that need it, and keep the default everywhere else.
- Setting
client_max_body_size 0on a public site. It removes the protection entirely.
Once the upload limit is correct, a large upload can still fail further along the request with a timeout. If that happens, read how to fix 504 Gateway Timeout on Nginx. For the wider Nginx settings a busy site needs, see how to tune Nginx for a high-traffic website.
Frequently asked questions
Why does the upload fail at a size I already raised?
Most often one of the other limits is still at its default. Check every layer in the order of Steps 2 to 4, and check the PHP-FPM pool files as well as php.ini.
Does the 413 error appear in the PHP log?
Not usually. It is generated by the web server, so the Nginx or Apache error log is the place to look.
Is it safe to allow very large uploads?
It is safe when the upload path is limited to the users who need it, and the files are checked after upload. Large limits on a public form are a common route for abuse, so keep them specific.
Does this also apply to Cloudflare?
Yes. A proxy such as Cloudflare has its own request body limits, which depend on the plan. If the error appears before it reaches your server, check the proxy’s limit and its documentation.
A 413 error is a size limit doing its job, at the layer that rejected the request. Find that layer in the logs, raise its limit for the paths that need it, and restart the service that enforces it. Then test the upload with a file that is just over the old limit.