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 DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
browser automation

How to Capture a Specific Element with Puppeteer

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

Use Puppeteer’s ElementHandle.screenshot() method. Select the element, wait until it exists, then call screenshot() with a file path or other screenshot options. Puppeteer scrolls the element into view automatically, but the handle must still refer to a connected DOM node when capture starts.

Direct method: select a handle and capture it

This complete Node.js example uses the current Puppeteer API documented for version 25.12.0. It opens a page, waits for .target-element, saves only that element as element.png, disposes the handle, and always closes the browser.

import puppeteer from 'puppeteer';

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

  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();
}

With a path, Puppeteer infers the image type from the extension. Use .png, .jpg, or .webp as appropriate. The returned value is a Uint8Array unless you request another encoding.

Prerequisites and page readiness

Install Puppeteer

In a new project, install Puppeteer with your package manager, then run the script as an ES module (for example, by setting "type": "module" in package.json or using an .mjs file). Puppeteer normally downloads a compatible browser during installation. If your environment supplies its own Chrome or Chromium, configure that executable explicitly when launching.

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.

Wait for the content that matters

page.goto() confirms navigation according to its wait condition, not that a client-rendered card, chart, or image has finished appearing. Use a selector wait for the actual target. If the element depends on data, wait for a more meaningful readiness condition as well:

await page.goto('https://example.com/dashboard', {
  waitUntil: 'networkidle2'
});
await page.waitForSelector('.target-element');

Network-idle waits can be unsuitable for pages with analytics, streaming requests, or long polls. In those cases, a specific selector, a known text change, or an application-defined readiness attribute is more reliable.

Choosing the element

waitForSelector(): direct and explicit

page.waitForSelector(selector) returns an ElementHandle when a matching node appears. This is the shortest route when the next operation is specifically ElementHandle.screenshot(). It also makes the failure point obvious if the selector never appears.

const element = await page.waitForSelector('#invoice-total');
if (!element) throw new Error('Invoice total is missing');
await element.screenshot({ path: 'invoice-total.png' });
await element.dispose();

page.$(): immediate lookup

page.$(selector) returns the first match or null. It does not wait. Use it only when the page is already ready or when you deliberately want to handle an absent element yourself.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const element = await page.$('.optional-banner');
if (element) {
  await element.screenshot({ path: 'banner.png' });
  await element.dispose();
}

Locators: automatic readiness checks

Puppeteer’s locator API is recommended for ordinary selection and interactions because it waits for elements to be present and in an appropriate state. A locator is not itself an ElementHandle; call waitHandle() when you need the handle-based screenshot method.

const locator = page.locator('.target-element');
const element = await locator.waitHandle();
try {
  await element.screenshot({ path: 'element.png' });
} finally {
  await element.dispose();
}

CSS selectors are the default. Puppeteer also documents text, accessibility, XPath, and shadow-root selector syntax. Prefer a stable attribute such as data-testid over a generated class name when you control the page.

Screenshot options that apply to an element

ElementHandle.screenshot() accepts the screenshot options used by page-level capture. The most useful options are:

  • path: writes the image to disk. The extension determines the type when a path is supplied.
  • encoding: request 'base64' when you need a string instead of binary bytes.
  • quality: controls JPEG or WebP quality where supported; it has no effect on PNG.
  • omitBackground: allows transparent output when the page and image format support it.
  • clip: applies a clipping rectangle, useful for trimming an already selected region.
  • fullPage: is a page-style option; an element screenshot is already limited to the target, so use it only when your installed Puppeteer version documents a meaningful combination for your case.

For a binary buffer, omit path and write the returned bytes yourself:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import { writeFile } from 'node:fs/promises';

const element = await page.waitForSelector('.chart');
if (!element) throw new Error('Chart not found');
try {
  const bytes = await element.screenshot();
  await writeFile('chart.png', bytes);
} finally {
  await element.dispose();
}

For base64 output:

const element = await page.waitForSelector('.avatar');
if (!element) throw new Error('Avatar not found');
try {
  const base64 = await element.screenshot({ encoding: 'base64' });
  console.log(base64);
} finally {
  await element.dispose();
}

Elements that are hidden, moving, or replaced

Outside the viewport

The method scrolls the target into view before capturing it. You do not need to call scrollIntoView() for a normal off-screen element. If a sticky header covers the result, add page-side scrolling or CSS adjustments before the screenshot and verify the rendered output.

