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

Use Puppeteer to open the page, wait for the application’s rendered state, call page.content(), and write the returned string with Node’s filesystem API. The result is serialized HTML, including the DOCTYPE—not a complete offline copy of every referenced asset.

The reliable capture workflow

A JavaScript application can send only a small shell in its initial response and fill the real content after scripts run. Saving the response body with an HTTP client therefore misses the rendered DOM. Puppeteer controls a real Chromium-based browser, so the sequence is:

  1. Launch a headless browser.
  2. Navigate with page.goto().
  3. Wait for a selector or other application-specific ready signal.
  4. Read await page.content().
  5. Write that string to disk with Node’s filesystem APIs.
  6. Close the browser in a finally block.

Puppeteer’s Page API describes content() as “The full HTML contents of the page, including the DOCTYPE.” There is no special saveHTML() method.

Raspberry Pi prerequisites

Use a supported architecture and current runtime

Puppeteer’s current system-requirements page lists Node.js 22.12 or later and Chrome for Testing on Debian/Ubuntu Linux x64 and arm64. That identifies a supported platform class, not a blanket certification for every Raspberry Pi model, Raspberry Pi OS release, Chromium package, or Puppeteer/browser pairing. Record the board model, OS architecture and release, Node version, Puppeteer version, and browser binary when diagnosing a deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
  • Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM)
  • Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
  • CanaKit Turbine Black Case for the Raspberry Pi 5
  • CanaKit Low Noise Bearing System Fan
  • Mega Heat Sink - Black Anodized

Raspberry Pi OS is Raspberry Pi’s official operating system and is distributed in 32-bit and 64-bit editions. Its downloads page lists Raspberry Pi 5 as compatible with the 64-bit edition. A Pi 5 is not established as mandatory for this workflow; compatibility depends on the complete software and hardware combination.

Check the machine before installing

uname -m
cat /etc/os-release
node --version
npm --version

An aarch64 result indicates a 64-bit ARM userland. If Node is older than 22.12, upgrade it using your normal supported Raspberry Pi OS method before installing a current Puppeteer release. Avoid claiming success for a 32-bit installation unless the exact browser build and package combination is verified on that machine.

Install a project-local Puppeteer

mkdir rendered-html-capture
cd rendered-html-capture
npm init -y
npm install puppeteer

A project-local install keeps the browser automation dependency and its lockfile together. Puppeteer versions and browser requirements change, so pin and recheck versions when reproducing a deployment.

Complete Node.js example

Save this as save-rendered-html.mjs. Replace both the URL and the readiness selector with values from the target application. The selector below is deliberately illustrative: it is not a universal Puppeteer selector.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
CanaKit Raspberry Pi 4 4GB Starter PRO Kit - 4GB RAM
  • Includes Raspberry Pi 4 4GB Model B with 1.5GHz 64-bit quad-core CPU (4GB RAM)
  • Includes Pre-Loaded 32GB EVO+ Micro SD Card (Class 10), USB MicroSD Card Reader
  • CanaKit Premium High-Gloss Raspberry Pi 4 Case with Integrated Fan Mount, CanaKit Low Noise Bearing System Fan
  • CanaKit 3.5A USB-C Raspberry Pi 4 Power Supply (US Plug) with Noise Filter, Set of Heat Sinks, Display Cable - 6 foot (Supports up to 4K60p)
  • CanaKit USB-C PiSwitch (On/Off Power Switch for Raspberry Pi 4)
import puppeteer from 'puppeteer';
import { writeFile } from 'node:fs/promises';

const targetUrl = 'https://example.com';
const outputPath = 'page.html';
const readySelector = 'main[data-ready="true"]';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  const response = await page.goto(targetUrl, {
    waitUntil: 'domcontentloaded',
    timeout: 60_000,
  });

  if (response && response.status() >= 400) {
    throw new Error(`Page returned HTTP ${response.status()}`);
  }

  // Wait for the application, not merely for the first HTML response.
  await page.waitForSelector(readySelector, { timeout: 30_000 });

  const html = await page.content();
  await writeFile(outputPath, html, 'utf8');
  console.log(`Saved ${html.length} characters to ${outputPath}`);
} finally {
  await browser.close();
}

Run it with:

node save-rendered-html.mjs

goto() returns the main resource response when navigation produces one. In headless shell, a valid HTTP 404 or 500 response may be returned rather than thrown, which is why the explicit status check matters. Navigation can still throw for an invalid URL, SSL failure, an unreachable server, or a timeout.

Choosing the right readiness condition

Wait for a meaningful application marker

The most reliable condition is a marker your application sets after data loading and hydration, such as main[data-ready="true"]. A page-specific selector also works when its appearance proves that the required content is present:

await page.waitForSelector('#product-results', { timeout: 30_000 });

If the site exposes a documented client-side signal, wait for that signal with Puppeteer’s page evaluation facilities. Keep the timeout finite so a broken application does not leave the job running forever.

Use navigation waits as a starting point, not proof

waitUntil: 'domcontentloaded' means the initial document has been parsed. It does not guarantee that asynchronous API calls, hydration, or lazy rendering have completed. Other navigation wait behaviors, including network-idle modes, can help on some sites, but they are not universal proof of readiness: analytics, WebSockets, polling, or long-lived connections can prevent the network from becoming idle, while an application can render after network activity settles.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #3
ELECROW CrowPi Case Kit for Raspberry Pi 5, 9-Inch Display
  • Not including the Raspberry Pi 5 (8GB), the Crowpi advanced version comes with the Raspberry Pi 5
  • ELECROW Black Case for the Raspberry Pi 5, CrowPi is equipped with a 9-inch HD touchscreen along with a camera; All the regular components used in DIY electronics are packed into the CrowPi development board, such as LCD, LED matrix, buzzer, light sensor, PIR sensor, ultrasonic sensor, IR sensor, etc
  • Raspberry Pi Sensors: The Crowpi raspberry pi 5 programming kit is jam-packed with lots of buttons such as 19 different sensors in a tidy easy to use package; You don't have to wait and wire things
  • Build Quality: Solid ABS shell and well made components in one place make it strong and convenient to travel
  • Programming Lessons: This raspberry pi 5 learning kit ships with step by step instructions and provides 21 lessons to take you through identifying components reading code and running it in the terminal

When no marker exists

Wait for a known rendered element or a documented application event. A fixed delay can be a last-resort guard for an opaque site, but it is slower on fast runs and still unreliable when the site is slower than the chosen value. Prefer a condition tied to the content you must save.

What exactly is written to disk?

page.content() serializes the current page DOM and includes the DOCTYPE. It captures the markup that exists at the moment you call it, including changes made by client-side scripts. It does not automatically download and rewrite external stylesheets, images, fonts, scripts, API responses, or other resources. URLs in those elements can remain external, and an HTML file opened offline may therefore look incomplete or fail to run.

If you need a portable archive, you must separately collect dependencies and rewrite references; that is a different project from saving rendered HTML.

HTML, PDF, and screenshot are different outputs

Desired result Puppeteer API File represents
Inspectable rendered markup page.content() followed by a filesystem write Serialized page HTML, including the DOCTYPE
Print document page.pdf({ path: 'page.pdf' }) PDF rendered with print media by default
Visual image page.screenshot({ path: 'page.png', fullPage: true }) Screenshot image; format follows the selected option or extension

For a screen-style PDF, emulate screen media before calling page.pdf(); PDF generation otherwise uses print media by default. A screenshot records pixels, not an editable HTML representation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
CanaKit Raspberry Pi 5 Desktop PC with SSD (Fully Assembled) (256 GB SSD)
  • Fully assembled for plug-and-play operation
  • Includes Raspberry Pi 5 with 8GB RAM
  • 256 GB PCIe Pi NVMe SSD (Pre-loaded with Pi 64-Bit OS)
  • M.2 HAT+
  • CanaKit Turbine Black Case for the Pi 5

Useful production safeguards

Make failures observable

Log the target URL, output path, versions, elapsed time, and the HTTP status when available. Do not silently write an empty or error page. Check that a required selector exists and, where appropriate, that the resulting HTML contains an expected heading or data attribute.

Always close Chromium

The finally block in the example runs whether navigation, waiting, or writing fails. Without it, repeated jobs can leave browser processes and consume the Pi’s memory.

Control resource use

Raspberry Pi resources are finite. Reuse one browser process for a batch of pages, create and close a page per job, and avoid launching many Chromium instances concurrently. Set explicit navigation and readiness timeouts. Large pages, video, canvas applications, and many images can require substantially more memory than a simple document; no general speed or success-rate figure should be assumed.

Preserve the right browser context

Authenticated or localized pages may require cookies, headers, a timezone, or a specific user agent. Configure those in the browser context before navigation, and treat credentials as secrets. A saved HTML file can contain personal data, tokens in inline state, or private content, so protect its permissions and storage location.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
RasTech Raspberry Pi 5 8GB Kit with Active Cooler and Pi5 Case
  • 【What you Get】You will get 1*Pi 5 8GB Single Board,1*RasTech Case,1*Active Cooler,1*Screwdriver,1*Installation instructions,12-month free warranty, lifetime service, 24-hour prompt and friendly response.
  • 【More Connectors】There are two USB 3.0 ports(5Gbps simultaneously) and two USB 2.0 ports, which triple total bandwidth ,support any combination of up to two cameras or displays. Peak SD card performance is doubled through support for the SDR104 high-speed mode. It provides a smooth desktop experience for you. Offer Gigabit Ethernet and a PCIe interface, along with dual-band Wi-Fi and Bluetooth 5.0/BLE wireless capability. The RasTech Pi 5 Kit use the new 27W 5.1V 5A USB-C power connector.
  • 【 Support Dual 4Kp60 Display 】Each of the two microHDMI sockets can control a 4K display at 60 Hertz, now support HDR, offering super HD video for media streaming projects. RPi 5 is the first RPi model that comes with a PCI Express port (PCIe 2.0 x1 with 500 MB/s) to attach SSDs (requires separate M.2 HAT).
  • 【 Excellent Chips And Applications】Pi 5 is a full-size Pi computer using silicon built in-house at Pi. The RP1 “southbridge” provides the bulk of the I/O capabilities for Pi 5. Pi 5 is more friendly and convenient in the development of Internet of Things, Web development, machine identification, automatic control and other electronic equipment applications and network.
  • 【 Faster CPU, Better GPU 】 Pi 5 features a Broadcom BCM2712 64-bit quad-core Arm Cortex-A76 processor running at 2.4GHz, it delivers a 2–3× increase in CPU performance relative to RaspberryPi 4. The 800MHz VideoCore VII GPU is compatible to OpenGL ES 3.1 and Vulkan 1.2, substantial uplift in graphics performance. Pi 5 Offers lightning-fast CPU speed, a PCI Express interface, a Real Time Clock (RTC) and a power button and runs significantly cooler than Pi 4.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting

The file contains only a loading shell

  • Cause: The capture ran after domcontentloaded but before client rendering finished.
  • Fix: Wait for a selector or application-ready signal that appears only after the required data is displayed. Verify the selector in browser developer tools.

waitForSelector times out

  • Cause: The selector is wrong, the page shows an error state, a login is required, or the application never reaches that state.
  • Fix: Inspect the page manually, choose a real readiness marker, increase the timeout only when the page legitimately needs more time, and capture diagnostic console or screenshot output separately.

goto() throws a navigation error

  • Cause: Invalid URL, DNS or connectivity failure, certificate problem, or timeout.
  • Fix: Test the URL from the Pi, check system time and certificates, confirm outbound access, and keep the timeout explicit. Ensure the browser closes in finally.

The script succeeds for a 404 or 500 page

  • Cause: Valid HTTP error statuses do not necessarily cause headless navigation to throw.
  • Fix: Inspect response.status() and fail explicitly for statuses of 400 or higher, as shown in the example.

Chromium will not launch on the Pi

  • Cause: Architecture mismatch, an unsupported browser package, missing shared libraries, sandbox restrictions, or an incompatible Node/Puppeteer pairing.
  • Fix: Record uname -m, OS release, Node version, Puppeteer version, and browser path. Confirm that the installed browser build matches the supported Linux architecture and follow the package’s documented launch requirements rather than copying flags blindly.

HTML is present but looks broken offline

The file may correctly contain the rendered markup while still referencing remote CSS, JavaScript, images, or fonts. Saving page.content() is not an offline-site exporter; collect and rewrite dependencies if that is your actual requirement.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. It returns PNG, JPEG, WebP, or PDF from one request, so you do not need to install Chromium on the Pi for a visual capture. It accepts the cookie or consent banner as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the result through X-Page-Verdict and X-Billed headers.

For an image of a page, use the API endpoint documented at ScreenshotNeo’s API documentation:

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

The equivalent Python request is:

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)

And in 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}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Features include full-page capture with lazy images loaded, CSS-selector element capture, device presets, custom viewport and retina scale, PDF paper settings and page ranges, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agent, timezone, geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work.

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

The Free plan includes 1,000 shots per month without a card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is on every plan. Create a free ScreenshotNeo account to try it.

Frequently Asked Questions

Can I run the capture without a desktop session?

Yes. Puppeteer’s headless mode is designed for shell or service environments, provided the Pi has a compatible browser build and its required libraries.

Does page.content() preserve the original server response exactly?

No. It serializes the live DOM after browser scripts have modified it, so it can differ substantially from the initial response body.

Should I commit the generated HTML to source control?

Only when the page is intended as a reviewed artifact. Generated files can contain private data, timestamps, or volatile markup; inspect and sanitize them before committing.

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

Quick Recap

Bestseller No. 1
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
CanaKit Raspberry Pi 5 Starter Kit PRO - Turbine Black (128GB Edition) (8GB RAM)
Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM); CanaKit Turbine Black Case for the Raspberry Pi 5
$259.95
Bestseller No. 2
CanaKit Raspberry Pi 4 4GB Starter PRO Kit - 4GB RAM
CanaKit Raspberry Pi 4 4GB Starter PRO Kit - 4GB RAM
Includes Raspberry Pi 4 4GB Model B with 1.5GHz 64-bit quad-core CPU (4GB RAM); Includes Pre-Loaded 32GB EVO+ Micro SD Card (Class 10), USB MicroSD Card Reader
$159.99
Bestseller No. 4
CanaKit Raspberry Pi 5 Desktop PC with SSD (Fully Assembled) (256 GB SSD)
CanaKit Raspberry Pi 5 Desktop PC with SSD (Fully Assembled) (256 GB SSD)
Fully assembled for plug-and-play operation; Includes Raspberry Pi 5 with 8GB RAM; 256 GB PCIe Pi NVMe SSD (Pre-loaded with Pi 64-Bit OS)
$339.97

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.