October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk6 min

How to Capture a Website Screenshot with Puppeteer on AWS Lambda

A practical guide to capturing website screenshots with Puppeteer on AWS Lambda, covering Chromium deployment, runtime settings, responses, S3 and troubleshooting.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To capture a website screenshot with Puppeteer on AWS Lambda, deploy puppeteer-core alongside a Lambda-compatible Chromium binary, launch Puppeteer with that package’s settings, navigate to a validated URL, and call page.screenshot(). The example below returns a PNG in the Lambda response; for durable or larger images, save the file to Amazon S3 instead. Match the browser package, Puppeteer version, runtime and CPU architecture, and size memory and temporary storage for your workload.

Build a Lambda screenshot handler

This Node.js ES-module example follows the launch pattern in the @sparticuz/chromium README. It assumes the package and puppeteer-core are included in your deployment, and that the selected Chromium distribution is compatible with your Lambda runtime and architecture. It is an implementation pattern, not a guarantee that every target page will finish loading or fit in a synchronous response.

As an Amazon Associate I earn from qualifying purchases.

import puppeteer from "puppeteer-core";
import chromium from "@sparticuz/chromium";

export const handler = async (event) => {
  const url = event?.url;
  if (typeof url !== "string") {
    return { statusCode: 400, body: "Provide a URL string in event.url" };
  }

  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    return { statusCode: 400, body: "Invalid URL" };
  }
  if (!["http:", "https:"].includes(parsed.protocol)) {
    return { statusCode: 400, body: "Only HTTP and HTTPS URLs are supported" };
  }

  let browser;
  try {
    browser = await puppeteer.launch({
      args: chromium.args,
      defaultViewport: chromium.defaultViewport,
      executablePath: await chromium.executablePath(),
      headless: chromium.headless,
    });

    const page = await browser.newPage();
    page.setDefaultNavigationTimeout(25000);
    await page.goto(parsed.href, { waitUntil: "networkidle0" });
    const screenshot = await page.screenshot({ type: "png" });

    return {
      statusCode: 200,
      headers: { "content-type": "image/png" },
      body: screenshot.toString("base64"),
      isBase64Encoded: true,
    };
  } catch (error) {
    console.error("Screenshot capture failed", error);
    return { statusCode: 502, body: "Could not capture the requested page" };
  } finally {
    if (browser) await browser.close();
  }
};

The URL check limits the protocol, but it is not a complete security boundary. If callers are not fully trusted, apply an allowlist or other server-side controls to prevent access to internal services and resources. Set the navigation timeout to fit within the Lambda invocation budget; the 25-second value here is an example, not a universal setting.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What the handler does

  • chromium.args, chromium.defaultViewport, chromium.executablePath() and chromium.headless provide the browser launch configuration exposed by the package.
  • networkidle0 waits for network activity to become idle. Pages with persistent connections or continuous requests may not reach that state, so choose a different navigation condition or an explicit selector or delay when appropriate.
  • page.screenshot() returns image bytes. The handler encodes those bytes as base64 and marks the response accordingly for a caller that supports binary Lambda responses.
  • The finally block closes the browser on success and on errors after launch.

Choose a deployment package and browser build

Packaging is a core design decision because Chromium is large and its binary must match the environment. AWS documents a 50 MB zipped limit for direct ZIP uploads through the console, API or SDK, and a 250 MB unzipped deployment-package contents limit, including layers and custom runtimes. Lambda container images can be up to 10 GB uncompressed. Check the current AWS Lambda quotas for the upload path and deployment you use.

Choice When it fits Trade-offs
ZIP package Dependencies and browser assets fit within the applicable ZIP and unzipped limits. Simpler deployment shape when it fits, but package size and binary inclusion need attention.
Container image Browser dependencies make ZIP limits awkward or you need a controlled operating-system environment. Allows images up to 10 GB uncompressed, but requires building and publishing an image. AWS’s older Puppeteer example uses Node.js 12; treat its architecture as illustrative, not as current runtime guidance.

