Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsTo take screenshots with Puppeteer on AWS Lambda, deploy a Lambda-compatible Chromium build alongside Puppeteer, make the browser’s runtime files writable, and save the resulting image somewhere durable such as Amazon S3. Local Chrome is not a substitute for a Linux-compatible Lambda browser. The setup below uses a Node.js handler pattern; choose a matching package, runtime, and CPU architecture, then test with the pages and concurrency you expect to serve.
Choose a Lambda packaging approach
Puppeteer needs a compatible browser binary as well as its Node.js package. Its troubleshooting guidance points Lambda users to a serverless Chromium package. Do not deploy a macOS or Windows Chrome binary and expect it to run in Lambda.
Container image
A container image lets you package browser dependencies and operating-system libraries together. AWS has a worked architecture example that runs Puppeteer in Lambda and sends screenshots to S3, with a separate function fanning out work to screenshot workers. Its Dockerfile uses the historical amazon/aws-lambda-nodejs:12 base image, so use it to understand the workflow, not as a current runtime recipe. Select a currently supported Lambda runtime and apply least-privilege permissions for your own storage workflow.
ZIP package or layer
For ZIP- or layer-based deployments, the Sparticuz Chromium README documents a full package and a -min package. The full package carries its Chromium files; -min omits compressed Chromium files, which you must provide separately, for example in /opt/chromium. Use the package’s asynchronous executable-path resolver and recommended launch arguments, and check its current release notes before pinning versions.
#1 Best Overall
Match the binary artifact to the Lambda architecture. Sparticuz documents x64 binaries in its npm package; for arm64 it describes using the -min package with a released arm64 Lambda layer or remote pack, with arm64 binaries available starting with Chromium v135. Verify that the selected artifact, Lambda architecture, and Puppeteer version are compatible before deployment.
Implement a screenshot handler
This example shows the essential handler flow: receive a URL, launch the package-provided browser, take a screenshot, and persist it to S3. It is a pattern, not a complete deployment template: configure your function’s current runtime, environment variables, IAM permissions, and input validation for your application.
const chromium = require('@sparticuz/chromium');
const puppeteer = require('puppeteer-core');
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const s3 = new S3Client({});
exports.handler = async (event) => {
const url = event.url;
const bucket = process.env.SCREENSHOT_BUCKET;
const key = event.key || `screenshots/${Date.now()}.png`;
if (!url || !bucket) {
throw new Error('Provide event.url and SCREENSHOT_BUCKET');
}
let browser;
try {
browser = await puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: chromium.headless,
userDataDir: '/tmp/puppeteer-profile'
});
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });
const image = await page.screenshot({ type: 'png', fullPage: true });
await s3.send(new PutObjectCommand({
Bucket: bucket,
Key: key,
Body: image,
ContentType: 'image/png'
}));
return { bucket, key };
} finally {
if (browser) await browser.close();
}
};
This assumes the dependencies and browser assets are included through your selected package, layer, or image, and that the function can write to /tmp. A production handler should also restrict allowed URLs and destinations to prevent callers from using it to fetch unintended internal resources.
Persist and scale output deliberately
Lambda’s local temporary storage is not durable output storage. The AWS example writes screenshots to S3; use S3 or another durable destination if callers need to retrieve the result after the invocation. For a workload involving many URLs, separate request fan-out from per-URL capture workers rather than making one invocation do unbounded browser work. The AWS example demonstrates that architectural split, but does not establish a current throughput figure.
Make the browser work in Lambda
Use writable runtime paths
Lambda execution environments have read-only locations outside their temporary storage. Puppeteer advises placing Chrome configuration and cache directories under /tmp when running in a read-only environment. Set environment variables before launch and set the browser profile explicitly if needed:
process.env.XDG_CONFIG_HOME = '/tmp/.config';
process.env.XDG_CACHE_HOME = '/tmp/.cache';
// In the launch options:
userDataDir: '/tmp/puppeteer-profile'
Ensure the directories exist if your chosen package or launch path does not create them. Confirm the actual executable path returned by the browser package rather than assuming a local development path will exist in the deployed artifact.
Rank #3
- Connect various PLCs, fieldbus instruments and devices to the Cloud Servers over WAN by MQTT protocol,
- MQTT Gateway
- Connect to Microsoft Azure, Amazon AWS, and more
Configure bundlers and browser assets
If you bundle with esbuild, webpack, Rollup, or a comparable tool, mark @sparticuz/chromium as external so the package can resolve its relative browser resources at runtime. Sparticuz associates the error The input directory "/var/task/bin" does not exist with failing to externalize the package. After building, inspect the artifact and verify that the package, layer, or separately hosted files are present where the resolver expects them.
Plan for fonts
Lambda does not provide general font faces by default, so rendering can differ from a developer machine or omit glyphs. Sparticuz documents bundled Open Sans coverage for Latin, Greek, and Cyrillic. For additional scripts or exact brand typography, provision the required fonts, for example through a Lambda layer. Its documented font locations include /var/task/.fonts, /var/task/fonts, /opt/fonts, and /tmp/fonts.
Tune memory, timeout, and browser lifecycle
Lambda’s CPU allocation scales with configured memory, while actual completion time depends on page load and network latency, data transfer, browser work, and downstream requests. AWS’s memory configuration guidance and timeout guidance support workload-specific tuning; there is no universal memory or timeout value for Puppeteer screenshots. Test representative pages, including slow and complex cases, and set the timeout to cover the expected upper end of the work without masking a stuck request.
Rank #4
Always close the browser in a finally block, as in the handler example. Close pages when finished, and await browser.close(). Sparticuz notes that Chromium can open more pages than expected and documents browser cleanup considerations, including cases where close operations hang. Also inspect retained globals and libraries across warm invocations: AWS notes that initialized global state persists in warm environments, and some libraries can accumulate memory.
Common errors and how to fix them
| Symptom | Likely cause | Checks and fix |
|---|---|---|
Chromium fails before Puppeteer connects; crashpad reports --database is required |
Chrome configuration, cache, or profile paths are not writable. | Set XDG_CONFIG_HOME and XDG_CACHE_HOME to paths under /tmp; set userDataDir under /tmp as well if needed. Verify the deployed function can write there. |
The input directory "/var/task/bin" does not exist |
The Sparticuz package’s relative browser resources were not available at runtime, commonly because a bundler included the package instead of leaving it external. | Externalize @sparticuz/chromium, inspect the deployed artifact and any layer or remote-pack assets, and confirm the executable resolver points to the deployed files. |
| Text is missing or glyphs differ from local screenshots | The Lambda environment does not have the required font faces. | Check whether the glyphs are covered by Sparticuz’s bundled Open Sans (Latin, Greek, and Cyrillic); provision additional fonts in a documented font location for other scripts or exact design matching. |
| The screenshot invocation times out | The configured timeout is too short for browser startup, page/network latency, transfer, or rendering complexity, or the workload is stalled. | Use CloudWatch Logs to locate the slow step; test the real page mix, review memory/CPU allocation, and adjust timeout and memory based on observed upper-bound workloads. |
| Warm invocations slow down or consume increasing resources | Resources or library state may be retained between invocations, or pages and browsers are not being closed. | Inspect retained globals and library behavior, close each page, and await browser closure in a finally path. |
| Handler succeeds but the screenshot is missing | The handler may have failed before storage, used an unexpected destination, or reported an error outside the caller’s view. | Check the handler result and CloudWatch Logs. AWS’s example specifically directs readers to the Puppeteer function’s logs when screenshots are missing; verify the bucket, key, and storage permissions in your own deployment. |
Do not start by adding arbitrary launch flags or increasing the timeout. Those changes do not correct a missing binary, incompatible architecture, non-writable profile path, missing font, or incorrect artifact layout. Find the failing stage in the logs first.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Choose between image, layer, and remote assets
| Approach | What it bundles | Trade-off to evaluate |
|---|---|---|
| Lambda container image | Browser dependencies and OS libraries can be packaged with the application. | Useful when you want a unified image; choose and maintain a currently supported runtime rather than copying the historical Node.js 12 example. |
| Full Sparticuz package | The package carries its Chromium files; README documents x64 npm content. | Check package size and compatibility against the target Lambda architecture and Puppeteer release. |
-min package with layer or remote pack |
The package omits compressed Chromium files; those assets must be supplied separately. The README describes arm64 layer or remote-pack options. | Can suit package-size constraints but adds asset hosting, version, architecture, and path management. |
No packaging method is established as universally best for cost, cold starts, or throughput. Measure startup and per-page time on the target runtime, region, architecture, page mix, and concurrency before making quantitative performance or cost comparisons. Also account for durable output storage and any downstream requests in the design.
Free tools Windows power users keep installed
One-click scans. No signup required.
Or skip the browser setup
If the goal is to get a screenshot rather than operate Chromium in Lambda, ScreenshotNeo is a screenshot API with a single GET request. Its endpoint returns an image or PDF:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. An MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo’s free plan.
Frequently Asked Questions
Can I use the regular `puppeteer` package instead of `puppeteer-core`?
The example uses `puppeteer-core` because the browser binary is supplied separately by the Lambda-compatible Chromium package; check the package compatibility guidance for the versions you deploy.
Does the AWS sample prove that 100,000 browser screenshots can run concurrently?
No. Its 100,000 figure describes a hypothetical load-testing scenario, not a measured Lambda screenshot capacity.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




