← Compare to Self-Hosted
AWS Lambda Chromium Binary Size Limit
Why your Puppeteer deployment fails and what to do about it
The Error
Unzipped size must be smaller than 262144000 bytes
# Or you might see:
Resource handler returned message: "Unzipped size must be smaller
than 262144000 bytes" (RequestToken: xxx, HandlerErrorCode: InvalidRequest)This happens when your Lambda deployment package (including dependencies) exceeds 250 MB unzipped. Chromium alone is ~280 MB. You're stuck before you even start.
Why This Happens
Lambda Limits
- 250 MB unzipped deployment size
- 50 MB zipped upload limit
- Lambda Layers count toward this
Chromium Size
- Full Chromium: ~280 MB
- chromium-min: ~45 MB (stripped)
- + Puppeteer/Playwright: ~50 MB
Even with stripped-down Chromium builds, you're constantly fighting the limit. Add your application code and any other dependencies, and you hit the wall fast.
Traditional "Solutions" (And Their Problems)
1. Use Lambda Layers
Split Chromium into a separate Layer to stay under the limit.
Problems:
- Layers still count toward 250 MB total
- Layer management adds deployment complexity
- Version mismatches between Puppeteer and Chromium
- Cold starts are still brutal (~8-15 seconds)
2. Use @sparticuz/chromium
A stripped-down Chromium build for Lambda (~45 MB).
npm install @sparticuz/chromium puppeteer-coreProblems:
- Missing fonts, emoji, some rendering features
- Maintenance burden when Chromium updates
- Still ~100 MB with Puppeteer, leaving little room for your code
- Cold starts still 5-10 seconds
3. Use Container Images
Lambda supports container images up to 10 GB.
Problems:
- ECR costs and complexity
- Slower cold starts (pulling larger images)
- More infrastructure to manage
- Still dealing with Chrome memory issues
The Simpler Solution: Don't Run Chrome in Lambda
Instead of fighting Lambda limits, use an API that runs Chrome elsewhere:
// Your Lambda function - simple HTTP call, no Chrome needed
const response = await fetch("https://api.riddledc.com/v1/run", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({ url: "https://example.com" })
});
const screenshot = await response.arrayBuffer();
// Done. No Chromium. No layers. No size limits.Added to your deployment
Screenshot returned
Per screenshot
Time Comparison
| Approach | Setup Time | Cold Start | Ongoing Maintenance |
|---|---|---|---|
| Puppeteer + Layers | 4-8 hours | 8-15 seconds | Monthly updates |
| @sparticuz/chromium | 2-4 hours | 5-10 seconds | Version tracking |
| Container Image | 4-6 hours | 10-20 seconds | ECR + Image builds |
| Riddle API | 5 minutes | 0 (no Chrome) | None |
Skip the Lambda Chrome Struggle
Get screenshots without managing Chromium infrastructure.