The Sparticuz README warns that @sparticuz/chromium should be externalized when using bundlers such as esbuild or webpack because it locates binary resources by relative paths. If the deployment reports that /var/task/bin is missing, check bundler externalization and ensure the documented browser assets are included, provided through a Lambda layer, or supplied through a supported external pack.

Align architecture and versions

The Sparticuz README describes @sparticuz/chromium as containing x64 binaries. For arm64, it directs users to @sparticuz/chromium-min with an arm64 layer or remote pack. Confirm the selected binary distribution, Lambda architecture, Node.js runtime and Puppeteer version together before deployment. The package’s versioning follows Chromium releases rather than semantic versioning; the README warns that breaking changes may occur even at patch level. Pin and validate versions as a set rather than assuming an upgrade is backward-compatible.

Set memory, timeout and temporary storage

AWS documents Lambda memory from 128 MB through 10,240 MB and a standard function timeout maximum of 900 seconds. CPU allocation increases with memory. The Sparticuz README recommends at least 512 MB RAM and says 1,600 MB or more is recommended. Treat those figures as package guidance: actual needs depend on the page, viewport, fonts, concurrency and image dimensions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Lambda’s configurable ephemeral storage ranges from 512 MB to 10,240 MB at /tmp. Chromium extracts compressed browser files there on first use and can reuse the extracted binary in a warm execution environment. Leave room for the browser profile and screenshot artifacts, and remove generated files when they are no longer needed. AWS states that data stored in /tmp is encrypted at rest with a key managed by AWS.

Return the image or save it to S3

Return a modest image synchronously

The example returns PNG bytes as base64 with content-type: image/png. Use this when the image and encoded response fit the synchronous request-and-response payload quotas and the caller expects an image response. Base64 increases the payload size, so account for that overhead and check the current Lambda payload limits before relying on direct responses.

Persist screenshots in S3

For durable output, or when an image is too large for a synchronous response, write the screenshot bytes to an S3 object and return an object key or a URL created under your application’s access policy. AWS’s 2021 architecture example illustrates a Puppeteer Lambda saving screenshots to S3 and a separate function invoking captures for multiple URLs. Its Node.js 12 image is historical, not a current runtime recommendation.

Develop locally without mixing browser paths

The Chromium binary included with Sparticuz’s package is Linux-only, so it will not run directly on macOS or Windows. For local development, use a locally installed browser and make the launch choice explicit, for example through an environment variable. Keep the packaged executable path as the production Lambda branch; do not let a developer’s local browser path become the deployed default.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common failures

  • Chromium will not launch or the executable cannot be found: confirm the browser package is included, its binary assets are available, and the handler awaits chromium.executablePath().
  • /var/task/bin is missing: check whether your bundler externalized @sparticuz/chromium and whether the package’s binary resources were included using its documented deployment method.
  • The invocation times out: inspect the page’s load behavior and chosen navigation condition, set an appropriate navigation timeout, and tune the Lambda timeout within its documented maximum.
  • The invocation runs out of memory or rendering is slow: measure representative pages and increase memory as needed; memory also affects CPU allocation. No one allocation is established as sufficient for every site.
  • Temporary storage fills: inspect /tmp usage, configure ephemeral storage for the workload, and clean up generated artifacts where appropriate.
  • The browser starts locally but not in Lambda: verify that the deployed architecture matches the selected Chromium build or its documented arm64 distribution method.
  • An upgrade breaks launch or rendering: re-check compatibility among the chosen Chromium package release, Chromium version, Puppeteer and Lambda runtime; package patch releases can include breaking changes.
  • A page never reaches networkidle0: pages with ongoing requests can prevent that condition. Use a navigation condition that suits the page, then wait for a meaningful selector or a deliberate delay if the screenshot needs content to finish rendering.

Or skip the browser setup

If you need screenshots without packaging and maintaining Chromium in Lambda, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a screenshot 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 details. Before capture, it accepts cookie or consent banners and removes 60+ known consent platforms, newsletter popups and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info and capture_pdf for AI agents using Claude, Cursor or another MCP client. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.