How to Take Screenshots in AWS Lambda (Without Chromium Layers)
Getting Chromium to run in AWS Lambda is a rite of passage nobody enjoys. The standard approach: add @sparticuz/chromium or chrome-aws-lambda, configure a Lambda layer, stay under the 250MB deployment limit, fight cold start times, then discover Lambda's /tmp storage is too small for your screenshots.
There's a simpler path: don't run Chromium in Lambda. Make an API call instead.
The Lambda function
// handler.js
export const handler = async (event) => {
const { url, filename } = event;
const res = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: {
'x-api-key': process.env.PAGEBOLT_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url,
fullPage: true,
blockBanners: true
})
});
const buffer = Buffer.from(await res.arrayBuffer());
// Save to S3, return base64, or pass downstream
return {
statusCode: 200,
body: buffer.toString('base64'),
isBase64Encoded: true,
headers: { 'Content-Type': 'image/png' }
};
};
Zero dependencies beyond Node's built-in fetch (available in Node 18+). Deployment package is kilobytes, not hundreds of megabytes. Cold starts are instant.
Save to S3
For screenshot pipelines that store results:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({});
export const handler = async (event) => {
const { url, key } = event;
const res = await fetch('https://api.pagebolt.dev/v1/screenshot', {
method: 'POST',
headers: { 'x-api-key': process.env.PAGEBOLT_API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ url, fullPage: true, blockBanners: true })
});
const buffer = Buffer.from(await res.arrayBuffer());
await s3.send(new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: key || `screenshots/${Date.now()}.png`,
Body: buffer,
ContentType: 'image/png'
}));
return { statusCode: 200, key };
};
Generate a PDF
Swap the endpoint:
body: JSON.stringify({
url,
format: 'A4',
printBackground: true
})
// and POST to /v1/pdf instead of /v1/screenshot
PDF generation via Chromium in Lambda is even harder than screenshots — Lambda's sandboxed environment often breaks Page.printToPDF. With an API call it's identical to the screenshot pattern.
Trigger on a schedule (EventBridge)
{
"source": "aws.events",
"detail-type": "Scheduled Event",
"resources": ["arn:aws:events:us-east-1:123:rule/screenshot-cron"],
"detail": {
"url": "https://yoursite.com/dashboard",
"key": "monitoring/daily.png"
}
}
Pair with an EventBridge cron rule to capture daily screenshots of any URL — competitor monitoring, status page archives, visual regression baselines.
Environment variable setup
PAGEBOLT_API_KEY=your_key_here
S3_BUCKET=your-bucket-name
Set both as Lambda environment variables in the console or via Terraform/CDK. No layers, no extensions, no binary compatibility issues.
What you skip
The @sparticuz/chromium approach requires:
- A Lambda layer (~40MB compressed)
- Setting
executablePathto the layer binary - Configuring
--single-process,--no-zygote,--disable-dev-shm-usage - Bumping Lambda memory to 1-2GB for Chromium to launch
- Accepting 5-10s cold starts when the container initializes
With an API call, your Lambda stays at 128MB, deploys in seconds, and cold starts in milliseconds. The browser runs on PageBolt's infrastructure.
Free tier: 100 requests/month, no credit card. → pagebolt.dev
Top comments (0)