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

For a screenshot of a rendered webpage, use a browser automation library—usually Playwright or Puppeteer. Both drive a real browser, so they can capture what the browser renders, including a full page or a selected element. Use html2canvas when the work must happen inside the page and a DOM-derived image is acceptable; it reconstructs pixels from DOM information rather than taking a literal browser screenshot.

This guide shows runnable JavaScript examples, explains the fidelity and execution trade-offs, and covers an API alternative when maintaining browser infrastructure is not worthwhile.

Quick decision: which library fits?

Approach Best fit What it captures Important limitation
Playwright Automated browser screenshots in a new or cross-browser project Viewport, full scrollable page, or a locator’s element; can return a buffer Requires browser automation setup and a browser process
Puppeteer Projects already using its Chromium-focused workflow Page or element screenshots, with options such as full-page, clipping, type and quality Readiness depends on the page; a navigation wait condition is not a universal guarantee
html2canvas Client-side, DOM-derived rendering where an exact browser image is unnecessary Supported DOM and CSS reconstructed into a canvas image Not pixel-for-pixel; unsupported CSS, cross-origin images and cross-origin iframes can affect output
ScreenshotNeo Hosted captures without running browsers yourself Clean PNG, JPEG, WebP or PDF from one request Requires an API key and network request

There is no documented speed or fidelity benchmark that establishes one of the three JavaScript libraries as a universal winner. Choose by execution context, required fidelity, capture target and output handling.

Playwright: a real-browser screenshot API

Playwright is the clearest default when you need automated screenshots of rendered pages and want documented support for full-page, element and in-memory captures. It launches a browser, navigates to the URL, waits for the condition your page needs, and asks the browser for an image.

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

Install and capture a viewport

npm init -y
npm install playwright
npx playwright install chromium
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  await page.screenshot({ path: 'page.png' });
  await browser.close();
})();

domcontentloaded means the initial document has been parsed, not that every image, font or client-rendered component is ready. For a page that fills content after navigation, wait for a meaningful selector or a deliberate delay:

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('[data-testid="report"]').waitFor();
await page.screenshot({ path: 'report.png', fullPage: true });

Full-page, element and buffer captures

// Entire scrollable document
await page.screenshot({ path: 'full.png', fullPage: true });

// Only the first matching element
await page.locator('.invoice').screenshot({ path: 'invoice.png' });

// Keep the image in memory for processing or uploading
const bytes = await page.screenshot({ type: 'png' });
// bytes is a Buffer

Use a locator for an element rather than guessing coordinates. If the page has animations, freeze or wait for them before capture; otherwise two otherwise-identical runs can differ.

Puppeteer: browser automation with flexible screenshot options

Puppeteer is a good choice when its browser workflow already matches your project. Its guide demonstrates navigation with a waitUntil option, page screenshots and element screenshots. The screenshot API returns binary data by default, or a base64 string when requested.

Install and capture a page

npm init -y
npm install puppeteer
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 900 });
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'page.png', fullPage: true });
  await browser.close();
})();

networkidle2 is an example readiness condition, not a promise that every page is visually complete. Analytics, long polling and advertisements can keep connections open, while a page can still be rendering after the network quiets. Prefer a page-specific selector or application signal when available.

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

Capture an element, clip a region or return base64

const card = await page.$('.pricing-card');
await card.screenshot({ path: 'card.png' });

await page.screenshot({
  path: 'crop.webp',
  type: 'webp',
  quality: 85,
  clip: { x: 0, y: 0, width: 800, height: 600 }
});

const encoded = await page.screenshot({ encoding: 'base64' });

Choose PNG for lossless UI text, JPEG for photographs, and WebP when your downstream system supports it. Quality applies to lossy formats. Transparent backgrounds and other options are useful for compositing, but verify the result against your browser and library versions.

html2canvas: a different kind of screenshot

html2canvas runs in the page and traverses the DOM, building a canvas from the properties it understands. It does not take a literal screenshot of the browser’s rendered surface. Unsupported CSS can disappear or change, cross-origin images may fail without suitable CORS handling, and cross-origin iframe contents cannot be read because of browser security restrictions.

Basic client-side example

import html2canvas from 'html2canvas';

