ScreenshotNeo

BlogHow-to

How to Run Puppeteer on AWS EC2

Install and run Puppeteer on EC2 with distro-aware setup, architecture checks, a launch test, and fixes for common Chrome errors.

By the ScreenshotNeo team4 October 20267 min read

Puppeteer runs on AWS EC2 when the instance has a supported Node.js runtime, a Chrome or Chromium binary compatible with its CPU architecture, and that browser’s required Linux libraries. On a typical x86_64 Ubuntu instance, install Node.js 22.12 or later, install Puppeteer with its browser download enabled, add the required Ubuntu packages, and verify the browser as the same OS user that will run your service. Amazon Linux and Graviton need release- and architecture-specific browser setup.

Puppeteer is a JavaScript library for controlling Chrome or Firefox. It runs headless by default, so ordinary screenshot or page automation does not need a desktop. Check the current Puppeteer system requirements against your chosen AMI and Node.js version before setup.

1. Identify the instance image and architecture

Run these commands on the instance before choosing installation instructions:

cat /etc/os-release
uname -m
node --version 2>/dev/null || true

x86_64 is the usual 64-bit Intel or AMD architecture; aarch64 is ARM64, including AWS Graviton. Use commands for the distribution named in /etc/os-release. Do not substitute an older Amazon Linux recipe for Amazon Linux 2023 without checking package availability for that AMI.

2. Install Node.js and Puppeteer

Use a Node.js version that satisfies the current Puppeteer requirements page (currently Node.js 22.12 or later). Install Node.js using a supported method for your distribution, then create a project and install Puppeteer:

mkdir -p ~/puppeteer-ec2
cd ~/puppeteer-ec2
npm init -y
npm install puppeteer

The puppeteer package normally downloads a compatible Chrome for Testing browser; Puppeteer v21.6.0 and later also downloads chrome-headless-shell. The browser download is about 282 MB on Linux, so allow for download time and disk space. Some package-manager settings block install scripts. If Puppeteer reports that Chrome cannot be found, check that the install script ran and consult the Puppeteer installation guide.

Use the Puppeteer-managed browser when you want Puppeteer to pair its library with a compatible downloaded browser. A system-installed Chromium can be useful when you need distribution-managed packages, but you must point Puppeteer at its executable and keep browser compatibility in mind. On ARM, make sure the browser itself is ARM64; the AWS Graviton guide notes that Puppeteer’s bundled Chrome is x86.

3. Install Linux browser libraries

Chrome needs system shared libraries in addition to the browser executable. For Ubuntu or Debian, use the dependencies listed by the Puppeteer troubleshooting guide for the selected Chrome build. An example package set commonly used for Chrome on Ubuntu/Debian is:

sudo apt-get update
sudo apt-get install -y \
  ca-certificates fonts-liberation libasound2t64 libatk-bridge2.0-0 \
  libatk1.0-0 libatspi2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
  libdrm2 libexpat1 libgbm1 libglib2.0-0 libnspr4 libnss3 \
  libpango-1.0-0 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \
  libxdamage1 libxext6 libxfixes3 libxrandr2 xdg-utils

Package names can differ between OS releases. If apt cannot find a listed package, consult the upstream troubleshooting instructions for your release rather than mixing in packages from another distribution.

Amazon Linux

Puppeteer’s troubleshooting page documents this older Amazon Linux route:

sudo amazon-linux-extras install epel -y
sudo yum install -y chromium

This is not a universal Amazon Linux command. The documented setup warns that Chromium may fail to start with missing libraries such as libatk-1.0.so.0 without the repository and dependency setup. For Amazon Linux 2023, verify current repositories and package availability for the exact AMI; the research sources do not establish a complete current AL2023 dependency command.

Graviton and other ARM instances

On Graviton, install an aarch64 browser build from a package source that supports the specific image, then configure Puppeteer to use it. AWS publishes separate Ubuntu 22 and AL2023 examples in its Graviton Puppeteer guide; the examples include pinned versions and external package sources, so verify those sources and versions before using them. Do not use an x86 browser binary on an ARM instance.

4. Run a minimal headless smoke test

Save this as smoke.js in the project directory. It launches Puppeteer’s downloaded browser, opens a page, prints the title, and saves a screenshot:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
    console.log(await page.title());
    await page.screenshot({ path: 'example.png', fullPage: true });
  } finally {
    await browser.close();
  }
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
node smoke.js

Run this as the same non-root OS user and environment used by your application. If using system Chromium, set executablePath to its actual path:

