Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
JavaScript

How to Screenshot Child Elements Individually with Puppeteer

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

Use Puppeteer’s ElementHandle.screenshot() once for each matched child. Query the children with a CSS selector, then save each handle to a different file. Puppeteer scrolls an element into view if needed; if the page changes and an element is detached, query it again before capturing.

Capture each child with its own screenshot

For separate image files, select the intended child elements and call screenshot() on each returned handle. The selector below matches direct children of .parent that have the class .child; change it to match the elements on your page.

const children = await page.$$('.parent > .child');

for (const [index, child] of children.entries()) {
  await child.screenshot({ path: `child-${index}.png` });
}

Each call captures that element rather than taking a screenshot of the entire page. The index makes the output paths distinct, so a later capture does not overwrite an earlier one. If filenames need to correspond to meaningful records, construct them from a stable identifier in your application and ensure each path is unique.

A complete Node.js example

This script launches Chromium through Puppeteer, opens a page, waits for the target selector, captures every match as a PNG, and closes the browser even if navigation or capture fails. Puppeteer must already be installed in the project. Replace the example URL and selector with the page and child elements you want to capture.

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.
#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();

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

    const selector = '.parent > .child';
    await page.waitForSelector(selector);

    const children = await page.$$(selector);
    if (children.length === 0) {
      throw new Error(`No elements matched: ${selector}`);
    }

    for (const [index, child] of children.entries()) {
      await child.screenshot({ path: `child-${index}.png` });
    }
  } finally {
    await browser.close();
  }
})();

waitForSelector() ensures the selector appears before the query runs; it does not guarantee that every element has finished any later content changes. If the page updates the target nodes after they appear, wait for the page’s relevant state before taking the handles, or query again after the update. The example uses domcontentloaded as a navigation milestone, not as proof that every image or application-rendered element is ready.

Choose a selector that matches the intended children

Direct children versus any descendant

The selector .parent > .child matches elements with class child that are direct children of an element with class parent. If the desired elements can be nested at any depth, use a descendant selector such as .parent .child. A broader selector can capture nested matches you did not intend, so prefer a selector tied to the exact component or repeated item.

Check the match count

page.$$(selector) returns the matching element handles as an array. An empty array means no elements matched at query time; it does not create an error by itself. Check the count before the loop so that a changed page or incorrect selector is not mistaken for a successful batch that produced no files. If the count is larger than expected, inspect the selector and narrow it before saving outputs.

Rank #2
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Take fresh handles after page changes

An ElementHandle refers to a particular DOM element, not merely to a selector that Puppeteer can resolve forever. If navigation or a DOM update removes that element, its handle becomes detached and ElementHandle.screenshot() throws. When a page transition or rerender occurs between selection and capture, query the selector again after the change and use the new handles.

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

What an element screenshot includes

ElementHandle.screenshot() is the built-in option when the target is an element in the DOM. It scrolls the element into view when needed, then captures it using the page screenshot mechanism. Its screenshot options expose scrollIntoView, which defaults to true in the documented API reference. This avoids having to calculate a page-coordinate rectangle for each matched element.

An element must have layout bounds to be captured. Puppeteer’s ElementHandle.boundingBox() returns bounds relative to the main frame, or null when the element is not part of layout; an element styled with display: none is one example. If a target has no bounds, making a screenshot call is not a substitute for making the element render. Check its visibility and layout state first.

Capturing an element is different from asking for a full-page screenshot. Page.screenshot() captures the page; its fullPage option defaults to false. Use the element method for a DOM target and page-level clipping for a custom rectangle.

Use clipping for a rectangle, not a DOM target

If the desired output is defined by page coordinates rather than by an element, use Page.screenshot({ clip }). The clip option describes a region of the page to capture. This is useful when the region crosses element boundaries or when you already have a rectangle to reproduce. It requires you to work with the coordinates and dimensions of that region; for ordinary child elements, the element handle method does that targeting for you.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.screenshot({
  path: 'region.png',
  clip: { x: 100, y: 200, width: 400, height: 250 }
});

The numeric rectangle above is only an example. Set its values for the page layout and region you actually need. Clipping is not a way to select every matching child automatically: for a set of separate DOM nodes, query the nodes and capture each handle.

