ScreenshotNeo

BlogHow-to

Take a Screenshot of a Webpage Element with Puppeteer in Node.js

Capture one DOM element as an image with Puppeteer in Node.js. See runnable code, screenshot options, fixes for common errors, and a no-browser alternative.

By the ScreenshotNeo team4 October 20267 min read

Use Puppeteer to open the page, select the element, and call ElementHandle.screenshot(). This saves the selected element as an image and scrolls it into view if needed. The example below writes a PNG file and closes the browser even if navigation or capture fails.

import puppeteer from 'puppeteer';

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

  const element = await page.waitForSelector('.target-element');
  if (!element) throw new Error('Target element was not found');

  await element.screenshot({ path: 'element.png' });
  await element.dispose();
} finally {
  await browser.close();
}

This uses Puppeteer’s ES module import form. In a project configured for CommonJS, use const puppeteer = require('puppeteer'); and wrap the asynchronous work in an async function. Install Puppeteer with npm install puppeteer; it downloads a compatible browser as part of the package’s normal installation. If your environment manages Chrome separately, consult the Puppeteer installation guide for the supported setup.

1. Set up a Node.js script

Create a project and install Puppeteer:

mkdir element-shot
cd element-shot
npm init -y
npm install puppeteer

Save the example as capture-element.mjs and run node capture-element.mjs. The .mjs extension enables ES modules in Node.js without changing the package configuration.

2. Select the element you want to capture

Replace .target-element with a CSS selector that identifies the element. For example:

const element = await page.waitForSelector('#invoice');

waitForSelector() waits for a matching element and returns an element handle. If you use options that allow a missing element, check the result before calling screenshot(). On pages that render content asynchronously, wait for a selector that signals the content is ready rather than assuming the page is ready as soon as navigation completes.

Puppeteer also recommends locators for selecting and interacting with page elements. Locators provide readiness checks and retries for supported actions, and can use CSS and other selector forms. The documented element screenshot method is on ElementHandle, so use a handle for the final .screenshot() call; do not assume a locator has that method.

3. Choose when navigation is ready

The example uses waitUntil: 'networkidle2', which is one available navigation condition. It is not right for every site: analytics, polling, streaming, or other persistent requests can keep network activity going. Choose a condition suited to the page, then wait for the actual target content when necessary.

Navigation condition When it can help What to consider
domcontentloaded The document is parsed and the target appears early. Images, fonts, or client-rendered content may still be loading.
load The page’s load event is a useful milestone. Some pages continue loading resources after this event.
networkidle0 / networkidle2 Network quietness is a useful proxy for readiness. Persistent traffic can delay or prevent these conditions.

When capture timing matters, combine a suitable navigation condition with a wait for the target selector. A selector wait answers whether the element exists; if the page fills it with data later, wait for a page-specific readiness signal too.

4. Save the element screenshot

Pass a path to write the screenshot directly to disk:

await element.screenshot({ path: 'element.png' });

Without a path, the method returns image data as a Uint8Array by default. You can write it with Node’s filesystem APIs:

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

const image = await element.screenshot();
await writeFile('element.png', image);

Set encoding: 'base64' when a base64 string is more useful to your application:

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

5. Configure format and appearance

The screenshot options let you control the output. PNG is the default. The available interface also documents JPEG and WebP output, clipping, full-page capture, and omitting the background.

Option Effect Practical note
path Writes the image to a file. Without it, use the returned image data.
type Selects an image format such as png, jpeg, or webp. PNG is the documented default.
quality Sets lossy image quality for supported non-PNG formats. It does not apply to PNG.
encoding Selects binary image data or a base64 string. Binary data is the default.
omitBackground Omits the default page background where transparency is supported. Useful for overlays; inspect the result in the format you choose.
clip Captures a specified rectangular region. Usually unnecessary for an element screenshot, which already targets the handle.
fullPage Captures the full page. Use page-level screenshot capture when you need the whole document rather than one element.

For example, save a JPEG with a chosen quality:

await element.screenshot({ path: 'element.jpg', type: 'jpeg', quality: 85 });

Use options supported by your installed Puppeteer version. The API documentation surfaced for this guide is labeled 25.12.0; your installed version may differ.

6. Handle dynamic pages and cleanup

An element handle refers to a particular DOM node. If a framework replaces or removes that node between selection and capture, ElementHandle.screenshot() throws because the element is detached. Minimize the gap between locating and capturing it. If the page routinely rerenders, wait for its stable state and reacquire the handle before capture when your application can safely do so.

Element capture scrolls the element into view if necessary. That can change the page’s scroll position, so account for it if subsequent steps depend on the viewport. Always close the browser in a finally block in scripts that may fail during navigation, selection, or capture.

7. Troubleshoot common problems

Symptom Likely cause What to try
Selector wait times out The selector is wrong, the element is absent, or it appears later than expected. Check the selector and page state; wait for the correct content-ready signal.
“Node is detached” or a detached-element error The page replaced or removed the selected node before capture. Wait for the page to settle and obtain a fresh handle close to the screenshot call.
Screenshot is blank or incomplete The page or element content was not ready when captured. Wait for the relevant selector or application-specific readiness condition; verify the target URL and page state.
Navigation hangs at a network-idle condition The site keeps requests active, for example through polling or long-lived connections. Choose another navigation condition and explicitly wait for the element or content you need.
Output is missing The path is relative to a different working directory than expected, or the script failed before writing. Use an absolute path or inspect the process working directory and the thrown error.
Quality option has no visible effect The output is PNG. Choose JPEG or WebP if you need a lossy quality setting.
Browser fails to launch The browser installation or runtime environment is not configured for the host. Review the Puppeteer installation guide and the browser/runtime requirements for your environment.

8. Performance, reliability, and cost

A screenshot requires launching or reusing a browser, loading the page, waiting for the target, and encoding the image. For repeated captures in one process, reusing a browser and creating pages as needed can avoid repeated startup overhead; close pages and the browser when the work is done. Large elements and image-heavy pages can take longer and produce larger files, so capture only the required element and choose an output format appropriate to the use.

Reliability depends on page behavior, network access, selector stability, browser installation, and your readiness conditions. Use explicit timeouts and error handling appropriate to your workload, and treat a detached-node failure as a signal to reacquire the element when safe. Puppeteer is software you run, so budget for the compute and browser maintenance in your environment; the cited API material gives no universal runtime, cost, or performance benchmark.

9. Or skip the browser setup

If you only need a webpage screenshot and do not need to manage Chromium, ScreenshotNeo provides a screenshot API and MCP server. One GET request can return an image or PDF. See the ScreenshotNeo 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
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)
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(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

The API captures a page, rather than targeting a DOM element by CSS selector. Its options include selectors to hide and other capture controls, but if you specifically need the rendered pixels of one element, the Puppeteer handle approach above gives you direct DOM-element capture.

  • Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Responses indicate the page verdict and billing status in headers.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. All features are on every plan.

Sign up free for 1,000 screenshots a month, with no card required.

10. FAQ

Does an element screenshot include content outside the selected element?

No. It captures the element represented by the handle. Use page-level screenshot capture when you need the whole page.

Can I get the screenshot without saving a file?

Yes. Omit path and use the returned Uint8Array, or request base64 encoding.

Does Puppeteer support taking a screenshot of an element that is off screen?

The element screenshot method scrolls the element into view if needed, then captures it.

Which selector should I use on a frequently changing page?

Prefer a stable attribute or selector tied to the target’s meaning. If the DOM node is replaced during rendering, reacquire its handle near capture time.

References