const browser = await puppeteer.launch({
  headless: true,
  executablePath: '/usr/bin/chromium'
});

Replace that example path with the path on your AMI. You can locate a package-installed executable with command -v chromium or command -v chromium-browser.

5. Choose the right operating mode

Choice Use it when Trade-off
Puppeteer-managed Chrome You want Puppeteer’s install to obtain a compatible browser. Install scripts must be allowed, and the browser download consumes disk space.
System Chromium You need an OS-managed browser or a suitable ARM build. You own the executable path and browser/library compatibility.
Headless Normal automated navigation, screenshots, and page inspection. No visible desktop; usually the simplest server setup.
Headful with Xvfb A test specifically requires a display server or visible-browser behavior. Requires a virtual display such as Xvfb; AWS’s Graviton guide includes headful examples.
Manual EC2 setup You need control over the AMI, packages, and deployment. You maintain browser dependencies and updates.
Marketplace image You prefer a preconfigured starting point. Review the third-party image’s contents, maintenance, and terms; it is not an official Puppeteer distribution.

6. Diagnose launch failures

Could not find Chrome

Cause: Puppeteer’s browser download did not run, was blocked by package-manager policy, or the application uses a different user’s browser cache.

Fix: Check the installation output and install scripts, verify the expected browser cache for the runtime user, and reinstall with the browser download step enabled. If you intentionally use system Chromium, set executablePath to its real location.

Failed to launch or a missing shared object (.so)

Cause: A required Linux shared library is absent, or the selected executable does not match the operating system.

Fix: Inspect the actual browser executable, not a guessed path:

ldd /path/to/chrome | grep 'not found'

Install the missing library packages using the package manager and repositories for that AMI. Recheck with ldd after installation. Puppeteer documents this as a way to find unresolved shared libraries.

No usable sandbox!

Cause: Chrome cannot use its expected sandbox in the current host or runtime configuration.

Fix: Investigate the host’s sandbox prerequisites and run the browser as the intended non-root user. Puppeteer documents --no-sandbox only for content you are absolutely sure is trusted. Disabling the sandbox is not a routine production fix, especially if pages can contain untrusted content.

Works over SSH but fails as a service

Cause: The service can run with another OS user, HOME, cache directory, permissions, environment, executable path, or memory limit.

Fix: Compare those values between the interactive shell and service, then run the smoke test as the service account. Make sure that account can read the browser and write to its profile and cache directories.

ARM-only launch failure

Cause: The browser binary is x86 while the instance is ARM64, or the package source did not provide an ARM build.

Fix: Check uname -m and inspect the browser package or binary architecture. Install an aarch64 browser compatible with the OS and configure Puppeteer to use that executable.

7. Production notes: reliability, performance, and cost

  • Keep the browser pairing deliberate. Puppeteer’s managed download helps pair the library and browser; system browsers require you to manage compatibility as packages change.
  • Budget for installation artifacts. The Linux Chrome for Testing download is approximately 282 MB; that figure is browser download size, not total disk sizing. Include the browser cache and application files in your own disk planning.
  • Use a stable runtime identity. Run the smoke test and service with the same user, cache, permissions, and executable path.
  • Use headless mode for server automation. Add Xvfb only if a headful workflow needs a display.
  • Check failures at the source. Log the launch error and executable path, and inspect unresolved libraries with ldd. Package availability changes, so verify AMI repositories before baking an image.
  • Instance sizing is workload-specific. The Node.js minimum and browser download size are not EC2 CPU, memory, or cost recommendations. Measure your own page complexity and concurrency before choosing capacity.

Or skip the browser setup

If your task is taking website screenshots rather than automating a custom browser workflow, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF, so you do not need to install Chrome dependencies on EC2 for that capture.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

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)

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(`ScreenshotNeo request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

See the ScreenshotNeo API documentation for parameters. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does Puppeteer need a desktop on EC2?

No. Puppeteer runs headless by default. A display server such as Xvfb is for headful workflows.

Can I use Chromium instead of Puppeteer’s Chrome?

Yes. Install a compatible system browser and set executablePath to its path. Check the browser version, libraries, and CPU architecture.

Can I run Puppeteer on Graviton?

Yes, with an ARM64 browser build that matches the instance and operating system. Do not assume the bundled x86 Chrome will run there.

Should I always pass --no-sandbox on EC2?

No. Investigate the sandbox setup first. Puppeteer’s documented exception is limited to content you are absolutely sure is trusted.