Make a batch reliable and easy to inspect

Wait for the right state

Wait for the selector before querying, as in the complete example. If the site renders children asynchronously, the mere presence of one match might not mean the entire list is ready. Add an application-appropriate condition before selecting, such as waiting for a known completion marker or for the expected content to be present. Avoid taking handles and then allowing a navigation or rerender to replace those nodes before capture.

Save to distinct paths

Use a separate output path for every capture. A simple numeric index is convenient for a one-off sequence; for recurring jobs, include a stable item identifier and, if necessary, a run-specific directory. This makes it easier to map images back to their source items and prevents unintended overwrites. The screenshot examples use PNG paths; choose another extension only when your capture configuration is set up to produce that format.

Capture sequentially when the page is shared

The loop awaits each screenshot before moving to the next handle. That ordering is straightforward to debug and avoids scheduling multiple captures against a page whose viewport may scroll as each element is brought into view. It also makes failures easier to associate with an individual output. If throughput matters, measure the actual job before changing the capture strategy; the documentation cited here does not establish a general speed advantage for parallel captures.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
JavaScript and jQuery: Interactive Front-End Web Development
  • JavaScript Jquery
  • Introduces core programming concepts in JavaScript and jQuery
  • Uses clear descriptions, inspiring examples, and easy-to-follow diagrams

Keep the browser lifecycle bounded

Close the browser in a finally block so an exception does not leave the launched browser running. In a larger worker, apply the same principle at the lifecycle boundary you own: close the page or browser when the job ends, and record which selector and output path failed. The example throws for a zero-match result so that an empty batch cannot silently look like a completed capture.

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

Troubleshoot common failures

Symptom Likely cause What to do
No files are produced, or the loop is skipped The selector matched zero elements at query time. Check the selector against the current page and wait for the target content to appear before calling page.$$().
ElementHandle.screenshot() reports a detached element The page navigated or the DOM changed after the handle was obtained. Wait until the new page state is ready, then query the selector again and capture the replacement handles.
The target has no usable bounds It may not be part of layout, for example because it has display: none. Check the element’s visibility and layout. Use boundingBox() to inspect whether Puppeteer returns bounds; it returns null when the element is not part of layout.
The image shows a different portion of the page than expected You may be using a page screenshot or a clip when the task is to capture a DOM element, or vice versa. Use ElementHandle.screenshot() for a selected element; use Page.screenshot({ clip }) for a custom coordinate rectangle.
A later image replaces an earlier one Multiple captures were written to the same path. Generate a distinct path for every item, such as an index-based filename or a stable item identifier.

Version notes

The official Puppeteer screenshot guide and ElementHandle.screenshot() documentation identified version 25.12.0 at the time covered by the documentation reviewed for this article. Related references surfaced version 25.5.0 for boundingBox() and 25.9.0 for ElementScreenshotOptions. Documentation pages can change, so check the references for the version installed in your project when a detail depends on a specific release.

Or skip the browser setup

If you need a website screenshot without launching and managing Puppeteer, ScreenshotNeo takes a URL in one request. It can also capture an element by CSS selector; use Puppeteer’s method above when you need explicit control over a batch of child handles and separate per-child output files.

Quick Recap

SaleBestseller No. 1
HTML and CSS: Design and Build Websites
HTML and CSS: Design and Build Websites
HTML CSS Design and Build Web Sites; Comes with secure packaging; It can be a gift option
$14.18
SaleBestseller No. 2
Web Design with HTML, CSS, JavaScript and jQuery Set
Web Design with HTML, CSS, JavaScript and jQuery Set
Brand: Wiley; Set of 2 Volumes
$35.05
SaleBestseller No. 3
SaleBestseller No. 5
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript Jquery; Introduces core programming concepts in JavaScript and jQuery; Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
$22.80

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
  • Cookie and consent banners are accepted before capture, and more than 60 known consent platforms, newsletter popups, and chat widgets are removed; each step can be turned off.
  • Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools 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 screenshots.

Sign up for ScreenshotNeo’s free plan.

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.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
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.