Skip to content
>_ TrueFileSize.com
··7 min read

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 large
  • POST 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

  1. Check Nginx error log: tail -f /var/log/nginx/error.log — look for client intended to send too large body
  2. Check which layer: Does the 413 come before your app code runs? → It's the proxy
  3. Check headers: curl -v -X POST -F "[email protected]" https://your-api.com/upload
  4. Test locally vs production: If it works locally but not in production, the limit is at the reverse proxy or CDN layer