const node = document.querySelector('#receipt');
const canvas = await html2canvas(node, {
  backgroundColor: '#ffffff',
  useCORS: true,
  scale: window.devicePixelRatio
});
const png = canvas.toDataURL('image/png');
document.querySelector('#preview').src = png;

Test the exact page, assets and browser conditions that matter. A canvas export can be useful for a user-initiated “save this panel” feature, but it is a risky substitute for a pixel-accurate audit, visual regression test or capture of third-party content.

How to choose in a real project

Need the browser’s actual rendering?

Start with Playwright or Puppeteer. They execute scripts, apply layout, load fonts and images, and expose page-level and element-level screenshot methods. Add an explicit readiness check for data-driven pages.

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

Need a client-only feature?

Use html2canvas only when a DOM reconstruction meets the visual requirement and all important assets are accessible. It avoids a server browser, but the security and rendering limitations become your responsibility.

Need image bytes for another service?

Playwright returns a buffer directly. Puppeteer returns binary data by default and can return base64 when requested. Keeping bytes in memory avoids temporary files, while writing files is simpler for debugging and artifact retention.

Need many URLs or non-JavaScript callers?

A hosted screenshot API can centralize browser lifecycle, retries, formats and access controls. ScreenshotNeo is the first alternative to try: it produces clean shots, bills only clean captures, and its paid entry plan is $5 for 3,000 shots.

Production checklist and failure handling

  • Browser startup fails: install the browser binaries (for example, Playwright’s install command), ensure the runtime has the required sandbox or container permissions, and close every browser in a finally block.
  • Blank or half-rendered output: wait for a stable selector, font readiness or an application-specific “loaded” state instead of relying only on a fixed timeout.
  • Lazy images are missing: scroll the page or trigger the application’s lazy-load mechanism before a full-page capture.
  • Cookie banners, chat or popups obscure content: dismiss or hide them in the automated page before taking the shot. A generic selector will not work for every site.
  • Element capture throws: confirm the locator matches exactly one visible element and that the element is not detached during a re-render.
  • html2canvas omits an image or iframe: check CORS headers and same-origin rules; cross-origin iframe pixels are not available to page JavaScript.
  • Different results in CI: pin library and browser versions, set the viewport and device scale factor, use consistent fonts, and disable time-dependent animations.
  • Huge files or memory use: capture an element or clip a region, choose an appropriate image type, and avoid holding many full-page buffers at once.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and response headers report the page verdict and whether the request was billed.

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

One GET request returns PNG, JPEG, WebP or PDF. The API also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, custom CSS and JavaScript, clicks, selector or network-idle waits, request/resource blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

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)
r.raise_for_status()
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(`${res.status} ${res.statusText}`);
require('fs').writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));

See the ScreenshotNeo documentation for request options and response headers. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.

Plans and operational cost

Plan Allowance Price
Free 1,000 shots/month $0, no card
Starter 3,000 shots $5
Growth 15,000 shots $15
Pro 60,000 shots $39
Scale 250,000 shots $99
Business 1,000,000 shots $249

Yearly billing gives two months free, and every feature is available on every plan. Start with 1,000 free screenshots a month—no card required.

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

FAQ

Can html2canvas capture a page from another domain?

Not reliably. Cross-origin images require appropriate CORS handling, and cross-origin iframe content cannot be accessed by page JavaScript.

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.

Should I use full-page capture for every test?

No. Capture the smallest region that answers the question. Full-page images are useful for documents and archives but increase rendering time, memory use and artifact size.

Can these libraries create PDFs?

Playwright and Puppeteer can support PDF workflows through their browser APIs, while ScreenshotNeo exposes PDF capture directly. html2canvas produces a canvas image; assembling a document is a separate task.

Frequently Asked Questions

Can html2canvas capture a page from another domain?

Not reliably. Cross-origin images require appropriate CORS handling, and cross-origin iframe content cannot be accessed by page JavaScript.

Should I use full-page capture for every test?

No. Capture the smallest region that answers the question. Full-page images increase rendering time, memory use and artifact size.

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

Can these libraries create PDFs?

Playwright and Puppeteer can support PDF workflows through their browser APIs, while ScreenshotNeo exposes PDF capture directly. html2canvas produces a canvas image; assembling a document is separate.

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.