Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk6 min

Puppeteer Screenshot API: Automate Website Captures from a Node.js Server

Use Puppeteer on a Node.js server to capture rendered pages, choose the right screenshot target and format, and return image bytes safely.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To capture a website from a Node.js server with Puppeteer, launch a browser, open a page, navigate to the URL, and call page.screenshot(). The example below returns PNG bytes; add a path option to save a file, or choose full-page, clipped-region, or element capture depending on what the endpoint needs.

Install Puppeteer and capture a page

The following ES module example captures a page and returns its image bytes. Install Puppeteer with npm install puppeteer; the package manages a compatible browser for its standard installation. If your deployment supplies its own browser, configure the launch options for that environment and verify the browser executable is available.

As an Amazon Associate I earn from qualifying purchases.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  const image = await page.screenshot({ type: 'png' });
  // `image` is binary image data; return it or persist it as needed.
} finally {
  await browser.close();
}

This follows Puppeteer’s documented lifecycle: launch, create a page, navigate, capture, and close the browser. The finally block matters in a server handler because it also runs if navigation or capture throws. Puppeteer’s current API documentation identifies version 25.12.0. See the official Page API example.

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

Choose what the screenshot should include

Capture target How to request it Useful when
Current viewport Default behavior; no full-page or clip option You want only what is visible at the configured viewport size.
Full document await page.screenshot({ fullPage: true }) You need a tall image containing the whole page.
Rectangular region Pass a clip rectangle with x, y, width, and height. You need a specific bounded area rather than the whole viewport.
One element Wait for its selector, get its element handle, then call element.screenshot(). You need a component, card, chart, or other rendered element by itself.

Full-page capture

const image = await page.screenshot({ fullPage: true });

Capture a region

const image = await page.screenshot({
  clip: { x: 0, y: 0, width: 900, height: 600 }
});

Use coordinates and dimensions appropriate to the rendered page and viewport. Check the result for the intended crop, particularly when layout changes across viewport sizes.

Capture one element

await page.waitForSelector('.report-card');
const card = await page.$('.report-card');
if (!card) throw new Error('Report card was not found');
const image = await card.screenshot();

The screenshot guide notes that an element screenshot scrolls the element into view by default when it is hidden. Waiting for a selector establishes that it exists; it does not necessarily prove that a client-side component has finished populating its content. See the Puppeteer screenshots guide.

Save a file or return image data

Without a path, page.screenshot() returns image data rather than writing a file. By default, the data is a Uint8Array; you can request base64 output with encoding: 'base64'. Set a path when the server should persist the capture locally.

// Save to disk; Puppeteer infers the output type from the extension.
await page.screenshot({ path: 'capture.png' });

// Return bytes to the caller.
const bytes = await page.screenshot({ type: 'png' });

// Return base64 text, for example when an API contract requires JSON.
const base64 = await page.screenshot({ type: 'png', encoding: 'base64' });

For an HTTP endpoint that returns an image directly, send the bytes with a matching content type, such as image/png. If a JSON response requires base64, encode the image deliberately and account for the larger representation; binary output is usually the more natural form for an image response. The API options and return types are documented in Page.screenshot.

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.

Set format, quality, and transparency

  • PNG: the default format; it is a sensible choice when you need lossless output or transparency.
  • JPEG: set type: 'jpeg'. The quality option ranges from 0 to 100 and applies only to formats where quality is supported, not PNG.
  • Transparent background: use omitBackground: true where transparency is needed.
  • File extension: when using path, Puppeteer infers the image type from that extension.
const transparentPng = await page.screenshot({
  type: 'png',
  omitBackground: true
});

const compactJpeg = await page.screenshot({
  type: 'jpeg',
  quality: 80
});

Consult the complete ScreenshotOptions reference for supported options and constraints.

Wait for the right page state

The official screenshot guide uses waitUntil: 'networkidle2' in its navigation example. It is a useful starting condition, not a guarantee that every site is ready to capture: some pages continue rendering, poll services, or load content only after application-specific events.

await page.goto(url, { waitUntil: 'networkidle2' });
await page.waitForSelector('.report-ready');
const image = await page.screenshot({ fullPage: true });

If the capture depends on known content, wait for its selector or a specific application-ready condition before taking the screenshot. Avoid assuming that a successful navigation alone means a dynamic page has finished displaying the data you need.

Use the capture in a Node.js HTTP endpoint

This framework-neutral handler shape shows the key decisions: validate the requested URL in your application, ensure cleanup runs on errors, and return the binary response with an image content type. URL validation and network access controls are important in a public screenshot service; do not let an untrusted caller use your server to reach internal services.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import puppeteer from 'puppeteer';

export async function capturePng(req, res) {
  const url = req.query.url;
  if (typeof url !== 'string' || !/^https?:///i.test(url)) {
    res.statusCode = 400;
    res.end('A valid HTTP or HTTPS URL is required');
    return;
  }

  let browser;
  try {
    browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(url, { waitUntil: 'networkidle2' });
    const image = await page.screenshot({ type: 'png' });
    res.statusCode = 200;
    res.setHeader('Content-Type', 'image/png');
    res.end(Buffer.from(image));
  } catch (error) {
    res.statusCode = 502;
    res.end('Screenshot capture failed');
  } finally {
    if (browser) await browser.close();
  }
}

This is a starting shape, not a complete hardened service. Apply request timeouts, URL allowlisting or destination filtering, authentication and rate limits according to your threat model. Do not return raw internal exception details to callers.

Best Value
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Plan server lifecycle and concurrency around your workload

Close browser resources on both success and failure paths. The simplest example launches and closes a browser per job. Whether to reuse browser processes, isolate jobs with separate contexts, or impose a queue depends on workload and deployment constraints; the Puppeteer documentation cited here does not establish a universal safe throughput, memory budget, platform choice, or browser-pool configuration.

For shared BrowserContexts, Puppeteer documents that opening a new page or closing a page waits while a screenshot is in progress; bringToFront() does not wait. Avoid treating page focus as a synchronization barrier. See the Page.screenshot API notes.

Troubleshoot common capture failures

Symptom Likely cause What to check
Navigation or screenshot throws The browser, navigation, or capture operation failed. Log the server-side error, confirm the target URL is reachable from the server, and keep browser cleanup in a finally block.
Screenshot is blank or incomplete The page may still be rendering or a required component is not ready. Wait for a relevant selector or application-ready condition instead of relying only on navigation completion.
Only the visible area appears Default screenshot behavior captures the viewport. Set fullPage: true for the whole page or use a clip or element handle for a narrower target.
No image file appears No output path was supplied. Set path, or handle the returned bytes in memory.
Transparency or JPEG quality has no effect The selected option may not apply to the chosen format or page background. Use omitBackground for transparent output; use quality with JPEG rather than PNG.
Capture jobs interfere with page operations Concurrent page operations can interact with an in-progress screenshot. Sequence work on the page; in shared contexts, page creation or closure waits for screenshots, while bringToFront() does not.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. A single GET request can return an image or PDF, with options for full-page capture, CSS selectors, viewport and device presets, and more. Its clean-shot handling accepts consent banners and removes known consent platforms, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with verdict and billing information in response headers. AI agents can use its MCP server tools, including take_screenshot, get_page_info, and capture_pdf.

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

Here is a Node.js call that saves the response bytes:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));

For a Node.js environment without Bun, write the returned bytes with Node’s file system API. See the ScreenshotNeo documentation for request parameters and response behavior. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan to try 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.