ScreenshotNeo

BlogHow-to

How to Capture a Puppeteer Screenshot After Scrolling to an Element

Capture one element with Puppeteer after scrolling it into view. See the runnable code, options, troubleshooting tips, and a no-browser-setup alternative.

By the ScreenshotNeo team4 October 20266 min read

Use ElementHandle.screenshot() to capture one element. Puppeteer scrolls the element into view if needed; the documented scrollIntoView option defaults to true. This is usually all you need:

const element = await page.waitForSelector('#target');
if (!element) {
  throw new Error('Target not found');
}
await element.screenshot({ path: 'target.png' });

This saves the element itself, rather than the whole page. The examples below use Puppeteer 25.12.0 documentation as their reference; check the API docs for the version installed in your project.

1. Install Puppeteer and capture an element

In an existing Node.js project, install Puppeteer:

npm install puppeteer

Save the following as capture-element.js and run it with node capture-element.js. It opens a page, waits for the target selector, and saves only that element to target.png in the current working directory.

const puppeteer = require('puppeteer');

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

    const element = await page.waitForSelector('#target', { timeout: 15000 });
    if (!element) {
      throw new Error('Target #target was not found');
    }

    await element.screenshot({ path: 'target.png' });
    await element.dispose();
  } finally {
    await browser.close();
  }
})().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

Replace the URL and selector with the page and element you need. Use an element that exists in the page DOM, such as #product-card or [data-testid="receipt"]. The official guide demonstrates waiting for a selector and then calling element.screenshot({ path: ... }). Puppeteer screenshot guide

2. Scroll explicitly when the workflow needs it

The element screenshot method scrolls into view automatically. Call scrollIntoView() yourself when scrolling needs to happen as a distinct step—for example, if you want to perform another action after the scroll and before capture:

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

await element.scrollIntoView();
// Optional: wait for application-specific content or animation here.
await element.screenshot({ path: 'target.png' });

Puppeteer documents ElementHandle.scrollIntoView() as an explicit scrolling method. Avoid adding a fixed delay unless the page has a known animation or delayed rendering; prefer waiting for the condition your application needs.

3. Choose element capture or page capture

Goal Use Result
Save one element element.screenshot() The element’s visible rendered bounds, with scrolling into view enabled by default.
Save the page viewport page.screenshot() A screenshot of the current page viewport.
Save the whole page page.screenshot({ fullPage: true }) A full-page screenshot rather than a single DOM element.
Save a chosen page region page.screenshot({ clip: { x, y, width, height } }) A rectangular region specified in page screenshot coordinates.

Use element capture when you want the element’s own bounds. Use page capture with clip when you need a particular region of the page, or fullPage when you need the complete document. Puppeteer’s screenshot guide covers both page and element screenshots. Screenshot guide

4. Screenshot options and output

ElementHandle.screenshot() accepts screenshot options, including the documented scrollIntoView behavior. Relevant screenshot options documented by Puppeteer include:

  • path: write the image to a file. The file extension determines the image format; a relative path is resolved from the current working directory.
  • fullPage: capture the full page when using page screenshot capture.
  • clip: capture a specified rectangle when using page screenshot capture.
  • captureBeyondViewport: control capture beyond the viewport where applicable.
  • scrollIntoView: for element screenshot capture, controls scrolling the element into view; its documented default is true.

Check the API reference for the exact supported combination and defaults in your installed Puppeteer version. The element screenshot documentation does not promise custom alignment, such as placing the element at the top of the viewport; do not rely on a particular alignment unless your version and page behavior confirm it.

References: ElementHandle.screenshot(), ElementScreenshotOptions, and ScreenshotOptions.

5. Make the capture reliable

  1. Wait for the target. Use waitForSelector() with a timeout that fits the page. If the selector is absent, fail clearly instead of attempting a screenshot with a missing handle.
  2. Wait for the right page state. A selector can exist before its content, images, or application data are ready. Wait for an application-specific selector or state before capturing.
  3. Capture a stable element. Puppeteer documents that element screenshot capture throws if the element has been detached from the DOM. If the page replaces nodes during rendering, wait for the final target and reacquire the handle.
  4. Close resources. Put browser.close() in a finally block so the browser closes after both successful captures and errors.
  5. Use a predictable output path. Relative paths are based on the process working directory. Use an absolute path if a job runner or service may start from different directories.

6. Troubleshooting

Symptom Likely cause Fix
waitForSelector times out The selector is wrong, the page has not rendered it, or navigation did not reach the expected page. Inspect the selector in the page, confirm the URL and navigation outcome, and wait for the page-specific condition that creates the element.
Screenshot fails because the element was detached The application replaced or removed the DOM node between lookup and capture. Wait for the final render, query the selector again, and capture the fresh handle.
The capture contains the wrong content The selected element is not the intended node, or its contents were still loading. Use a more specific selector and wait for the expected text, data, or child element before capture.
The file cannot be found The relative path was resolved from a different current working directory. Log process.cwd() or save to an absolute path and ensure its parent directory exists.
The browser remains running after an error Cleanup did not run on the failure path. Close the browser in finally, as in the complete example.
The element is not positioned where expected Element screenshot capture scrolls it into view, but the reviewed API does not promise a custom viewport alignment. Use explicit scrollIntoView() as a separate step if needed, and validate the result for your page and Puppeteer version.

7. Performance, reliability, and cost

A local Puppeteer screenshot requires launching or reusing a browser, navigating to the page, waiting for the element, and encoding the output. For repeated captures, reuse a browser process where your service design permits and create pages as needed; always close pages and the browser when the job lifecycle ends. Set navigation and selector timeouts so a slow or unreachable page cannot hold a worker indefinitely.

Capture only the element when that is the requested output; a full-page capture can produce much larger images and take longer to encode. Page content is dynamic, so stable selectors and application-specific readiness checks matter more than arbitrary sleeps. Puppeteer itself does not charge per screenshot; operational cost depends on the machine and browser infrastructure you run.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Send one request with the target URL to get an image or PDF; see the API documentation. For example, this cURL request saves a WebP screenshot:

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,
)
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(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. These calls capture a URL; use Puppeteer when you need to select an element by a page-specific CSS selector.

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

9. FAQ

Does taking an element screenshot scroll the page automatically?

Yes. Puppeteer’s documented element screenshot behavior scrolls the element into view when needed, and scrollIntoView defaults to true.

Can I save only the element and not the surrounding page?

Yes. Call screenshot() on the element handle. Use page.screenshot() when you want a page or viewport capture.

What happens if the element disappears?

The API reference says element screenshot capture throws if its element is detached from the DOM. Wait for a stable target and reacquire it if the page replaces the node.

Can I force the element to the top of the viewport?

The reviewed element screenshot options do not document a custom alignment setting. You can explicitly scroll before capture, but verify the resulting alignment for your Puppeteer version and page.

References