Run Puppeteer in a Lambda container by starting from an AWS Node.js base image, installing puppeteer-core and a Lambda-compatible Chromium build, and passing Chromium’s actual path to puppeteer.launch(). Build the image for the same CPU architecture as the function, keep browser extraction and profiles under writable /tmp, and test the container through the Lambda Runtime Interface Emulator before publishing it.
Choose the Lambda container model first
AWS supports three container-image approaches. Your choice determines how the runtime starts and how much of the operating-system setup you own.
| Approach | What you get | What you must handle |
|---|---|---|
| AWS Node.js base image | Node.js runtime, Lambda entrypoint conventions and AWS’s supported image layout. | Install Puppeteer and Chromium, then set the function handler. |
| AWS OS-only base image | AWS’s minimal operating-system image. | Add Node.js and the Lambda Runtime Interface Client (RIC), then install the browser stack. |
| Non-AWS base image | Complete control over the distribution and packages. | Include a compatible RIC and all runtime, shared-library and browser dependencies yourself. |
For most Puppeteer deployments, the AWS Node.js image is the least fragile starting point. Node.js 20-and-later AWS images use Amazon Linux 2023 and its microdnf package manager (also available through the dnf name). When you test an AL2023 image locally, Docker 20.10.10 or newer is required.
Constraints that affect the design
- Architecture: build for the function’s configured architecture. Use
linux/amd64for x86_64 functions orlinux/arm64for ARM64 functions. A mismatch can make Chrome fail before your handler runs. - Image size: Lambda allows a maximum uncompressed container-image size of 10 GB, including all layers. AWS recommends keeping the image manifest below 25,400 bytes.
- Writable storage: Lambda’s deployment directories are not writable. Chromium extraction, its profile, temporary downloads and generated PDFs or screenshots belong in
/tmp. Configure enough ephemeral storage for your browser workload. - Browser binary: Puppeteer does not make an arbitrary system Chrome compatible. The Linux Chromium binary must be present in the image or extracted at runtime, and you should pass its real path explicitly when you manage the browser.
Build a working Node.js 20 image
1. Create the project files
Use puppeteer-core when Chromium is supplied separately. The following package file enables ECMAScript imports:
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →#1 Best Overall
- Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
- Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
- Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
- Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
- 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
{
"name": "lambda-puppeteer",
"version": "1.0.0",
"type": "module",
"private": true
}
Install the two runtime packages and commit the resulting lockfile so builds remain reproducible:
npm install puppeteer-core @sparticuz/chromium
Pin the exact @sparticuz/chromium version in your lockfile and verify it during image builds. Sparticuz follows Chromium’s release cycle and can introduce breaking changes at the patch level, so do not assume that a future package release will remain interchangeable.
2. Add the Lambda handler
Create index.mjs. This handler accepts either a direct invocation object containing url or an API Gateway-style body containing JSON with that property.
import puppeteer from "puppeteer-core";
import chromium from "@sparticuz/chromium";
export const handler = async (event) => {
const input = typeof event?.body === "string"
? JSON.parse(event.body)
: (event?.body || event || {});
const target = input.url;
if (!target) {
return {
statusCode: 400,
body: JSON.stringify({ error: "Provide a url property" })
};
}
try {
new URL(target);
} catch {
return {
statusCode: 400,
body: JSON.stringify({ error: "url must be an absolute URL" })
};
}
let browser;
try {
browser = await puppeteer.launch({
args: await puppeteer.defaultArgs({
args: chromium.args,
headless: "shell"
}),
executablePath: await chromium.executablePath(),
headless: "shell"
});
const page = await browser.newPage();
await page.goto(target, {
waitUntil: "networkidle0",
timeout: 30000
});
return {
statusCode: 200,
headers: { "content-type": "application/json" },
body: JSON.stringify({
title: await page.title(),
url: page.url()
})
};
} finally {
if (browser) {
await browser.close();
}
}
};
chromium.executablePath() resolves the binary that the package makes available. Sparticuz extracts its binary under /tmp on first use and can reuse it on warm starts. The networkidle0 condition waits until there are no active network connections; pages with analytics, sockets or continuously polling requests may therefore need a different wait strategy, such as a selector wait or a bounded delay.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
- 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
- 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
- Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
- 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
- What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.
3. Define the Dockerfile
FROM public.ecr.aws/lambda/nodejs:20
WORKDIR ${LAMBDA_TASK_ROOT}
COPY package.json package-lock.json* ./
RUN npm install --omit=dev
COPY index.mjs ./
CMD ["index.handler"]
The AWS Node.js image supplies the Lambda runtime. Keeping only production dependencies in the final layer reduces transfer size and cold-start work. If you choose an OS-only or non-AWS image instead, add the Lambda Runtime Interface Client and configure its entrypoint as required by that image.
Build for the function’s CPU architecture
Build with Docker Buildx and select the same architecture configured in Lambda:
# x86_64 function
docker buildx build --platform linux/amd64 -t puppeteer-lambda:latest --load .
# ARM64 function
docker buildx build --platform linux/arm64 -t puppeteer-lambda:latest --load .
Do not mix an ARM64 Chromium package with an x86_64 image (or the reverse). An architecture error is often reported as an executable-format failure or as a browser that exits immediately. The browser package, native Node modules and base image all need to agree.
Test the image locally before deployment
Start the container
docker run --rm -p 9000:8080 puppeteer-lambda:latest
AWS’s Lambda Runtime Interface Emulator exposes the local invocation endpoint on port 9000. In another terminal, invoke the handler with a URL:
Rank #3
- Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
- Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
- Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
- Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
- What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.
curl -XPOST
"http://localhost:9000/2015-03-31/functions/function/invocations"
-d '{"url":"https://example.com"}'
A successful response is a JSON object containing the page title and the final URL. This test exercises image startup, module loading, Chromium extraction, navigation and browser shutdown without waiting for a cloud deployment. Test a second invocation while the container remains running to expose warm-start and /tmp reuse problems.
Test the same architecture you deploy
On an x86 workstation, an ARM64 image may require emulation and run substantially slower. That is useful for correctness but not for measuring production latency. For meaningful cold-start observations, test on a machine or CI runner that matches the Lambda architecture, then measure the deployed function separately.
Decide between Puppeteer, puppeteer-core and Chromium packaging
| Choice | Browser source | Operational consequence |
|---|---|---|
puppeteer |
Puppeteer normally downloads a compatible Chrome for Testing during installation. | Simple dependency setup, but the downloaded browser increases image size and must be available in the final image layer. |
puppeteer-core plus @sparticuz/chromium |
Chromium is supplied by the serverless package and extracted when needed. | Explicit executablePath, Lambda-oriented launch arguments and writable /tmp are required. |
| System or custom Chromium | A binary you install or copy into the image. | You own shared libraries, executable permissions, updates and Puppeteer/browser compatibility. |
Puppeteer’s installation documentation lists approximate Chrome for Testing download sizes of 170 MB for macOS, 282 MB for Linux and 280 MB for Windows. Those figures describe the downloads, not your compressed image transfer or Lambda’s uncompressed limit. Whichever source you use, verify that the binary actually exists at runtime and that its release is compatible with your Puppeteer version.
Launch options and page behavior that matter in Lambda
Use an explicit executable path
If you manage Chromium yourself, do not rely on Puppeteer’s default discovery. Set executablePath to the value returned by the package (or to the path where your image stores its binary). A path that works on a developer laptop may not exist in the Lambda filesystem.
Recommended Free Tools
Rank #4
- Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
- Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
- Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
- Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
- Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Choose a wait condition deliberately
networkidle0is useful for mostly static pages but can time out on applications with persistent connections.- A selector wait is better when a specific report, chart or component marks readiness.
- A short, bounded delay can cover late-rendering content when no reliable selector exists; keep a navigation timeout so one page cannot consume the entire invocation.
Handle the sandbox carefully
Puppeteer’s troubleshooting guidance allows --no-sandbox when you absolutely trust the content opened in Chrome. Use that flag only when the container cannot provide a usable Chrome sandbox, because it weakens browser isolation. First check the base image, permissions and Chromium arguments; do not add the flag reflexively.
Close every browser
Always close the browser in a finally block. A leaked process can consume memory across warm invocations and eventually cause timeouts or out-of-memory failures. If you later introduce a global browser for warm reuse, add health checks and recreate it when the process has exited.
Troubleshoot failures in a useful order
| Symptom | Likely cause | Fix |
|---|---|---|
Exec format error or Chrome exits immediately |
Image, Node native modules and Chromium were built for different architectures. | Rebuild with --platform linux/amd64 or --platform linux/arm64 to match the function, then redeploy all layers. |
Failed to launch the browser process with a missing .so file |
The selected image lacks a shared library required by that Chromium build. | Use a Lambda-compatible Chromium package, install the missing library in the image, or switch to an image/package combination documented for the same distribution. |
ENOENT for the executable |
executablePath points to a laptop path, a build-only path or a file that was never copied. |
Log the resolved path, verify it inside the running container, and pass await chromium.executablePath() or the actual installed location. |
| Browser starts, then crashes after several calls | /tmp is full, profiles accumulate or browser processes are not closed. |
Close the browser, remove unnecessary artifacts, increase ephemeral storage and inspect free space during local repeated invocations. |
Navigation timeout at networkidle0 |
The target keeps connections open or loads resources indefinitely. | Use a selector or bounded delay, block unnecessary resources where appropriate, and retain a finite navigation timeout. |
| Sandbox startup error | The container cannot provide the permissions or kernel support Chrome expects. | Correct permissions and launch arguments first. Only for content you absolutely trust, consider --no-sandbox and document the isolation trade-off. |
| Works locally but fails in Lambda | Different architecture, environment variables, writable paths, network access or package versions. | Run the exact image through the local emulator, inspect the resolved executable and /tmp, then compare the deployed function’s architecture and settings. |
| Large upload or slow cold start | Chrome and operating-system layers are oversized. | Use puppeteer-core with one verified Chromium build, remove development dependencies, consolidate layers and stay below Lambda’s 10 GB uncompressed limit. |
Reliability, performance and cost considerations
- Cold starts: Chromium extraction, image transfer and browser launch add work before the first page. Smaller production dependencies and a single browser build reduce that work, but the exact latency depends on page complexity, architecture and allocated memory.
- Warm starts: The extracted Sparticuz binary can be reused from
/tmp. Treat the directory as temporary: code must recreate missing files and avoid assuming that one container instance will remain available. - Memory: Rendering several tabs or large PDFs can exhaust the function’s memory even when the image itself is small. Close pages promptly and avoid parallel tabs unless you have measured the workload.
- Network: Lambda still needs network access to the target site, DNS and any assets required for rendering. Private targets may require VPC configuration, which can add its own connectivity and startup considerations.
- Billing: Container-image size and browser work affect startup and execution time, while Lambda billing itself follows your AWS account’s configured pricing. No universal cost per screenshot is established, so measure your function with representative URLs rather than applying a generic estimate.
Or skip the browser setup
If your goal is a clean screenshot or PDF rather than maintaining Chrome in Lambda, ScreenshotNeo provides a website screenshot API and MCP server. It accepts a URL in one request, handles the browser environment for you and can return PNG, JPEG, WebP or PDF. Cookie-consent banners, newsletter popups and chat widgets are removed before capture. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.
One-call examples
See the complete parameter list in the ScreenshotNeo documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Every feature is included on every plan; 1,000 screenshots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.
Best Value
- 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
- Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
- Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
- HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
- What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.
FAQ
Can I use a different Chromium package?
Yes, provided its Linux binary and shared libraries match the image and its CPU architecture. Replace the executable path and launch arguments, then verify the exact combination in the built container.
Should I return a screenshot from the Lambda handler?
You can return binary data through an integration that supports base64 responses, or write the artifact to object storage and return a URL. Keep temporary browser output in /tmp and remove it after the response when it is no longer needed.
Why pin both Puppeteer and Chromium?
Puppeteer controls the browser protocol while Chromium supplies the executable. Pinning both lets you reproduce a known pairing and detect incompatibilities during the image build instead of during a production invocation.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFrequently Asked Questions
Can I use a different Chromium package?
Yes, provided its Linux binary and shared libraries match the image and its CPU architecture. Replace the executable path and launch arguments, then verify the exact combination in the built container.
Should I return a screenshot from the Lambda handler?
You can return binary data through an integration that supports base64 responses, or write the artifact to object storage and return a URL. Keep temporary browser output in /tmp and remove it after the response when it is no longer needed.
Why pin both Puppeteer and Chromium?
Puppeteer controls the browser protocol while Chromium supplies the executable. Pinning both lets you reproduce a known pairing and detect incompatibilities during the image build instead of during a production invocation.
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.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →

