ScreenshotNeo

BlogHow-to

How to Capture a Specific Area with a Puppeteer Screenshot Clip

Capture a precise rectangle with Puppeteer’s clip option, or screenshot a DOM element when its boundaries define the area you need.

By the ScreenshotNeo team4 October 20265 min read

Use page.screenshot({ clip: { x, y, width, height } }) to capture a rectangular area of a page. Use ElementHandle.screenshot() when a DOM element defines the area you want. A clip describes page coordinates and dimensions; it is not necessarily limited to what is currently visible in the viewport.

1. Install Puppeteer

This runnable Node.js example launches Puppeteer, loads a page, captures a rectangle, and closes the browser. The coordinate values are examples; adjust them for the page and area you want.

npm install puppeteer
// capture-clip.js
const puppeteer = require('puppeteer');

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

    await page.screenshot({
      path: 'area.png',
      clip: { x: 100, y: 80, width: 400, height: 250 },
    });
  } finally {
    await browser.close();
  }
})();

Run it with node capture-clip.js. The example uses networkidle2 as a navigation readiness condition; for pages with persistent network activity, choose a different readiness condition or wait for a specific selector.

2. Set the clip rectangle

The clip object takes x, y, width, and height. Coordinates and dimensions describe the intended rectangle for the page being captured. A clip also has an optional scale value, which defaults to 1.

await page.screenshot({
  path: 'area.png',
  clip: {
    x: 100,
    y: 80,
    width: 400,
    height: 250,
    scale: 1,
  },
});

Choose a clip when the area is geometric, spans several elements, or has no single useful DOM node. Set the viewport before measuring or choosing coordinates, and keep it consistent between runs. The clip’s capture behavior can extend beyond the viewport: Puppeteer documents captureBeyondViewport as defaulting to false when there is no clip and true when a clip exists.

3. Capture a DOM element instead

If the area is one identifiable element, wait for it and call its screenshot method. This avoids manually maintaining a rectangle when the element’s size or position changes.

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

ElementHandle.screenshot() attempts to scroll an element into view if it is hidden. A selector-based screenshot is often the better fit for a card, chart, product image, or component whose bounds are represented by one node. A rectangular clip is still the right choice for a region that crosses element boundaries.

4. Choose the output format and consume the result

Providing path writes an image file; Puppeteer infers its image format from the file extension. PNG is the documented default. JPEG quality can be set from 0 to 100; the quality setting does not apply to PNG.

await page.screenshot({
  path: 'area.jpg',
  type: 'jpeg',
  quality: 80,
  clip: { x: 100, y: 80, width: 400, height: 250 },
});

Without path, the call returns image data (normally a Uint8Array). You can write those bytes yourself or request base64 output with the API’s encoding overload, which returns a string.

const bytes = await page.screenshot({
  clip: { x: 100, y: 80, width: 400, height: 250 },
});
require('node:fs').writeFileSync('area.png', bytes);

For image-format details and overloads, see the official ScreenshotOptions, ScreenshotClip, and Page.screenshot() references.

5. Decide when the page is ready

Capture only after the content in the target region has rendered. Navigation completion does not guarantee that client-side rendering, delayed images, fonts, or animations have finished.

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('.target');
await page.screenshot({
  path: 'area.png',
  clip: { x: 100, y: 80, width: 400, height: 250 },
});

Use a selector that signals the specific content is ready when possible. If the page changes layout after capture begins, wait for that state or disable the page’s animation in a controlled test environment. Do not rely on a fixed sleep as the only readiness check when a page can load at different speeds.

6. Common problems and fixes

Symptom Likely cause Fix
The screenshot contains the wrong region Clip coordinates were chosen for a different viewport or page layout. Set the viewport before navigation and capture; recompute the rectangle after responsive layout changes.
The result is blank or missing dynamic content The screenshot ran before the target rendered. Wait for a target selector or another page-specific ready condition before capturing.
The target element cannot be found The selector is incorrect, the element is inside a frame, or it has not appeared yet. Verify the selector and wait for it. For framed content, locate the relevant frame and query within it.
The element screenshot is positioned unexpectedly The element was offscreen or the page scrolled to bring it into view. Account for element scrolling, or use an explicit page clip when fixed page coordinates are required.
The image is larger or slower to handle than expected PNG is lossless and can be large, especially for detailed or large regions. Use JPEG with an appropriate quality value when lossy output is acceptable; keep PNG when lossless detail is needed.
The output file format is unexpected The path extension and requested type do not match. Use a matching extension and type; if relying on path inference, use the intended extension.

7. Performance, reliability, and cost

A smaller clip produces less image data than capturing an unnecessarily large region, and JPEG may reduce output size when some loss is acceptable. Keep the browser open for a batch of captures instead of launching a fresh process for each image. Close pages and browsers in cleanup paths so a failed navigation does not leave processes running.

For repeatable output, fix the viewport, wait for the relevant content, and use stable selectors or measured coordinates. Responsive layouts, web fonts, animation, cookie prompts, and changing page content can all affect the captured result. Puppeteer itself is a browser automation library; operational costs depend on where and how you run the browser, which this documentation does not quantify.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF, and its API documentation covers the available capture options.

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

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. 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. Sign up free and get 1,000 screenshots a month with no card.

FAQ

Should I use a clip or an element screenshot?

Use a clip for explicit rectangular coordinates; use ElementHandle.screenshot() when a selector identifies the whole target element.

Does a clip capture only what is visible?

Not necessarily. Puppeteer’s documented default for captureBeyondViewport is conditional: false without a clip and true when a clip is present.

What does scale do in a clip?

It is an optional ScreenshotClip field and defaults to 1. Leave it at the default unless you need a different clip scale.

Does the JPEG quality option change PNG output?

No. The quality option applies to JPEG, not PNG.