How to fix the 413 Request Entity Too Large error in WordPress
The web server, or a proxy in front of it, refused a request larger than its own limit, and the file never reached PHP. Raising PHP's upload_max_filesize does not clear it. Send the file over SFTP and install it with WP-CLI, or raise the limit on the server that answered.
- By
- WP Ministry
- Published
- Tested on
- WordPress 7.1.3, PHP 8.3.35
In short
- A 413 is written by the web server or by a proxy in front of it, not by WordPress. Nothing on the site has changed.
- The limit is on the whole request, and it is separate from PHP's upload_max_filesize.
- nginx accepts 1 MB unless client_max_body_size says otherwise.
- Apache's limit is LimitRequestBody. Since 2.4.54 it is 1 GB unless it has been set to something else.
- A plugin or theme zip already on the server installs with WP-CLI, with no upload form.
- The HTTP standard now calls the status "413 Content Too Large". nginx and Apache still print the older name.
A 413 is not written by WordPress. It is the answer of the web server, or of a proxy or a CDN in front of it, to a request that is larger than that server accepts. In WordPress you meet it when you upload: a plugin or a theme as a .zip file, a file for the Media Library, or a file to import.
Nothing has been lost or changed. The server refused the file, and the site is as it was a minute ago.
The limit is not PHP's. PHP has two limits of its own, and when one of them stops a file WordPress says so in its own words: see "The uploaded file exceeds the upload_max_filesize directive in php.ini." A 413 comes from a limit in front of PHP. nginx compares the size the browser declares with its limit and refuses the request without passing it on. Apache answers 413 and throws the upload away. Either way PHP never receives the file, which is why raising upload_max_filesize changes nothing here.
What you see in WordPress
- Plugins, Add Plugin, Upload Plugin, and the same for a theme. After you click Install Now, the server's own page takes the place of the dashboard. Where PHP runs as part of Apache, WordPress's "The link you followed has expired." and a "Please try again." link follow on the same page, under Apache's words. Apache has thrown the upload away, PHP runs all the same, and WordPress finds a form with nothing in it.
- Media, Add Media File. "Unexpected response from the server. The file may have been uploaded successfully. Check in the Media Library or reload the page." After a 413 the file has not been uploaded.
- The Media Library, and the media window an editor opens. The same sentence, except for an image, where it is "The server cannot process the image. This can happen if the server is busy or does not have enough resources to complete the task. Uploading a smaller image may help. Suggested maximum size is 2560 pixels." That is the message the page on the "HTTP error" is about.
- The block editor. "The response is not a valid JSON response." The editor asked for data and was sent the server's error page. It uses the same words when a save fails.
Only the first of these names the status. For the others, open your browser's developer tools, choose the Network tab and upload the file again. The failed request is async-upload.php, or in the block editor one whose address contains /wp-json/wp/v2/media, and its status is 413.
Which server wrote the page
- nginx. "413 Request Entity Too Large", centered, with "nginx" under a line. nginx's documentation adds: "Please be aware that browsers cannot correctly display this error." So do not count on seeing the page. Go by the status code, or by nginx's error log, where the line reads "client intended to send too large body" and gives the size in bytes.
- Apache. The heading "Request Entity Too Large", then "The requested resource does not allow request data with POST requests, or the amount of data provided in the request exceeds the capacity limit."
- A CDN or a proxy. A page of its own.
The name varies, and the number does not. The HTTP standard has renamed this status twice: "Request Entity Too Large" became "Payload Too Large" in RFC 7231 and "Content Too Large" in RFC 9110, the standard in force since June 2022. nginx and Apache both still print the first name, and the current source code of each still holds it. Cloudflare's documentation calls the status "Payload Too Large", and MDN calls it "Content Too Large". They are one status.
Tell the server's limit from PHP's
Go to Media, then Add Media File. The figure under the upload box, "Maximum upload file size", is PHP's limit. WordPress works it out from PHP's two settings and knows nothing of the web server's. A file smaller than that figure that is still refused has met a limit in front of PHP.
| What you see | Whose limit | Where to go |
|---|---|---|
| A 413, or "Request Entity Too Large" | The web server's, or a proxy's | The fixes below |
| "The uploaded file exceeds the upload_max_filesize directive in php.ini.", or a file that "exceeds the maximum upload size for this site." | PHP's upload_max_filesize | The page on upload_max_filesize |
| "The link you followed has expired." after a plugin upload, with nothing from the server above it | PHP's post_max_size | "The link you followed has expired." |
A request has to fit through every server in turn: a CDN where there is one, then nginx or Apache, then PHP. You meet the smallest limit first. Once it is raised, the next smallest shows itself, so a 413 that turns into PHP's message is progress.
Where it goes wrong
A page request passes through each of these in turn. This one comes from the web server.
- Browser
- DNS
- HTTPS
- CDN or firewall
- Web server (this error comes from here)
- PHP
- WordPress
- Database and files
What causes it
nginx's client_max_body_size is smaller than the file
Commonnginx accepts a request body of 1 MB unless client_max_body_size sets another figure. It compares the size the browser declares with the limit and answers 413 without passing the request to PHP.
Fix: Get the file in without the upload form, or Raise client_max_body_size on nginx, or Ask the host to raise it
Apache's LimitRequestBody is set lower than the file
SometimesSince Apache 2.4.54 the limit is 1073741824 bytes, 1 GB, unless it is set. In 2.4.53 and earlier there was none by default. A 413 from Apache for a file of a few megabytes means a lower figure has been set, in the server's configuration or in an .htaccess file.
Fix: Get the file in without the upload form, or Raise LimitRequestBody on Apache, or Ask the host to raise it
A CDN or a proxy in front of the server has a limit of its own
SometimesA request passes through every server between the browser and WordPress, and each can refuse it. Cloudflare's documentation gives its largest upload as 100 MB on the Free and Pro plans.
Fix: Get the file in without the upload form, or Check the limit of a CDN or a proxy in front
A firewall on the server limits the size of a request
RareThe ModSecurity firewall rejects a request over its SecRequestBodyLimit with a 413. Its manual gives the default as 134217728 bytes, which is 128 MB, and a host can set it lower.
Fix: Get the file in without the upload form, or Ask the host to raise it
How to fix it
Get the file in without the upload form
- Takes care
- Low risk
- About 15 minutes
- Steps tested on WordPress 7.1.3
The limit applies to what a browser sends through the web server. A file that reaches the server over SFTP does not pass through it, so no limit on this page applies. This changes no setting, which makes it the place to start for one large file.
The commands need SSH access and WP-CLI: how to use WP-CLI covers connecting and checking that it is installed.
Step 1: Upload the .zip file over SFTP
Leave it zipped. Put it in a folder of its own on the server, such as
incomingin your home folder.Step 2: Install a plugin from the file
In the folder WordPress is installed in, run this with the path to your own file.
WP-CLI unpacks the file and ends with "Success: Installed 1 of 1 plugins." The plugin is then on the Plugins screen, ready to activate.
bashwp plugin install ~/incoming/my-plugin.zipStep 3: Or a theme
bashwp theme install ~/incoming/my-theme.zipStep 4: Delete the .zip file
WP-CLI has copied what it needs into
wp-content, so the file inincomingis no longer wanted.
If the file is a newer copy of a plugin that is already installed, WP-CLI stops with "Destination folder already exists." That page shows how to install over the top.
Without SSH, unzip the file on your computer and upload its folder over SFTP into wp-content/plugins or wp-content/themes. It then appears in the dashboard, ready to activate.
A file for the Media Library needs one more step, because the library lists only what WordPress has a record of. The page on upload_max_filesize shows how to add a file that is already on the server with wp media import.
To undo it: Delete the plugin or the theme from its screen in the dashboard.
Raise LimitRequestBody on Apache
- Takes care
- Back up first
- About 10 minutes
- Steps tested on WordPress 7.1.3
Use this when the page that refused the file is Apache's. Left alone, Apache's limit is 1 GB, and before 2.4.54 there was none. A lower one was set by somebody, in the server's configuration or in an .htaccess file, and it can be raised the same way.
Step 1: Look for a line that is already there
Open
.htaccessin the site's main folder, besidewp-config.php, and search it forLimitRequestBody. Its name begins with a dot, so set your file manager to show hidden files if you cannot see it. Ifwp-adminhas an.htaccessof its own, look there too: Apache's manual says a file in a folder can override the ones above it.If you find a line, change its number and go to the last step.
Step 2: Add this line above "# BEGIN WordPress"
The number is in bytes, and 67108864 is 64 MB. Choose one with room above your largest file. A value of 0 means no limit at all. Where one file holds two
LimitRequestBodylines, Apache goes by the later one, so leave no smaller figure below this line..htaccessLimitRequestBody 67108864Step 3: Upload the file again
If WordPress now refuses the file in its own words, the server has let it through and PHP's limit is next: see the page on upload_max_filesize. The .htaccess generator can write PHP's two upload settings into the file. It does not write
LimitRequestBody.
If the 413 is still there, the limit that refused the file is somewhere .htaccess does not reach: in the server's own configuration, or in nginx or a CDN in front of Apache. Take the line out again and go on to the fixes below.
On a server you run, the same line can go in the site's virtual host. Apache notes the refusal in its error log, as "Requested content-length of … is larger than the configured limit of …", only at the info log level. The default level is warn, so at the default the log shows nothing.
To undo it: Remove the line from .htaccess, or put the old number back.
Raise client_max_body_size on nginx
- Advanced
- Back up first
- About 15 minutes
This is for a server whose nginx configuration you can edit. Where the host runs nginx, use the last fix.
Step 1: Confirm that nginx refused the request
Its error log has a line with "client intended to send too large body" at the time of the upload. If there is none, look further forward: a CDN or another proxy may have answered.
Step 2: Set the limit
The line is allowed in the
httpblock, in aserverblock and in alocationblock. With no such line anywhere, nginx accepts 1 MB. If the configuration already has one that applies to the site, change its figure. A value of 0 turns the check off.nginxclient_max_body_size 64m;Step 3: Test the configuration, then reload
The first command checks the files, and the second runs only if the check passed.
bashsudo nginx -t && sudo nginx -s reloadStep 4: Raise PHP's limits to match
nginx now lets the file through, and PHP's own limits apply to it next. The page on upload_max_filesize covers them.
The nginx server block generator writes this line into the server block it builds.
To undo it: Remove the line, or put the old figure back, and reload nginx.
Check the limit of a CDN or a proxy in front
- Easy
- Low risk
- About 15 minutes
A CDN that carries the whole site receives every upload before your server does. If its limit is the smaller one, raising the server's changes nothing.
Step 1: Find out whether one is in front
How to set up a CDN for WordPress explains the two kinds. One that is in front of the whole site, through DNS, receives your uploads. One that serves only static files from a second hostname does not.
Step 2: Read its limit in its own documentation
Cloudflare's documentation gives the largest upload as 100 MB on the Free and Pro plans, 200 MB on Business and up to 5 GB on Enterprise. The setting is "Maximum Upload Size", on the zone's Network page.
Step 3: Raise it, or go round it
Where the plan allows a higher figure, set it. Where it does not, Cloudflare's own suggestions are to send the file in smaller pieces, to upload through a DNS record that it does not proxy, or to change plan. The first fix on this page goes round the CDN as well, because SFTP does not pass through it.
A load balancer or a proxy that the hosting company runs has a limit the host sets. Use the next fix.
To undo it: Put the setting back as it was.
Ask the host to raise it
- Easy
- No risk
- About 15 minutes
Where you cannot read the server's logs or edit its configuration, the host can.
Step 1: Write down what happened
The size of the file, the address of the page you uploaded from, the exact time with your time zone, and the words on the error page.
Step 2: Ask questions that have an answer
Ask which server answered 413 and what its limit is: nginx's
client_max_body_size, Apache'sLimitRequestBody, or a firewall's limit such as ModSecurity'sSecRequestBodyLimit. Ask for it to be set above the size of your file for your site, and whether your plan allows that.Step 3: Ask for PHP's limits at the same time
upload_max_filesizeandpost_max_sizeneed to be above the file as well, or the upload stops at the next limit.
WordPress hosting problems: how to tell whether the fault is the host or the site has a message to copy.
When to get help
If the 413 is still there after the limit was raised on the server you thought was answering, another limit sits somewhere in the chain. It can be a second proxy, a firewall's own limit or a setting in a part of the configuration you cannot open. Finding it means following one upload from the browser to PHP with each server's log open, and that takes access to the server.
Common questions
Will raising upload_max_filesize fix a 413?
No. That setting is PHP's, and a 413 means a server in front of PHP refused the request, so PHP never had the file to measure. Raising it does matter afterward: once the server lets the file through, PHP's limits are the next it has to fit.
Why does the page also say "The link you followed has expired."?
Because WordPress ran after the server had refused the upload. Where PHP is part of Apache, Apache sends its 413 page and discards what was sent, and PHP still runs the request with an empty form. WordPress finds no security token in it and adds its usual words for that. The cause is the 413 above them, not the token.
Is "413 Content Too Large" a different error?
No. It is the name the current HTTP standard gives the same status. "Payload Too Large" was the name before it, and "Request Entity Too Large" the one before that, which nginx and Apache still print.
How high should the limit be?
Above the largest file you expect to upload, on every server the request passes through, PHP included. A large file also takes longer to send and to process. If the upload then stops on a time limit, the pages on "Maximum execution time exceeded" and the 504 error cover those.
- GuideHow to update the PHP version of a WordPress site
- GuideWordPress uptime monitoring: what a check sees and what it misses
- Glossary termHeartbeat API
- GuideHow to change WordPress permalinks without breaking your old links
- GuideHow to deactivate WordPress plugins when you are locked out of the dashboard
- Glossary term.htaccess

