How to Fix Nginx 413 Request Entity Too Large Errors

Last updated Monday, May 18, 2026 9:40 am Joshua James 10 min read

Nginx returns 413 Request Entity Too Large when a client sends a request body that is larger than the layer handling the request allows. File uploads are the usual trigger, but large JSON payloads, API imports, backups, media uploads, and form submissions can hit the same limit.

The fix is not always one setting. Nginx can reject the body before it reaches the application, PHP-FPM can reject it after Nginx accepts it, and a CDN or load balancer can reject it before the request reaches your server. Start by finding which layer owns the 413 response, then raise only the limit that matches the real upload path.

Understand Nginx 413 Request Entity Too Large

The main Nginx directive for this error is client_max_body_size. It is valid in the http, server, and location contexts. The documented default is 1m, and setting it to 0 disables the Nginx request-body size check.

Use this map to decide where to look first:

LayerCommon LimitTypical SymptomFirst Check
Nginx edge serverclient_max_body_sizeNginx error page or Nginx log says the client intended to send too large a bodysudo nginx -T and the Nginx error log
Nginx reverse proxyclient_max_body_size in the proxying server or locationUploads fail before the upstream application sees the requestTest the origin Nginx directly and check the proxy location
PHP-FPM applicationupload_max_filesize and post_max_sizeNginx accepts the request, but WordPress, Laravel, phpMyAdmin, or another PHP app still rejects the uploadInspect the active PHP-FPM configuration
Application serverFramework or app upload settingNginx no longer returns 413, but the app returns its own upload-size errorCheck the app logs and app-specific upload setting
CDN, WAF, or load balancerProvider request-size limitThe visible error page names the edge provider or the origin log shows no requestBypass the edge and test the origin directly

Do not raise upload limits globally unless every virtual host needs them. A large limit on all sites increases disk, memory, and abuse risk for endpoints that should never accept big request bodies.

Find the Nginx 413 Source

Check the response headers first to identify the layer answering the hostname, then reproduce the failing upload while watching the logs. If the response comes from your origin Nginx, the Server header and error page often point there. If a CDN, WAF, reverse proxy, or hosting panel owns the response, changing the origin Nginx configuration may not affect the visible error.

curl -I https://example.com/upload

A header response that reaches Nginx might look similar to this:

HTTP/2 200
server: nginx

Next, inspect the Nginx error log while reproducing the upload. Use the active log path from your server block if the site has per-site logs. If you are not sure where Nginx writes logs, use the Nginx access and error logs guide to identify the active paths before changing configuration.

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

Relevant log output for an Nginx-owned 413 often includes this pattern:

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

If the origin log does not change while the browser shows 413, reproduce the upload against the origin by resolving the real hostname to the origin IP for one request. Replace 192.0.2.10 with your origin IP address, and adjust the file size and endpoint to match the failing upload:

truncate -s 12M /tmp/nginx-upload-test.bin
curl -i --resolve example.com:443:192.0.2.10 --data-binary @/tmp/nginx-upload-test.bin https://example.com/upload
rm -f /tmp/nginx-upload-test.bin

If the origin accepts the upload request but the public hostname still returns 413, the limit is probably outside origin Nginx. Check the CDN, WAF, reverse proxy appliance, cloud load balancer, or hosting control panel that sits in front of the server.

Set the Nginx Request Body Limit

Place client_max_body_size at the narrowest scope that matches the upload endpoint. For a single site, the server block is usually safer than the global http block. For one upload route, a dedicated location limit is safer than changing the whole site.

The examples in this section use HTTP listeners to keep the request-body limit separate from certificate setup. On a production HTTPS site, put the same client_max_body_size directive inside the existing TLS server block that already defines its certificate settings.

Raise the Limit for One Nginx Server Block

Edit the virtual host that handles the upload. Debian and Ubuntu packages commonly use /etc/nginx/sites-available/, while Fedora, RHEL, Rocky Linux, nginx.org packages, and many custom layouts commonly use /etc/nginx/conf.d/. If you are not sure which file handles the hostname, inspect the full active configuration:

