# How to run Puppeteer in a cloud sandbox Install puppeteer from npm in an Ubuntu 24.04 microVM, add Chrome's system libraries with apt, run the script, and read the PDF back. **On Runtime, Puppeteer's own download of Chrome for Testing works the same way it does on a laptop.** Each sandbox is a Firecracker microVM with Node.js 24, `sudo` and its own kernel. A page that misbehaves stays inside a machine that exists only for that job. A 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the browser waits on the network. With both CPUs rendering, it costs $0.08 an hour ([pricing](/docs/pricing)). Puppeteer 25.16.0 was the current npm release on 25 October 2026. ## Render a page to PDF The script runs inside the sandbox. Your code on the host sends the script in and reads the PDF out. ```ts check import { writeFile } from "node:fs/promises"; import { Sandbox } from "withruntime"; const chromeLibs = "fonts-liberation libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0t64 libcups2t64 " + "libgbm1 libglib2.0-0t64 libgtk-3-0t64 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 " + "libxdamage1 libxfixes3 libxkbcommon0 libxrandr2 libxss1"; const script = ` import puppeteer from "puppeteer"; const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(process.argv[2], { waitUntil: "networkidle0" }); await page.pdf({ path: "page.pdf", format: "A4", printBackground: true }); console.log(await page.title()); await browser.close(); `; await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 900 }); const slow = { check: true, timeoutMs: 600_000 } as const; await sbx.exec(`sudo apt-get update -qq && sudo apt-get install -y -qq ${chromeLibs}`, slow); await sbx.exec("npm install --no-fund --no-audit puppeteer@25.16.0", slow); await sbx.files.write("/workspace/render.mjs", script); const run = await sbx.exec(["node", "render.mjs", "https://example.com"], { check: true }); console.log(run.stdout); await writeFile("page.pdf", await sbx.files.read("/workspace/page.pdf")); ``` ```python check from withruntime import Sandbox CHROME_LIBS = ( "fonts-liberation libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0t64 libcups2t64 " "libgbm1 libglib2.0-0t64 libgtk-3-0t64 libnspr4 libnss3 libpango-1.0-0 libxcomposite1 " "libxdamage1 libxfixes3 libxkbcommon0 libxrandr2 libxss1" ) with open("render.mjs") as handle: # the same Puppeteer script as above script = handle.read() with Sandbox.create(disk_mib=8192, timeout_seconds=900) as sbx: sbx.exec(f"sudo apt-get update -qq && sudo apt-get install -y -qq {CHROME_LIBS}", check=True, timeout_ms=600_000) sbx.exec("npm install --no-fund --no-audit puppeteer@25.16.0", check=True, timeout_ms=600_000) sbx.files.write("/workspace/render.mjs", script) run = sbx.exec(["node", "render.mjs", "https://example.com"], check=True) print(run.stdout) sbx.files.download("/workspace/page.pdf", "page.pdf") ``` `npm install puppeteer` downloads Chrome for Testing and `chrome-headless-shell` into `~/.cache/puppeteer`. In a sandbox, that path is `/workspace/.cache/puppeteer`. Puppeteer's installation guide puts the Linux download at about 282 MB. The sample therefore asks for an 8 GiB disk. The default 4 GiB sandbox had about 2.5 GiB free on 24 September 2026. ## Chrome's libraries on Ubuntu 24.04 Puppeteer's troubleshooting guide lists the Debian packages that Chrome needs. Several of them were renamed in Ubuntu 24.04, when the archive moved to 64-bit time (`t64`). The old names either no longer exist on noble or are virtual packages. So if you copy the list unchanged, `apt-get` stops. These are the noble names, each checked in the Ubuntu archive's noble package index on 25 October 2026: | Puppeteer's list says | Install on Ubuntu 24.04 | | --------------------- | ----------------------- | | `libasound2` | `libasound2t64` | | `libatk-bridge2.0-0` | `libatk-bridge2.0-0t64` | | `libatk1.0-0` | `libatk1.0-0t64` | | `libcups2` | `libcups2t64` | | `libglib2.0-0` | `libglib2.0-0t64` | | `libgtk-3-0` | `libgtk-3-0t64` | | `libnss3`, `libgbm1` | unchanged | The sample names the top packages of the tree and lets apt install their dependencies. X11 and D-Bus libraries such as `libx11-6`, `libxtst6` and `libdbus-1-3` keep their old names on noble. ## Start every sandbox with Chrome installed A [custom image](/docs/images) runs the install once. Puppeteer's own `--install-deps` flag installs Chrome's system libraries on Ubuntu and Debian. It needs root, which recipe commands have. `PUPPETEER_CACHE_DIR` moves the browser out of root's home directory, so the sandbox user can find it. ```ts check import { Runtime } from "withruntime"; const runtime = new Runtime(); await runtime.images.build({ name: "puppeteer", recipe: { env: { PUPPETEER_CACHE_DIR: "/opt/puppeteer" }, commands: [ "npm init -y && npm install --no-fund --no-audit puppeteer@25.16.0", "npx puppeteer browsers install chrome --install-deps", ], }, }); await using sbx = await runtime.sandboxes.create({ image: "puppeteer" }); ``` ```python check from withruntime import Runtime runtime = Runtime() runtime.images.build(name="puppeteer", recipe={ "env": {"PUPPETEER_CACHE_DIR": "/opt/puppeteer"}, "commands": [ "npm init -y && npm install --no-fund --no-audit puppeteer@25.16.0", "npx puppeteer browsers install chrome --install-deps", ], }) sbx = runtime.sandboxes.create(image="puppeteer") ``` Building is free. Without credit, the build counts toward its hours. A stored image is charged by its size. An account without credit stores three images free. ## Keep a scraper to the sites it should visit A scraper that follows links chosen by an LLM can be held to a list. Network rules are enforced on the host, so root inside the sandbox cannot lift them: ```ts check import { Sandbox } from "withruntime"; await using sbx = await Sandbox.create({ image: "puppeteer", network: { internet: true, allow: ["example.com", "*.example.com"] }, }); ``` Anything off the list is refused, on every port. `internet: false` turns off the web entirely, once the pages are loaded ([turn off sandbox internet](/how-to/turn-off-sandbox-internet)). ## Things that trip people up | Symptom | What is going on | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `error while loading shared libraries` | A library from the table above is missing; install the noble name | | `No usable sandbox!` | Puppeteer's guide says Ubuntu 23.10 and later ship an AppArmor profile that stops Chrome for Testing using user namespaces; it recommends configuring a sandbox rather than `--no-sandbox` | | Command timed out after 60 seconds | The default `exec` timeout; give installs `timeoutMs` | | `ENOSPC` during `npm install` | Ask for `diskMiB: 8192`; without credit, up to 10 GiB | | A site on port 8443 never answers | Sandboxes without credit reach ports 80 and 443; paid sandboxes reach any port | ## Puppeteer, Playwright or the desktop - **Puppeteer** suits code already written against it, and Chrome-only jobs such as PDF rendering. - **[Playwright](/integrations/playwright)** drives Chromium, Firefox and WebKit, and brings its own test runner. - **The sandbox [desktop](/docs/javascript#a-desktop)** takes clicks and keys and returns screenshots. It suits an agent that looks at the screen instead of the DOM ([browser automation agent](/use-cases/browser-automation-agent)). - **No framework at all:** Chrome's own command line prints PDFs and screenshots ([headless Chrome](/integrations/headless-chrome)). Try it free. A new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card: ```bash no-run npx withruntime sandboxes run -- node --version ``` ## Sources - Puppeteer installation guide, https://pptr.dev/guides/installation, read 25 October 2026 - Puppeteer troubleshooting, https://pptr.dev/troubleshooting, read 25 October 2026 - Puppeteer configuration, https://pptr.dev/guides/configuration, read 25 October 2026 - Puppeteer browsers CLI, https://pptr.dev/browsers-api, read 25 October 2026 - npm registry, https://registry.npmjs.org/puppeteer, read 25 October 2026 - Ubuntu 24.04 package index, http://archive.ubuntu.com/ubuntu/dists/noble/main/binary-amd64/, read 25 October 2026 Facts on this page were checked on 25 October 2026.