Detached handles after re-rendering

Single-page applications may replace a node after you select it. A handle to the old node is then detached, and ElementHandle.screenshot() throws. Re-query after the update rather than reusing the stale handle:

await page.click('[data-action="refresh"]');
await page.waitForSelector('.target-element');
const current = await page.$('.target-element');
if (!current) throw new Error('Target disappeared after refresh');
try {
  await current.screenshot({ path: 'fresh.png' });
} finally {
  await current.dispose();
}

Animations and layout shifts

Pause animations with a temporary stylesheet or wait for a stable state. A screenshot taken while a chart, font, or image is still changing can be valid but visually inconsistent. For deterministic captures, wait for the final selector and, where possible, an application signal that data and fonts are ready.

Shadow DOM and iframes

A selector in the main document cannot directly reach an element inside an iframe. Obtain the frame, then query within that frame. Shadow-root selectors require the selector syntax supported by your installed Puppeteer version. Keep the same rule: obtain a handle from the correct browsing context and capture it before that node is replaced.

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.

Reusable helper with timeout and cleanup

This helper centralizes null checks, timeout handling, and handle disposal:

async function captureElement(page, selector, path, timeout = 30_000) {
  const element = await page.waitForSelector(selector, { timeout });
  if (!element) {
    throw new Error(`No element matched ${selector}`);
  }
  try {
    await element.screenshot({ path });
  } finally {
    await element.dispose();
  }
}

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await captureElement(page, '.target-element', 'element.png');
} finally {
  await browser.close();
}

Dispose handles in long-running workers. Always close the browser in a finally block so a selector timeout or screenshot failure does not leave Chromium processes behind.

Troubleshooting

“Cannot read properties of null”

page.$() returned null. Confirm the selector, URL, frame, and timing. Replace immediate lookup with waitForSelector() or a locator, and retain an explicit null check.

Timeout waiting for selector

The selector never appeared before the timeout. Inspect the page at the actual URL, check whether content is behind authentication or a consent flow, and verify that the element is not inside an iframe or shadow root. Increase the timeout only after fixing an incorrect readiness assumption.

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

Element is detached from the DOM

The page replaced the node between selection and capture. Wait for the update to finish, then select a new handle immediately before screenshot(). Avoid holding handles across clicks, route changes, or framework re-renders.

The file is blank or incomplete

Check that the target has dimensions and is visible, wait for its data and images, and disable or await animations. If navigation is still in progress, use a targeted readiness condition rather than capturing immediately after goto().

Browser launch fails in CI

Use the browser executable and sandbox settings required by your CI image, and confirm that the Puppeteer-installed browser is available. This is an environment issue rather than an element-selection issue; log the launch error and browser version before changing screenshot code.

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

Or skip the browser setup

ScreenshotNeo captures a URL or a CSS-selected element through one HTTP request. It removes cookie and consent banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with the result identified by response headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. Element capture and the other 63 options are documented at https://screenshotneo.com/docs/.

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

For an element, pass the target CSS selector using the API’s element option:

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

The same request in Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://example.com",
        "selector": ".target-element",
    },
    timeout=90,
)
r.raise_for_status()
open("element.webp", "wb").write(r.content)

And Node.js:

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

ScreenshotNeo’s free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is included on every plan. Create a free ScreenshotNeo account to get started.

Best Value
The SQL Programming Language: .
  • Used Book in Good Condition

FAQ

Does an element screenshot include the whole page?

No. It captures the selected element’s rendered region, not an unrelated page area.

Can I capture the same element repeatedly?

Yes, but reacquire the handle after actions that may re-render or replace the node.

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

Which method should new Puppeteer code use?

Use a locator for normal selection and readiness, then call waitHandle() when the screenshot API requires an ElementHandle. Use waitForSelector() for a straightforward lower-level workflow.

Frequently Asked Questions

Can I capture an element without saving a file?

Yes. Omit the path and use the returned Uint8Array, or set encoding to base64 for a string.

Why does Puppeteer scroll before the screenshot?

ElementHandle.screenshot() brings an off-screen target into view automatically before delegating to the page screenshot implementation.

What happens if the selector matches several nodes?

page.$() and waitForSelector() use the first matching element; use a more specific selector when the first match is not the intended target.

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

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
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver 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.