Skip to main content
DevOpsbeginner

Fix "413 Request Entity Too Large" in Nginx

Fix nginx 413 Request Entity Too Large by raising client_max_body_size, which defaults to just 1 MB. Covers PHP-FPM limits, chained proxies, Kubernetes ingress, and how to verify the new limit.

8 min readUpdated August 2026

Nginx returns 413 Request Entity Too Large when an upload exceeds client_max_body_size — and the default is only 1 MB, small enough that one photo from a phone can trip it.

413 Request Entity Too Large
nginx/1.24.0

The matching line in /var/log/nginx/error.log:

client intended to send too large body: 4823910 bytes, client: 203.0.113.9,
  server: example.com, request: "POST /upload HTTP/1.1"

That number is the size the client tried to send. Set your limit above it.


The Fix

Add client_max_body_size to your nginx config:

http {
    client_max_body_size 50m;
    ...
}

Then test and reload:

sudo nginx -t
sudo systemctl reload nginx

Always run nginx -t first. If the config has a syntax error, reload fails and nginx quietly keeps serving the old config — so you would be testing a change that never applied.

Where to put it

The directive is valid in three contexts, and the choice matters:

ContextEffectWhen to use
httpEvery site on the serverSimple single-purpose servers
serverOne virtual hostOne site needs larger uploads
locationOne path onlySafest — raise it just for the upload endpoint

Scoping it to a location is the better habit:

server {
    server_name example.com;

    client_max_body_size 1m;          # default for the whole site

    location /api/upload {
        client_max_body_size 200m;    # only this endpoint accepts large files
        proxy_pass http://127.0.0.1:3000;
    }
}

That way an attacker cannot POST a 200 MB body to your login form.

Which file to edit

DistributionMain configSite configs
Debian / Ubuntu/etc/nginx/nginx.conf/etc/nginx/sites-available/
RHEL / Rocky / AlmaLinux/etc/nginx/nginx.conf/etc/nginx/conf.d/*.conf

If you are unsure which files nginx actually loads, ask it:

sudo nginx -T | grep -n "client_max_body_size"

nginx -T dumps the fully resolved configuration including every include. If your directive does not appear there, nginx is not reading the file you edited — the single most common reason "I already set it" fails.


Still 413 After Raising the Limit?

Another proxy is enforcing a smaller limit

Every layer between the client and your application enforces its own maximum. Raising it on one does nothing if a stricter one sits in front:

browser → CDN → load balancer (nginx) → app server (nginx) → application

Each hop needs the higher limit. A CDN in front of you may cap uploads by plan tier regardless of your configuration — check your provider's limits before spending an hour on nginx.

Advertisement

PHP has its own limits

Nginx accepting the body does not mean PHP will. In php.ini:

upload_max_filesize = 50M
post_max_size = 55M

Set post_max_size slightly above upload_max_filesize, because the POST body includes form fields and multipart overhead in addition to the file itself. Both must be at least as large as the nginx limit. Then restart PHP-FPM — reloading nginx does nothing here:

sudo systemctl restart php8.3-fpm
php -i | grep -E "upload_max_filesize|post_max_size"

Kubernetes ingress-nginx

Do not edit nginx.conf inside the controller pod; it is regenerated and your change disappears. Use the annotation:

metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"

The application enforces its own cap

Express (body-parser limit), Django (DATA_UPLOAD_MAX_MEMORY_SIZE), Rails, and most upload libraries have independent limits. If nginx logs no error but the client still sees a rejection, the request reached your app and your app said no.


client_body_buffer_size 128k;   # default 8k or 16k

This does not change what nginx accepts. It controls how much of the body is held in memory before nginx spills it to a temporary file on disk. Raising it can reduce disk I/O for moderately sized uploads, but it will never fix a 413 — and setting it very large multiplies memory use by the number of concurrent uploads.


Verify the Fix

Send a real file of a known size:

# make a 20 MB test file
dd if=/dev/zero of=/tmp/test.bin bs=1M count=20

curl -s -o /dev/null -w "%{http_code}\n" \
  -F "file=@/tmp/test.bin" https://example.com/upload

A 200, 201, or 302 means the limit is doing what you want. A 413 means something in the chain is still capping you — check the error log to find out which nginx logged it:

sudo tail -f /var/log/nginx/error.log

If no client intended to send too large body line appears, nginx is not the layer rejecting the request. See Where Are Nginx Logs Stored? if the log is not in the default location.

Clean up the test file afterwards:

rm /tmp/test.bin

Prevention

  • Set the limit deliberately when you build the server, not after the first user complains. The 1 MB default is a placeholder, not a recommendation.
  • Scope generous limits to upload endpoints only. A site-wide 500 MB limit is an easy way for someone to exhaust your disk.
  • Keep nginx and application limits in sync, and document the number somewhere both teams can see — mismatched limits produce a confusing failure where the upload appears to succeed and then fails.
  • Return a useful error. A bare nginx 413 page tells users nothing; catch the size client-side and say what the maximum is before they wait through the upload.

Frequently Asked Questions

Find answers to common questions

The request body exceeded client_max_body_size, which defaults to only 1 MB. Nginx rejects the upload before your application ever sees it, so no amount of application configuration will help until you raise the nginx limit.

Add 'client_max_body_size 50m;' inside the http, server, or location block, then run 'sudo nginx -t' and 'sudo systemctl reload nginx'. Put it in the http block to cover every site, or in a specific location to raise the limit only for an upload endpoint.

1 MB. That is small enough that a single phone photo can exceed it, which is why this error shows up on almost every new site that accepts uploads. Setting the value to 0 disables the size check entirely.

Usually another layer is still enforcing a smaller limit — a second nginx acting as a load balancer, a CDN, or a Kubernetes ingress controller. Every proxy in the chain must allow the size. Also check that you edited the file nginx actually loads and that you reloaded rather than just saved.

Yes, if you use PHP. upload_max_filesize and post_max_size in php.ini are separate limits, and PHP will reject the upload after nginx accepts it. Set both to at least the nginx value and restart PHP-FPM, not just nginx.

In the http block it applies to every server. In a server block it applies to one site. In a location block it applies to one path, which is the safest option — raise the limit only on your upload endpoint and leave the rest of the site protected at the default.

It disables the size check completely, which removes a cheap protection against memory and disk exhaustion from oversized requests. Prefer an explicit generous limit such as 100m or 500m over unlimited, so a malicious or buggy client cannot fill the disk.

Add the annotation nginx.ingress.kubernetes.io/proxy-body-size to the Ingress resource, for example '50m'. Editing nginx.conf inside the controller pod does not work — the controller regenerates the config and your change is lost on the next reload.

LimitRequestBody, set in bytes rather than with a size suffix. LimitRequestBody 52428800 allows 50 MB. It can be set in httpd.conf, a virtual host, a Directory block, or .htaccess.

That was the original HTTP/1.1 reason phrase. RFC 9110 renamed the status to 'Content Too Large', but nginx still emits the older wording, which is why you see the classic phrase in the error page and in most documentation.