Fix 413 Payload Too Large — File Upload Size Limit Errors
HTTP 413 Payload Too Large (also Request Entity Too Large) is the error you get when uploading a file that exceeds the server's size limit. The tricky part: the limit can be enforced at multiple layers.
The Error Messages
These all mean the same thing — file too large:
413 Request Entity Too Large(Nginx)413 Payload Too Large(HTTP/2)Error: request entity too large(Express/body-parser)PayloadTooLargeError: request entity too largePOST Content-Length exceeds the limit(PHP)Maximum request length exceeded(.NET)413: <html><body><h1>413 Request Entity Too Large</h1>(Nginx HTML page)
Where the Limit Is Enforced
Client → [CDN/WAF] → [Reverse Proxy] → [App Server] → [Framework]
Cloudflare Nginx/Apache Node/Python Express/Next
100MB 1MB default varies varies
You must increase the limit at every layer in the chain.
Fix 1: Nginx
# /etc/nginx/nginx.conf or site config
http {
client_max_body_size 100M; # Default is 1M!
}
# Or per-location
location /api/upload {
client_max_body_size 500M;
proxy_read_timeout 300s; # Also increase timeout for large files
}
Reload: sudo nginx -s reload
Fix 2: Apache
# .htaccess or httpd.conf
LimitRequestBody 104857600 # 100MB in bytes
# For PHP uploads (also set in php.ini)
php_value upload_max_filesize 100M
php_value post_max_size 100M
Fix 3: Express.js / Node.js
// body-parser (for JSON/raw bodies, NOT file uploads)
app.use(express.json({ limit: '100mb' }));
app.use(express.raw({ limit: '100mb' }));
// multer (for file uploads) — limit per file
const upload = multer({
limits: { fileSize: 100 * 1024 * 1024 }, // 100MB
});
// Error handling
app.use((err, req, res, next) => {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(413).json({
error: 'File too large',
maxSize: '100MB',
});
}
next(err);
});
Fix 4: Next.js
// next.config.mjs
export default {
api: {
bodyParser: {
sizeLimit: '100mb',
},
responseLimit: false,
},
};
// Or per-route (App Router)
// app/api/upload/route.ts
export const config = {
api: { bodyParser: false }, // Disable for streaming
};
Fix 5: PHP
; php.ini
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 300
memory_limit = 256M
Fix 6: Cloud Platforms
| Platform | Default Limit | How to Increase | |----------|--------------|-----------------| | Vercel | 4.5 MB (serverless) | Use Edge: 25MB, or direct S3 upload | | Netlify | 100 MB (deploy file) | N/A for functions | | AWS API Gateway | 10 MB | Use S3 presigned URLs for larger | | Cloudflare | 100 MB (free) | 500 MB (Business) | | Heroku | 500 MB | Already generous |
For limits above 100MB, use direct-to-S3 upload with presigned URLs.
Test with Exact-Size Files
Download files at exact boundary sizes to verify your fix:
| Test | File | Expected Result | |------|------|-----------------| | Under limit | sample-1mb.pdf | 200 OK | | At limit | sample-10mb.mp4 | 200 OK (if limit is 10MB) | | Over limit | sample-50mb.mp4 | 413 (if limit is 10MB) | | Way over | sample-100mb.bin | 413 or timeout |
Use our Sample Files by Size page to download files at exact sizes: 1MB, 5MB, 10MB, 50MB, 100MB, 500MB, 1GB.
Debugging Steps
- Check Nginx error log:
tail -f /var/log/nginx/error.log— look forclient intended to send too large body - Check which layer: Does the 413 come before your app code runs? → It's the proxy
- Check headers:
curl -v -X POST -F "[email protected]" https://your-api.com/upload - Test locally vs production: If it works locally but not in production, the limit is at the reverse proxy or CDN layer