Fix 413 Request Entity Too Large Errors on Image Uploads

A 413 error means a server rejected the upload as too large. Each limit an image upload passes, with defaults, and how to raise or avoid it.

An upload request stopped at a gate marked with a size limit

Key takeaways

  • A 413 error means a server between the browser and your code rejected the request body as larger than its limit.
  • An image upload passes several limits in a row, and the smallest one wins. By default, nginx allows 1 MB, Express’s JSON parser 100 KB, and PHP 2 MB per file and 8 MB per request.
  • A Base64 string in a JSON body is a third larger than the file. The 205 KB test photo became a 279,828-character string that Express rejected with 413 at its default limit.
  • Multer reports an oversized file as a LIMIT_FILE_SIZE error, and Express answers it with 500 unless a handler returns 413.
  • Resizing in the browser before the upload cut the 209,870-byte test photo to 107,306 bytes and keeps the limits where they are.

What does a 413 error mean?

A 413 error means the server refused the request because its body is larger than the server allows. MDN defines the status as 413 Content Too Large, and older software calls it Request Entity Too Large. The server answers before your upload handler runs, so no log line from your own code appears.

The limit applies to the whole request body. A multipart form with one photo and several text fields is counted together, and a JSON body counts the encoded string, not the image inside it.

Which limits does an image upload pass?

An image upload passes the web server, the application framework, the language runtime and the image upload API, in that order, and each one has its own maximum. The smallest limit rejects the request, whichever layer it belongs to.

LayerSettingDefaultWhere to change it
nginxclient_max_body_size1 MBhttp, server or location block
Express JSON parserlimit option of express.json()100 KBthe middleware call
Multerlimits.fileSizeno limitthe multer() options
DjangoDATA_UPLOAD_MAX_MEMORY_SIZE2.5 MB, file uploads excludedsettings.py
PHP and Laravelupload_max_filesize and post_max_size2 MB and 8 MBphp.ini
Laravel validationmax rulenone, set in kilobytesthe validation rules
Filestackmaximum file size20 MB Free, 1 GB Start, 2 GB Grow, 5 GB Scalethe plan
Table 1. Defaults from the nginx, Express, Multer, Django, PHP, Laravel and Filestack documentation and pricing page, checked November 4, 2026.

The other parts of a self-built upload pipeline are listed in the guide to uploading on your own server.

How do you raise the nginx limit?

Set client_max_body_size to the largest request you accept, then reload nginx. The directive’s default is 1m, and nginx returns 413 when a request body exceeds it (nginx documentation). The directive works in the http, server and location contexts, so the limit can be raised for the upload route alone:

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

Setting the value to 0 turns the check off, which leaves the size of an upload to the layers behind nginx. nginx documents that browsers cannot display this error correctly, so an upload form should read the status from the response and show its own message.

How do you raise it in Express, Django and Laravel?

Set the limit in the parser or setting that rejects the request. Each framework below was checked against its documentation, and Express was also run.

Express. The JSON parser’s limit option defaults to '100kb'. With Express 5.3.0 and body-parser 2.4.0, a {"image": "..."} body holding the 279,828-character Base64 string is rejected with 413 and request entity too large. The same body goes through express.json({ limit: "10mb" }), as checked on November 4, 2026. The better fix is to send the file as multipart or raw binary, as described in Base64 to image and image to Base64, and keep the parser at its default.

Multer. The Express examples are ES modules, run on Node.js 25.8.1, after this install:

npm install express multer

Multer’s limits.fileSize has no limit by default. When a file passes the limit you set, Multer raises a MulterError with the code LIMIT_FILE_SIZE, and Express’s default handler answers it with 500. This handler returns 413 instead:

import express from "express";
import multer from "multer";

const app = express();
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 100 * 1024 } });

app.post("/upload", upload.single("image"), (req, res) => res.json({ bytes: req.file.size }));

app.use((err, req, res, next) => {
  if (err instanceof multer.MulterError && err.code === "LIMIT_FILE_SIZE") {
    return res.status(413).json({ error: "Image is larger than 100 KB" });
  }
  next(err);
});

app.listen(3000);

A file over the 100 KB limit, such as the 209,870-byte photo, gets a 413 and the JSON message above.

Django. DATA_UPLOAD_MAX_MEMORY_SIZE defaults to 2,621,440 bytes (2.5 MB) and raises RequestDataTooBig when a request body passes it. The check excludes file upload data (Django settings), so it affects Base64 strings in form fields and JSON bodies, not multipart files.

Laravel and PHP. PHP rejects a file before Laravel sees it when the file passes upload_max_filesize (default 2M) or the request passes post_max_size (default 8M). Keep post_max_size larger than upload_max_filesize (PHP manual). Laravel’s max validation rule measures files in kilobytes, so 'image' => 'required|image|max:10240' allows 10 MB (Laravel validation).

Should you raise the limit or resize first?

Resize first when the photos come from phones and cameras. A limit compares bytes, and a camera original is larger than the image a page displays. Resizing in the browser keeps every limit in Table 1 where it is and sends fewer bytes.

This function scales an image to at most 1,000 pixels on its longest side. It then re-encodes the result as JPG at quality 0.8:

async function resizeImage(file, maxSide = 1000, quality = 0.8) {
  const bitmap = await createImageBitmap(file, { imageOrientation: "from-image" });
  const scale = Math.min(1, maxSide / Math.max(bitmap.width, bitmap.height));
  const canvas = new OffscreenCanvas(Math.round(bitmap.width * scale), Math.round(bitmap.height * scale));
  canvas.getContext("2d").drawImage(bitmap, 0, 0, canvas.width, canvas.height);
  return canvas.convertToBlob({ type: "image/jpeg", quality });
}

In headless Chrome on November 4, 2026, the 721 × 1118 photo (209,870 bytes) becomes a 645 × 1000 JPG of 107,306 bytes. Upload the blob the function resolves with instead of the original file.

The straw hat photo at 645 by 1000 pixels
The test photo at 645 × 1000 pixels, the size the resize function produces, delivered from the CDN.

Raise a limit when files have to stay at full size, such as print masters, and set it to the largest file you accept at every layer, with the upload API’s maximum as the ceiling. A plan’s maximum file size is set by the plan: 20 MB on Free, 1 GB on Start, 2 GB on Grow and 5 GB on Scale (Filestack pricing). A browser upload sent straight to the API does not pass through your own server’s limits.

Frequently asked questions

What is the default nginx upload limit?

The default is 1 MB. client_max_body_size is 1m unless you set it, and nginx returns 413 for any request body above it.

Why do large phone photos fail but small ones work?

A limit rejects every request whose body is over it, so a file from a phone camera can cross a limit that a resized image passes. The 209,870-byte test photo fits under nginx’s 1 MB default but not under Express’s 100 KB JSON default once it is Base64 encoded.

Can I upload files larger than the limit in parts?

Yes. A multipart upload sends a file as separate parts, each in its own request, so no single request carries the whole file. Filestack’s API clients use this flow for uploads, and the upload documentation describes it.

Sources

  1. MDN Web Docs, 413 Content Too Large.
  2. nginx, client_max_body_size.
  3. Django documentation, Settings.
  4. PHP manual, Description of core php.ini directives.
  5. Laravel documentation, Validation.
  6. Filestack, Pricing and Upload documentation.
  7. Express 5.3.0, body-parser 2.4.0 and Multer 2.5.0 behavior: our test requests on November 4, 2026.
Written by

Carl Cruz