A 413 Payload Too Large error occurs when the request body size exceeds the maximum allowed by the server. This prevents clients from sending oversized payloads that could overwhelm server resources or storage. It belongs to the 4xx client error class in the HTTP status codes specification—meaning the fix is always on the client side, not the server.

What 413 Payload Too Large Means
The HTTP Definition
Per RFC 9110, 413 indicates “the server is refusing to process a request because the request content is larger than what the server is willing or able to process.”
Key characteristics:
- This is a client error (4xx class)
- The server explicitly refuses the request
- The server may close the connection or suggest retry with smaller payload
- The
Retry-Afterheader may be included
Official Name Change
HTTP/1.1 used “413 Request Entity Too Large.” HTTP/2 and later use “413 Payload Too Large” (RFC 9110).
Common Causes of 413 Errors
1. Web Server Body Size Limits
Nginx:
# Default: 1MBclient_max_body_size 1m;Apache:
# Default: 0 (unlimited in older versions)LimitRequestBody 104857602. Application Framework Limits
Node.js (Express):
app.use(express.json({ limit: '1mb' }));app.use(express.urlencoded({ limit: '1mb', extended: true }));Django:
DATA_UPLOAD_MAX_MEMORY_SIZE = 2621440 # 2.5 MBPHP:
post_max_size = 8Mupload_max_filesize = 2M3. CDN or Proxy Limits
CDNs and reverse proxies often have their own limits:
- Cloudflare: 100MB for free plans
- AWS CloudFront: Configurable
- Azure CDN: 100MB default
- Azion: Configurable per application via Rules Engine
4. Load Balancer Limits
Cloud load balancers enforce limits:
- AWS ALB: 100KB for headers, larger for body
- Google Cloud Load Balancing: 1MB default
5. WAF Rules
Web Application Firewalls may block large payloads:
- ModSecurity rules
- Cloud WAF policies
- Custom security rules
Troubleshooting 413 Errors
Step 1: Identify Where the Limit Is
Client → CDN → Load Balancer → Web Server → Application ↑ ↑ ↑ ↑ limit? limit? limit? limit?The error response headers help identify the source:
HTTP/1.1 413 Payload Too LargeServer: nginx # Generated by NginxContent-Type: text/htmlStep 2: Check Web Server Configuration
Nginx:
grep -r "client_max_body_size" /etc/nginx/Apache:
grep -r "LimitRequestBody" /etc/apache2/Step 3: Check Application Limits
Node.js:
// Check middleware configurationapp.use(express.json({ limit: '10mb' }));PHP:
php -i | grep -E "(post_max_size|upload_max_filesize)"Step 4: Check CDN/WAF Logs
- Cloudflare: Security Events
- AWS WAF: CloudWatch metrics
- ModSecurity: Audit logs
- Azion: Real-Time Events → filter by status
413
Step 5: Test with Different Sizes
# Test with specific payload sizedd if=/dev/zero bs=1M count=5 | curl -X POST -H "Content-Type: application/json" --data-binary @- https://example.com/uploadHow to Fix 413 Errors
Increase Nginx Limit
http { # Global limit client_max_body_size 100m;}
server { # Per-server limit client_max_body_size 50m;
location /api/upload { # Per-location limit client_max_body_size 500m; }}Increase Apache Limit
<Directory /var/www/html/uploads> LimitRequestBody 52428800</Directory>Increase Application Limits
Express:
app.use(express.json({ limit: '50mb' }));app.use(express.urlencoded({ limit: '50mb', extended: true }));NestJS:
app.use(json({ limit: '50mb' }));Django:
DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800 # 50 MBFILE_UPLOAD_MAX_MEMORY_SIZE = 52428800PHP:
post_max_size = 50Mupload_max_filesize = 50MConfigure CDN Limits
Cloudflare:
- Increase plan limits
- Use direct origin uploads
- Use Cloudflare R2 or Workers
AWS CloudFront:
- Use signed URLs for large uploads
- Upload directly to S3
Azion:
- Configure request body size limit via Rules Engine
- Use Edge Storage with presigned URLs for large uploads
- Upload directly to Azion Edge Storage bypassing size limits at the proxy layer
Handling Large Uploads Properly
1. Chunked Uploads
Split large files into smaller chunks:
async function uploadFile(file) { const chunkSize = 5 * 1024 * 1024; // 5MB chunks const chunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < chunks; i++) { const start = i * chunkSize; const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end);
await uploadChunk(chunk, i, chunks, file.name); }
await completeUpload(file.name, chunks);}2. Direct-to-Storage Uploads
Upload directly to object storage:
// Get presigned URL from serverconst { url, fields } = await fetch('/api/upload-url').then(r => r.json());
// Upload directly to S3const formData = new FormData();Object.entries(fields).forEach(([key, value]) => formData.append(key, value));formData.append('file', file);
await fetch(url, { method: 'POST', body: formData });3. Streaming Uploads
Stream large payloads without loading into memory:
app.post('/upload', (req, res) => { const fileStream = fs.createWriteStream('/uploads/file.dat');
req.pipe(fileStream) .on('error', (err) => res.status(500).send('Upload failed')) .on('finish', () => res.send('Upload complete'));});4. Validate Before Upload
Check file size client-side before uploading:
const MAX_SIZE = 50 * 1024 * 1024; // 50MB
document.getElementById('file').addEventListener('change', (e) => { const file = e.target.files[0];
if (file.size > MAX_SIZE) { alert(`File too large. Maximum size is ${MAX_SIZE / 1024 / 1024}MB`); e.target.value = ''; }});Security Considerations
DoS Prevention
Large payloads can be used for denial of service:
- Set reasonable limits based on use case
- Limit total request time, not just size
- Implement rate limiting per client
Memory Limits
Prevent memory exhaustion:
// Use streaming for large uploadsapp.use(express.raw({ limit: '50mb', type: 'application/octet-stream'}));Input Validation
Always validate uploaded content:
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];
app.post('/upload', (req, res) => { if (!ALLOWED_TYPES.includes(req.file.mimetype)) { return res.status(415).send('Unsupported media type'); }
// Scan for viruses, validate structure, etc.});Client-Side Error Handling
Handle 413 gracefully in your client:
async function uploadFile(file) { try { const response = await fetch('/api/upload', { method: 'POST', body: formData });
if (response.status === 413) { const max = response.headers.get('X-Max-Size'); throw new Error(`File too large. Maximum size is ${max} bytes`); }
if (!response.ok) throw new Error('Upload failed');
return response.json(); } catch (error) { console.error('Upload error:', error); throw error; }}Monitoring 413 Errors
Track these metrics:
- 413 rate: Percentage of requests rejected for size
- Average rejected size: Understand typical oversize payloads
- Top endpoints: Which endpoints receive oversized requests
- Client patterns: Identify clients consistently sending large payloads
Alert thresholds:
- Sudden spike in 413s: Possible attack or misconfigured client
- Consistent 413s from legitimate clients: Limits too restrictive
Frequently Asked Questions
What’s the default Nginx limit? 1MB (client_max_body_size 1m).
What’s the default Apache limit? Varies by version. Modern versions often have no limit by default.
How do I handle very large file uploads? Use chunked uploads, presigned URLs to cloud storage, or streaming uploads.
Can I return the max size in the error response? Yes, add a custom header: X-Max-Body-Size: 10485760.
Should I allow unlimited uploads? No. Always set limits to prevent DoS attacks and resource exhaustion.
How do I test upload limits? Use dd to create test files of specific sizes, then upload with curl.