Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Run Playwright in Lambda by shipping your code, a pinned Playwright package, the matching browser binaries and Linux libraries, and Lambda’s runtime interface client in a container image. Build the image for the function’s architecture with Docker Buildx and --provenance=false, test it through the Lambda Runtime Interface Emulator (RIE), then publish it to Amazon ECR. Playwright is headless by default; install Xvfb and wrap the runtime with xvfb-run only when your workflow genuinely needs a headed browser.
What the container must contain
A Lambda browser image is self-contained. At minimum, include:
- Your handler and its application dependencies.
- A Playwright language package at a pinned version.
- Browser executables installed for that exact Playwright version.
- System libraries required by the selected browser.
- The Lambda Runtime Interface Client (RIC) when the base image is not an AWS Lambda language image.
- Xvfb and its supporting packages only if headed execution is part of the design.
Playwright’s published images bundle browser binaries and system dependencies, but they do not install your project’s Playwright package for you. Keep the image tag and package version identical; a mismatch commonly produces an executable-not-found error.
Choose a base-image strategy
Playwright image plus the Lambda RIC
A Playwright image is convenient because the browser libraries are already present. It is a non-AWS base, so install the language-specific RIC and provide the Lambda entrypoint and handler command yourself. This approach is useful when Chromium compatibility is more important than minimizing the image.
#1 Best Overall
AWS language base image
An AWS Node.js, Python, or other language base image supplies Lambda’s runtime integration. You must still install Playwright, the browser binary, and every Linux library that browser requires. Minimal images can need more dependency work than a Playwright-derived image.
OS-only or another Linux image
A custom or OS-only image is supported, but it must include the RIC for your language. Use a glibc-based distribution compatible with the Playwright browser build. Alpine-style images can require a different browser build and additional compatibility testing.
Pin Playwright and install Xvfb
Pick one Playwright version and use it everywhere: the Docker image tag, your package manifest, and the browser installation step. The following Node.js example uses a version variable so you can select a published tag and keep it synchronized rather than relying on an unpinned latest image.
Project files
package.json:
{
"name": "lambda-playwright",
"private": true,
"type": "module",
"dependencies": {
"@playwright/test": "1.55.0",
"aws-lambda-ric": "3.1.0"
}
}
Replace both version values with the same Playwright release you intend to deploy. The image tag in the Dockerfile must use that release too.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →index.mjs:
import { chromium } from '@playwright/test';
export const handler = async (event) => {
const target = event?.url || 'https://example.com';
const browser = await chromium.launch({
headless: process.env.HEADFUL !== 'true',
args: ['--no-sandbox', '--disable-dev-shm-usage']
});
try {
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
await page.goto(target, { waitUntil: 'networkidle', timeout: 45000 });
const body = await page.screenshot({ type: 'png', fullPage: true });
return {
statusCode: 200,
headers: { 'content-type': 'image/png' },
isBase64Encoded: true,
body: body.toString('base64')
};
} finally {
await browser.close();
}
};
The --no-sandbox flag is commonly needed in containerized Lambda environments. Treat it as a deployment decision and test your security requirements; do not add unrelated Chromium flags until a measured failure requires them. Always close the browser in a finally block so warm invocations do not accumulate processes.
Dockerfile with optional Xvfb
ARG PW_VERSION=1.55.0
FROM mcr.microsoft.com/playwright:v${PW_VERSION}-noble
WORKDIR /var/task
RUN apt-get update
&& apt-get install -y --no-install-recommends xvfb
&& rm -rf /var/lib/apt/lists/*
COPY package*.json ./
RUN npm ci --omit=dev
COPY index.mjs ./
# Use this entrypoint when headed mode is required.
ENTRYPOINT ["/usr/bin/xvfb-run", "-a", "/usr/local/bin/npx", "aws-lambda-ric"]
CMD ["index.handler"]
Use a real, published Playwright tag in PW_VERSION, and set the dependency version to exactly the same number. If your image places npx or xvfb-run elsewhere, locate those binaries during the image build and adjust the paths. For a headless-only function, remove the Xvfb package and make the entrypoint ["/usr/local/bin/npx", "aws-lambda-ric"]; Playwright does not need a virtual display in that mode.
Rank #2
Build for Lambda’s architecture
Choose the same architecture for Docker, ECR, and the Lambda function. Lambda supports x86_64 and arm64, but browser availability and native dependencies must be validated for the exact combination you select.
docker buildx build
--platform linux/amd64
--provenance=false
--build-arg PW_VERSION=1.55.0
-t lambda-playwright:1.55.0
--load .
Use linux/arm64 instead when the function is configured for arm64 and the selected browser build supports it. Lambda requires the provenance option to be disabled in the documented container-image workflow. Keep the uncompressed image, including all layers, below Lambda’s 10 GB maximum.
Reduce image size and startup work
- Use a multi-stage build if you compile assets or have development-only packages.
- Run
npm ci --omit=devin the final stage. - Copy only the handler, lockfile, and production assets into the runtime layer.
- Do not install every browser if the function uses only Chromium.
- Remove package-manager caches and temporary build files.
A smaller image usually downloads and initializes faster, but do not remove a library merely because the image still builds; launch the browser and exercise a real page after every dependency change.
Test locally with the Lambda Runtime Interface Emulator
Before pushing to ECR, invoke the image through the same HTTP contract Lambda uses. Download the Lambda RIE for your host, place it in the project directory, and run:
docker run --rm
-p 9000:8080
--shm-size=1g
-e HEADFUL=false
-v "$PWD/aws-lambda-rie:/aws-lambda-rie"
--entrypoint /aws-lambda-rie
lambda-playwright:1.55.0
/usr/bin/xvfb-run -a /usr/local/bin/npx aws-lambda-ric index.handler
In practice, you can bake the RIE into a local-only wrapper or use the RIE command supplied for your operating system. The important checks are the Lambda invoke endpoint, the image entrypoint, and the handler name.
curl -sS
-XPOST
'http://localhost:9000/2015-03-31/functions/function/invocations'
-d '{"url":"https://example.com"}'
-o response.json
For browser diagnostics, set DEBUG=pw:browser in the container environment. Confirm that the response contains an image, navigation reaches the intended URL, fonts and lazy-loaded content appear, and the process exits cleanly after a timeout or failed navigation.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #3
Headed-mode smoke test
Playwright launches headless browsers by default. On Linux, headed execution requires Xvfb. The documented pattern is:
xvfb-run -a npx playwright test
For the Lambda handler above, set HEADFUL=true and keep the RIC command wrapped by xvfb-run. If no headed feature is needed, leave HEADFUL=false and omit Xvfb to reduce complexity.
Deploy the image to Lambda
- Create an Amazon ECR repository in the same AWS Region where you will run the function.
- Authenticate Docker to ECR, tag the local image with the repository URI, and push it.
- Create the Lambda function with package type Image, select the same architecture used by Buildx, and provide the image URI.
- Set memory and timeout from measurements. Browser startup, JavaScript-heavy pages, PDF generation, and full-page screenshots may need materially more than a trivial handler.
- Configure environment variables such as
HEADFUL, navigation timeout, target restrictions, and log level. - Invoke the deployed function with a representative URL, not only a static test page.
Grant only the AWS permissions your function needs. If the function writes screenshots, use /tmp for temporary files and stream or upload results before the invocation ends. Lambda’s writable temporary directory is not a durable store and can persist between warm invocations, so clean up files whose names are not reused safely.
Operational decisions that affect reliability
Memory, timeout and concurrency
Measure browser launch and page work under your real concurrency. Increase the timeout above the slowest expected navigation, but retain an upper bound so a dead page does not consume an invocation indefinitely. More memory also supplies more CPU in Lambda, which can shorten browser startup, but the correct value is workload-specific; the available sources do not establish a universal setting.
Cold starts and warm reuse
Launching one browser per invocation is simple and isolates failures. Reusing a browser between warm invocations can reduce launch overhead, but requires strict context cleanup and recovery when a browser process dies. Never assume a warm execution environment will remain available.
Temporary storage and artifacts
Write PDFs and screenshots to unique paths under /tmp, check available space, and delete them after upload. Large full-page captures and browser caches can fill temporary storage even when the container image itself is within the 10 GB limit.
Browser selection
Validate Chromium, WebKit, or Firefox independently. A community Lambda container example reported Chromium and WebKit working while Firefox needed additional tuning; that is implementation evidence, not a guarantee for every Playwright release, architecture, or image. Test the exact browser you will deploy.
Common failures and fixes
“Executable doesn’t exist” or browser launch cannot find a binary
Check that the Playwright package, image tag, and browser installation all use the same version. Rebuild without stale Docker layers and verify the browser path inside the image.
Chromium crashes, hangs, or runs out of memory
Run the container with Docker’s documented initialization and IPC settings during local testing, including --init and --ipc=host where appropriate. Then reproduce through the RIE with the same architecture and memory profile. Remove unneeded tabs and close every context and browser.
Headed launch fails with “display” errors
Install Xvfb, ensure a display is created, and invoke the process through xvfb-run -a. Check that HEADFUL=true is actually reaching the handler. If the workload is compatible with headless mode, turn headed execution off instead.
Lambda rejects the image before invocation
Rebuild for the function architecture and include --provenance=false. Confirm that the pushed image is a Docker/OCI image and that its uncompressed layers total less than 10 GB.
Navigation times out or returns a blank page
Capture Playwright browser logs, test the URL inside the same container, and distinguish DNS, TLS, bot checks, JavaScript errors, and a page that genuinely renders blank. Use an explicit wait condition rather than an arbitrary sleep when the page has a reliable selector. Set a finite timeout and return a structured error so callers can retry safely.
Best Value
- Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
- Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
Firefox behaves differently from Chromium
Do not infer support from another browser’s result. Pin the browser, run a representative suite on the target architecture, and apply browser-specific launch or dependency changes only after reproducing the failure.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.When a managed screenshot endpoint is simpler
If the goal is a clean screenshot rather than owning browser packaging, ScreenshotNeo provides a website screenshot API and MCP server. It removes cookie-consent banners, newsletter popups and chat widgets before capture; only clean shots are billed, while bot checks, blank pages, timeouts, failed loads and cache hits are not billed and are identified by response headers.
Or skip the browser setup
Make one request to the ScreenshotNeo API. The API documentation lists all options and compatible parameter names.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
You can also call it from Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Or Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
await Bun.write('shot.webp', res);
ScreenshotNeo supports PNG, JPEG, WebP and PDF output, full-page captures with lazy images loaded, CSS-selector element shots, dark mode, device presets, custom viewports, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, usage reporting and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
Recommended Free Tools
The Free plan includes 1,000 screenshots per month with no card. Paid plans are Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing provides two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to start without a card.
Frequently Asked Questions
Can I deploy a Playwright Lambda image without Xvfb?
Yes. Playwright is headless by default. Omit Xvfb when your code does not require headed browser behavior; add it only for headed workflows.
What does –provenance=false change?
It disables provenance metadata in the Docker build, an option AWS requires for Lambda-compatible container images in its current examples.
Is the 10 GB limit measured from the compressed image shown in a registry?
No. Lambda’s limit is 10 GB uncompressed across all image layers, so inspect the expanded size rather than relying on registry transfer size.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Should I assume Firefox works because Chromium works?
No. Browser support is version-, image- and architecture-specific. Run a Firefox test suite in the exact image and Lambda architecture you plan to operate.
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.