sudo nginx -T | grep -E "server_name|client_max_body_size|include"

Add the limit inside the relevant server block:

server {
    listen 80;
    server_name example.com www.example.com;

    client_max_body_size 25m;

    root /var/www/example.com/public;
    index index.html index.php;

    location / {
        try_files $uri $uri/ =404;
    }
}

Use a value that matches the real business need. For example, 25m is enough for many profile-image, document, or small media uploads, while large backup imports or video uploads may need a separate endpoint or direct object-storage workflow instead of a very large global Nginx limit.

Raise the Limit for One Nginx Upload Location

For applications with one upload path, keep the higher limit scoped to that route. The rest of the site can keep a smaller default.

server {
    listen 80;
    server_name example.com;

    client_max_body_size 2m;

    location /uploads/api/ {
        client_max_body_size 50m;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

If the upload route uses a reverse proxy, keep the higher limit in the exact location that owns that route. If the route is matched by a different location than you expected, review the Nginx location block priority rules before assuming the new limit applies.

Apply the Nginx 413 Fix

Test the Nginx configuration before reloading:

sudo nginx -t

A successful syntax test prints these lines:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload Nginx only after the syntax test passes:

sudo systemctl reload nginx

The reload command normally returns no output on success. If it fails, check the service manager and error log before retrying the upload.

Verify the Nginx 413 Fix

Test with a disposable file that is larger than the old limit but smaller than the new limit. Replace the URL with a real upload endpoint that accepts request bodies. Do not use a production-only endpoint with private data for this test.

truncate -s 12M /tmp/nginx-upload-test.bin
curl -i --data-binary @/tmp/nginx-upload-test.bin https://example.com/upload
rm -f /tmp/nginx-upload-test.bin

If the body still exceeds the active Nginx limit, the response usually starts with a 413 status:

HTTP/1.1 413 Request Entity Too Large

After the fix, the response should no longer be an Nginx 413. The exact status depends on the application. A protected upload endpoint might return 401, an API might return 400 for missing metadata, and a working upload endpoint might return 200, 201, or 204. The important result is that Nginx no longer rejects the request body before the application handles it.

Fix Nginx 413 for PHP-FPM Uploads

PHP applications need matching limits in both Nginx and PHP. If Nginx accepts a 25 MB request but PHP allows only a 2 MB upload or an 8 MB POST body, the application can still reject the upload after the Nginx 413 is gone.

Find the active PHP upload settings. Common PHP-FPM paths vary by distribution and PHP branch, so this command searches the most common configuration files without assuming one exact version:

sudo grep -R -E '^[[:space:]]*(upload_max_filesize|post_max_size)[[:space:]]*=' /etc/php/*/fpm/php.ini /etc/php.ini /etc/php-fpm.d/*.conf 2>/dev/null

Relevant output may show values that are lower than your Nginx limit:

/etc/php/8.3/fpm/php.ini:upload_max_filesize = 2M
/etc/php/8.3/fpm/php.ini:post_max_size = 8M

Set post_max_size slightly higher than upload_max_filesize because the full POST body can include form fields and metadata in addition to the file itself. For example:

upload_max_filesize = 20M
post_max_size = 25M

Reload or restart the PHP-FPM service after changing PHP settings. Unit names vary. Debian and Ubuntu commonly use versioned names such as php8.3-fpm, while Fedora and RHEL-family systems commonly use php-fpm.

systemctl list-unit-files --type=service | grep -E 'php.*fpm'

Reload the service that matches your output. For example:

sudo systemctl reload php8.3-fpm

If the service does not support reload, restart it instead:

sudo systemctl restart php8.3-fpm

If PHP-FPM routing is also broken, the upload-size fix can be hidden behind 403, 404, or 502 errors. Use the Nginx 502 Bad Gateway troubleshooting guide when the socket, service, or upstream connection fails after upload limits are fixed.

Fix Nginx 413 Behind a Reverse Proxy

When Nginx proxies to another application, raise the request-body limit on the Nginx instance that first receives the client upload. If you have more than one Nginx layer, such as CDN proxy to edge Nginx to internal Nginx to app, every layer that reads the request body may need a compatible limit.

server {
    listen 80;
    server_name app.example.com;

    client_max_body_size 50m;

    location /api/uploads/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The request-body size limit is separate from timeout handling. If the upload size is accepted but the upstream takes too long to read or process it, you are no longer troubleshooting 413. Review the active proxy and application timeout settings instead of raising body-size limits again.

For path-related upload failures, especially when only one proxied prefix fails, check the Nginx proxy_pass trailing slash behavior. A path rewrite mistake can make the application reject a request that Nginx successfully accepted.

Fix Nginx 413 in Container and Control Panel Setups

Containerized Nginx and hosting panels often have another configuration owner. Editing /etc/nginx/nginx.conf on the host does not change an Nginx container unless that file is mounted into the container. Editing a generated panel file can also be overwritten by the next control-panel save.

  • For Docker or Compose, update the Nginx config mounted into the container, then reload or recreate the container according to how the service is managed.
  • For Kubernetes ingress, update the ingress controller annotation or ConfigMap that owns body-size limits instead of editing a pod-local generated file.
  • For Nginx Proxy Manager, cPanel, Plesk, or another panel, use the panel-supported custom Nginx field or upload-size option so the setting survives regeneration.
  • For CDN or WAF services, check the edge request-size policy. If the edge rejects the request, origin Nginx never gets a chance to apply client_max_body_size.

When a panel or ingress controller owns the live configuration, use nginx -T inside the actual Nginx runtime to confirm the final generated setting, not only the source template you edited.

Use Nginx Body Buffer Settings Carefully

client_body_buffer_size, client_body_temp_path, proxy_request_buffering, and fastcgi_request_buffering affect how Nginx stores or streams request bodies. They do not replace client_max_body_size as the normal 413 fix.

DirectiveUse413 Relevance
client_body_buffer_sizeControls how much of the request body can be buffered in memory before Nginx writes to a temporary fileNot the main size limit
client_body_temp_pathChooses where temporary request-body files are storedUseful when temp storage permissions or disk space cause different errors
proxy_request_bufferingControls whether Nginx buffers the full request body before sending it to a proxied upstreamCan affect streaming behavior, but the client body size limit still matters
fastcgi_request_bufferingControls request-body buffering before FastCGI handoffCan affect PHP-FPM streaming behavior, but PHP upload limits still matter

If uploads fail after increasing client_max_body_size, inspect disk space and Nginx temporary body paths. A full filesystem or unwritable temp directory usually creates different error patterns, but it can appear during the same upload workflow.

df -h
sudo nginx -T | grep -E "client_body_temp_path|proxy_temp_path|fastcgi_temp_path"

Troubleshoot Nginx 413 Request Entity Too Large

Troubleshoot 413 errors by proving the layer, the matching Nginx context, and the upload path in that order. Header checks can identify who answered the request, but use a body-bearing request when confirming whether the size limit is fixed.

Confirm the Active Nginx Limit Loaded

If Nginx still returns 413 after the edit, first prove the running configuration contains the limit in the file and context you expected. This check prints the loaded file markers plus nearby server, location, include, and body-size lines:

sudo nginx -T | grep -n -E "configuration file|server_name|location|include|client_max_body_size"

If the expected file does not appear, you edited a template, disabled file, container host file, or panel-generated file instead of the live Nginx configuration. Edit the loaded file, run sudo nginx -t, reload Nginx, then repeat the upload test.

Fix the Matching Server or Location Block

When several limits appear, the most specific matching context controls the request. A higher value in one location does not help a different upload URL, and a lower location value can override a higher server value for that route.

For one upload route, keep the larger limit in the exact location that receives the body. This pattern lets the rest of the site keep a smaller default:

server {
    listen 80;
    server_name example.com;

    client_max_body_size 8m;

    location = /api/import {
        client_max_body_size 50m;
        proxy_pass http://127.0.0.1:3000;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

A common miss is raising /upload/ while the browser posts to /api/import, /wp-admin/async-upload.php, or another application route. If the route is proxied, also verify the URI that reaches the upstream after proxy_pass path replacement.

truncate -s 12M /tmp/nginx-upload-test.bin
curl -i --data-binary @/tmp/nginx-upload-test.bin https://example.com/api/import
rm -f /tmp/nginx-upload-test.bin

Browser Shows 413 but Nginx Logs Stay Empty

An empty origin log during a visible 413 usually means the request never reached origin Nginx. Keep the hostname and TLS SNI the same, but resolve one request directly to the origin IP. Replace 192.0.2.10 with the origin address:

truncate -s 12M /tmp/nginx-upload-test.bin
curl -i --resolve example.com:443:192.0.2.10 --data-binary @/tmp/nginx-upload-test.bin https://example.com/upload
rm -f /tmp/nginx-upload-test.bin

If the origin request no longer returns 413 but the public hostname still fails, fix the CDN, WAF, load balancer, reverse proxy appliance, or hosting panel that sits before Nginx. If that layer has a hard upload-size ceiling, use a smaller upload flow, chunked application upload, or direct-to-storage design instead of raising origin Nginx again.

PHP App Still Rejects Uploads After Nginx 413 Is Gone

If the response is no longer an Nginx 413 but the PHP application still rejects the upload, check PHP-FPM and application limits next. post_max_size must be larger than upload_max_filesize because the full POST body includes form fields and metadata:

sudo grep -R -E '^[[:space:]]*(upload_max_filesize|post_max_size)[[:space:]]*=' /etc/php/*/fpm/php.ini /etc/php.ini /etc/php-fpm.d/*.conf 2>/dev/null

A matching PHP-FPM configuration can look like this:

upload_max_filesize = 20M
post_max_size = 25M

Reload the PHP-FPM service that owns the pool, then retest the upload. WordPress, Laravel, Drupal, phpMyAdmin, and other PHP applications may also have their own dashboard, plugin, or framework upload setting after PHP-FPM accepts the body.

Uploads Work Locally but Fail Through HTTPS

The HTTP and HTTPS server blocks may not share the same limit. Confirm which block receives the browser request and whether both blocks include the same body-size setting:

sudo nginx -T | grep -n -E "listen 80|listen 443|server_name|include|client_max_body_size"

For sites with separate HTTP and HTTPS blocks, a shared include prevents the values from drifting. Add the directive once in a snippet:

# /etc/nginx/snippets/upload-limit.conf
client_max_body_size 25m;

Then include that snippet inside every server block that accepts the upload request. Use an include path that exists in your Nginx layout, or create the directory before referencing it:

include /etc/nginx/snippets/upload-limit.conf;

Run sudo nginx -t before reloading. If the HTTPS block belongs to a control panel or certificate tool, keep the include in the supported custom-config area so it survives regeneration.

Nginx Rejects the New Directive During Reload

If sudo nginx -t reports that client_max_body_size is not allowed, the directive is in the wrong context. It belongs in http, server, or location, not inside if, map, upstream, or a rewrite-only snippet.

server {
    listen 80;
    server_name example.com;

    location /upload/ {
        client_max_body_size 50m;
        proxy_pass http://127.0.0.1:3000;
    }
}

After moving the directive, run the syntax test again. Reload only after Nginx confirms that the configuration file syntax is valid.

Nginx 413 Fix Breaks Another Site

The higher limit may have been added to the global http context or to a shared include used by multiple virtual hosts. Search the loaded configuration with file markers so you can see where the broad value comes from:

sudo nginx -T | grep -n -E "configuration file|server_name|client_max_body_size"

Move the higher value into the specific server or location block that owns the upload endpoint. Leave the global value small unless every virtual host should accept the larger body. Test Nginx, reload, and retest both the upload site and the site that was unintentionally affected.

Conclusion

Nginx should now accept the intended upload path without exposing every virtual host to larger request bodies. Keep the limit in the narrowest matching server or location block, retest after each reload, and continue at the PHP-FPM, application, CDN, or load-balancer layer if the 413 response moves outside Nginx.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: