October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
browser automation

How to Capture Webpages as PNG Images in TypeScript

Free tools Windows power users keep installed

One-click scans. No signup required.

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

Use Playwright’s page.screenshot() to capture a webpage as a PNG in TypeScript. Set a deliberate viewport, navigate to the page, and either provide a file path to save the image or omit it to receive PNG bytes as a Node.js Buffer. Use fullPage: true for the entire scrollable document, or call screenshot on a locator to capture one element.

Capture a webpage as a PNG with Playwright

This Node.js example opens Chromium, navigates to a page, saves a PNG, and closes the browser even if navigation or capture fails. It uses Playwright’s documented networkidle navigation wait; for pages that keep network requests open, choose another readiness check as described below.

import { chromium } from 'playwright';

async function main() {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({
      viewport: { width: 1440, height: 900 },
    });

    await page.goto('https://example.com', {
      waitUntil: 'networkidle',
    });

    await page.screenshot({
      path: 'page.png',
      type: 'png',
    });
  } finally {
    await browser.close();
  }
}

main();

Install Playwright in a Node.js project with npm install playwright, then install its Chromium browser with npx playwright install chromium. Save the example in a TypeScript file such as capture.ts. To execute TypeScript directly, use a TypeScript runner already configured in your project; alternatively, compile it with your TypeScript build setup and run the resulting JavaScript with Node.js. Playwright’s exact setup may vary with your project’s module configuration.

The output path is relative to the process’s current working directory. Change page.png to an absolute path or a path such as screenshots/page.png if you want a different destination; create the destination directory first if it does not exist.

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

Get the PNG as a Buffer instead of writing a file

page.screenshot() returns a Promise<Buffer>. When you omit path, the resolved value contains the image bytes, ready for upload, storage, or image processing:

const pngBytes = await page.screenshot({ type: 'png' });
// pngBytes is a Node.js Buffer

For example, within the earlier try block you can replace the path-based capture with the following file write:

import { writeFile } from 'node:fs/promises';

const pngBytes = await page.screenshot({ type: 'png' });
await writeFile('page.png', pngBytes);

Choose one approach if you only need one output: passing path lets Playwright write the screenshot, while omitting it gives your code the bytes to handle. Avoid converting a Buffer to base64 unless the destination specifically requires a base64 string; the Buffer is already usable as binary data.

Choose the capture scope: full page or one element

A viewport screenshot captures what is visible in the current page viewport. For a long article or document, request a full-page image. For a component such as an invoice, card, or chart, take a locator screenshot instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
TypeScript Programming Language - Software Engineer & Coder T-Shirt
  • TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
  • TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Capture the entire scrollable document

await page.screenshot({
  path: 'full-page.png',
  fullPage: true,
  type: 'png',
});

fullPage: true captures the full scrollable page rather than only the visible viewport. It can produce a much taller image, so use it when the complete document is the intended deliverable, not just to make a viewport capture “better.” Pages with content that loads only as the user scrolls may need additional preparation before capture; a full-page option alone is not a guarantee that every lazy-loaded asset has appeared.

Capture a selected element

const invoice = page.locator('.invoice');
await invoice.screenshot({
  path: 'invoice.png',
  type: 'png',
});

Replace .invoice with a CSS selector for the target. The locator must resolve to the intended element, and that element must be present and visible when the screenshot is taken. If the page has multiple matching elements, make the selector more specific or select the intended match before capturing. Element capture and fullPage solve different problems: one isolates a target element; the other covers the document.

Control dimensions, image type, and readiness

Set viewport and pixel scale intentionally

The viewport in browser.newPage() determines the browser’s CSS layout dimensions. Pick fixed dimensions when repeatability matters; otherwise, a page may wrap text or rearrange responsive components differently from the screenshot you expect.

Playwright’s screenshot scale option controls output pixel density. scale: 'css' produces one output pixel per CSS pixel. scale: 'device' uses device pixels and can create a larger, higher-DPI image. Use CSS scale when stable CSS-pixel dimensions are the priority, and device scale when extra pixel detail is more important.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.screenshot({
  path: 'page.png',
  type: 'png',
  scale: 'css',
});

Wait for the page state you actually need

Navigation completion and application readiness are not always the same thing. waitUntil: 'networkidle' is a useful choice for pages whose important resources finish loading after the initial response, but some applications continuously make requests. In that case, waiting for the network to become idle can time out or delay the capture. Prefer a condition tied to the page’s own ready state, such as waiting for an element that indicates the content you need has rendered.

await page.goto('https://example.com', {
  waitUntil: 'domcontentloaded',
});
await page.locator('main').waitFor({ state: 'visible' });
await page.screenshot({ path: 'page.png', type: 'png' });

The locator in this example is illustrative: replace main with a reliable selector for the content in your target site. A fixed delay can be useful when a known animation or delayed widget must finish, but it is less robust than waiting for a meaningful condition because the right duration can vary between runs.

Other capture controls

Playwright also supports PNG, JPEG, and WebP output; PNG is the default when no other type is inferred. For PNG captures, set type: 'png' explicitly when you want the output format to be clear in code. The screenshot API also provides a style option for applying a stylesheet during capture and a timeout option for limiting how long the screenshot operation may wait. Consult the Playwright API documentation for the version installed in your project when adding options beyond these examples.

Make repeated captures more reliable

A successful capture is not necessarily a repeatable one. Dynamic content, animation, and the browser environment can change pixels between runs. For visual-test baselines, keep the capture conditions controlled rather than treating every difference as an application regression.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Fix the viewport. Use the same width and height for baseline and comparison captures.
  • Wait for meaningful readiness. Prefer a page-specific selector or state over a generic wait when the application has a known rendering milestone.
  • Choose the scope deliberately. Use viewport, full-page, or element capture according to the comparison you want.
  • Reduce transient visual changes. Disable or mask animations and dynamic content where appropriate. Playwright screenshot options and visual comparison tools can help manage these cases.
  • Keep the environment stable. Playwright’s visual-comparison documentation warns that rendered screenshots can vary with operating system, browser version, settings, hardware, power source, and headless mode.
  • Close the browser in cleanup code. A finally block prevents a failed navigation or screenshot from leaving the browser process open.

For a project already using Playwright Test, expect(page).toHaveScreenshot() is the visual-regression route; PNG is its default snapshot format. Generate and compare baselines in a controlled environment, and investigate environment changes before treating pixel differences as application changes.

Or skip the browser setup

If you need a screenshot without installing and managing a local browser, ScreenshotNeo offers a one-request screenshot API and an MCP server. Its API accepts a URL and returns an image or PDF; the following Node.js example requests a WebP image using the provided API pattern:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

For API setup and options, see the ScreenshotNeo documentation. Its clean-shot options accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; you can turn each step off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether the request was billed. The MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

The free plan includes 1,000 screenshots per month with no card required. Paid plans start at $5 for 3,000 screenshots; yearly billing gives two months free. Every listed feature is available on every plan. Sign up for ScreenshotNeo’s free plan to try it without a card.

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

When to use Playwright, Puppeteer, or a screenshot API

Approach Best fit What to account for
Playwright TypeScript browser automation, page and element captures, and projects using Playwright Test. You manage browser installation and execution; consistent visual comparisons depend on a controlled environment.
Puppeteer Projects already built around Puppeteer and its browser automation APIs. It supports file and byte-returning screenshot use cases; choose waits and capture scope deliberately.
ScreenshotNeo API or MCP server Captures through a hosted endpoint, or screenshot actions initiated by an MCP-capable AI client. Use an API key for API requests and check the response headers to determine the page verdict and billing status.

Both Playwright and Puppeteer can save PNG files or provide screenshot bytes, and both support full-page and element capture workflows. Choose the library that matches the automation stack already in your application. Playwright documents Chromium, Firefox, and WebKit in its examples; the examples here use Chromium. A hosted API or MCP server is an alternative when you want to avoid local browser setup, not a reason to change an existing test stack that already meets your needs.

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

Puppeteer equivalent

If your TypeScript project uses Puppeteer, the core sequence is similar. This example waits with Puppeteer’s networkidle2 policy and saves a full-page PNG:

import puppeteer from 'puppeteer';

async function main() {
  const browser = await puppeteer.launch();
  try {
    const page = await browser.newPage();
    await page.goto('https://example.com', {
      waitUntil: 'networkidle2',
    });

    await page.screenshot({
      path: 'page.png',
      type: 'png',
      fullPage: true,
    });
  } finally {
    await browser.close();
  }
}

main();

Puppeteer’s screenshot API also has a byte-returning overload, and its encoding: 'base64' option provides a base64 string. Its guide also demonstrates capturing an element with ElementHandle.screenshot(). Use the API style appropriate to the Puppeteer version and TypeScript types in your project.

Troubleshoot common capture failures

The screenshot is empty, incomplete, or shows a loading state

  • Likely cause: The capture ran before the application rendered the desired content, or the chosen navigation wait does not represent the page’s actual ready state.
  • Fix: Wait for a page-specific visible element or application readiness condition before calling screenshot. If the site continuously sends requests, try domcontentloaded followed by a meaningful selector wait rather than relying on networkidle.

The capture hangs or navigation times out

  • Likely cause: A network-idle condition never occurs, a resource is slow, or a screenshot operation exceeds its configured timeout.
  • Fix: Use a navigation policy appropriate to the page, then wait for the specific content required. Review the screenshot operation’s timeout setting if the capture itself is the slow step; do not assume a longer timeout fixes an unending readiness condition.

The image has the wrong size or the page layout differs

  • Likely cause: The viewport or pixel scale differs from the intended output, or responsive layout changed at the selected dimensions.
  • Fix: Set the viewport explicitly and select scale: 'css' for one output pixel per CSS pixel, or scale: 'device' for device-pixel output. Confirm whether you intended viewport or full-page capture.

The element screenshot fails or captures the wrong content

  • Likely cause: The selector matches no visible element, is ambiguous, or identifies a different element than intended.
  • Fix: Wait for the target locator to become visible and make its selector specific enough to identify the intended component before calling locator.screenshot().

Visual tests change despite no deliberate UI change

  • Likely cause: Operating system, browser version, settings, hardware, power source, or headless mode changed; animation or dynamic content may also be different.
  • Fix: Generate and compare baselines under controlled conditions, and disable or mask transient content where suitable. Check environment changes alongside application changes.

The browser remains running after an error

  • Likely cause: Browser cleanup only occurs after successful navigation and capture.
  • Fix: Put browser work inside try and call browser.close() in finally, as in the examples.

Quick decision guide

  • For a file on disk, pass path: 'page.png'.
  • For bytes to upload or process, omit path and use the returned Buffer.
  • For everything in the scrollable document, add fullPage: true.
  • For one component, call screenshot on a locator or element handle.
  • For repeatable results, fix viewport, wait on meaningful page readiness, and control the test environment.
  • For browser automation already centered on Playwright or Puppeteer, keep the capture in that stack; use a hosted API or MCP server when avoiding browser management is more important.

Frequently Asked Questions

Can I use the screenshot Buffer directly in an HTTP upload?

Yes. It is binary PNG data, so pass the Buffer through the receiving library’s binary-body or multipart-file interface rather than encoding it as text.

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

Does TypeScript change the screenshot API?

No. TypeScript calls the same Playwright or Puppeteer APIs as JavaScript; TypeScript adds compile-time checking and may require project-specific module or runner configuration.

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.

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.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

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.