Puppeteer Element Screenshot Options Explained
Capture a DOM element with Puppeteer and choose the right screenshot options for format, quality, transparency, output, clipping, and scrolling.
Puppeteer captures a DOM element with ElementHandle.screenshot(). Wait for the element, call the method, and either provide a path to save an image or use the returned binary bytes in your program. By default, Puppeteer scrolls the element into view and returns a PNG as a Uint8Array. A detached element causes the method to throw. Puppeteer ElementHandle.screenshot() reference
Runnable example: save an element as a PNG
The following script launches Chromium, opens a page, waits for a CSS selector, captures that element, and closes the browser. It uses a public page as an example; replace the URL and selector with the page and element you need.
import puppeteer from 'puppeteer';
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('h1', { timeout: 15000 });
if (!element) throw new Error('The selector did not match an element');
await element.screenshot({ path: 'heading.png' });
console.log('Saved heading.png');
} finally {
await browser.close();
}
Save this as capture.mjs, then install and run it:
npm install puppeteer
node capture.mjs
ElementHandle.screenshot() scrolls the element into view when needed, then uses Page.screenshot() to capture it. The element must still be attached to the DOM when capture occurs. Puppeteer screenshots guide
Options you can pass
Element screenshot options extend Puppeteer’s general screenshot options. You can control scrolling, file output, image format, quality, transparency, clipping, and the returned data representation. Check the current ScreenshotOptions reference when upgrading Puppeteer; defaults and signatures can change by version.
| Option | Behavior | When to use it |
|---|---|---|
scrollIntoView |
Element-specific control. Defaults to true. |
Leave enabled for ordinary captures. Set false when you need to avoid Puppeteer’s automatic scrolling and have handled the element’s visibility and page state yourself. |
path |
Saves the screenshot. Format is inferred from the filename extension. Relative paths are resolved from the current working directory. Without a path, no file is saved. | Use a path such as card.png when you want a file on disk. |
type |
Chooses the image format; the documented default is 'png'. |
Choose a supported output format that fits the consuming system. Keep the extension in path consistent with the chosen format. |
quality |
A number from 0 to 100 for applicable formats; it does not apply to PNG. No default is listed. | Set it when using a format for which quality is applicable and you need to control the output trade-off. |
encoding |
Defaults to 'binary'. With 'base64', the method returns a string instead of binary bytes. |
Use binary for files and byte-oriented APIs; use base64 only if the receiving code needs a base64 string. |
omitBackground |
Defaults to false. When true, Puppeteer omits the default white background for transparent output. |
Useful when the element image will be placed over another background. |
clip |
Optionally specifies a screenshot region using ScreenshotClip. |
Use when you need a defined region. Consider whether clipping is needed when the element itself is the intended capture target. |
captureBeyondViewport |
Defaults to false without a clip and true with a clip. |
Set deliberately when your capture and clipping needs involve content outside the viewport. |
fullPage |
Defaults to false. |
This is a general screenshot option for full-page captures; an element screenshot targets the selected element. |
fromSurface |
Defaults to true; selects surface capture rather than view capture. |
Usually leave at the documented default unless you have a reason to choose the other capture source. |
optimizeForSpeed |
Defaults to false. The API reference does not specify a guaranteed performance gain or visual outcome. |
Only enable when the option fits your needs; validate output for your own page. |
These options do not guarantee a particular visual result for every page. Dynamic layouts, fonts, images, animations, and page state can affect what appears at capture time.
Choose the right output
Save to a file
Provide path; Puppeteer infers the image format from its extension. For example, path: 'card.png' saves a PNG. If you also set type, keep it consistent with the filename so the file’s extension describes its contents.
await element.screenshot({ path: 'card.png', type: 'png' });
Use the bytes in memory
Without a path, the method returns a promise for screenshot data. With default binary encoding, the result is a Uint8Array; pass it to code that accepts bytes or write it to a file yourself.
const bytes = await element.screenshot();
await import('node:fs/promises').then(({ writeFile }) => writeFile('card.png', bytes));
Request base64
Choose encoding: 'base64' only when a string is useful to the caller. The return type changes from binary bytes to a string.
const base64 = await element.screenshot({ encoding: 'base64' });
Make the captured background transparent
Set omitBackground: true to omit the default white background. Transparency depends on the page’s own backgrounds too: an opaque background applied by the page can still appear in the capture.
await element.screenshot({ path: 'card.png', omitBackground: true });
Choose format and quality
The documented default type is PNG. Quality is a number from 0 to 100 when applicable, but it has no effect on PNG. Puppeteer’s reference does not list a default quality. Choose format and quality based on the receiving system and inspect the actual output for your page.
await element.screenshot({ path: 'card.jpg', type: 'jpeg', quality: 80 });
Capture the intended element reliably
- Wait for a specific selector. Prefer the selector for the component you want over a broad selector such as
div. A broad selector may match an unintended element. - Wait for page content that the element needs. Selector presence only establishes that an element matched. If your page fills it with asynchronous content, wait for the relevant condition before capturing.
- Capture promptly after resolving the handle. A framework can replace or remove a node during a rerender. If it detaches before capture, Puppeteer throws; locate the current element again and retry when appropriate.
- Keep the browser lifecycle bounded. Close the browser in a
finallyblock so it is closed if navigation or capture fails. - Use one page state per intended image. If the page changes between locating the element and capturing it, the screenshot may not reflect the state you expected.
For a page where content readiness matters, wait for the selector and any application-specific condition before capturing. For example, a site might set a loading indicator to hidden when its content is ready; the condition and selector are specific to that site.
const element = await page.waitForSelector('[data-report-ready="true"]', { timeout: 15000 });
if (!element) throw new Error('Report did not become ready');
await element.screenshot({ path: 'report.png' });
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
waitForSelector times out |
The selector does not match, the page has not reached the needed state, or navigation failed. | Check the URL and selector, wait for the page condition the element depends on, and choose a timeout appropriate for the page. |
| Element screenshot reports a detached node | The page removed or replaced the element after Puppeteer found it. | Wait until the component is stable, resolve a fresh handle immediately before capture, and retry only if the page can safely be captured again. |
| The wrong element is captured | A selector matched a different or earlier element than intended. | Use a narrower selector and verify that it uniquely identifies the target component. |
| The element is not visible where expected | Automatic scroll behavior changed page scroll position, or the page state/layout differs from expectations. | Remember that scrollIntoView defaults to true. If that is undesirable, set it to false and arrange visibility and page state yourself. |
| A file has unexpected contents or extension | The path extension and explicitly selected output type may disagree. | Align the extension with type; without a path, handle the returned bytes or base64 string according to encoding. |
| PNG quality setting appears ineffective | The quality option does not apply to PNG. | Use a format where quality applies, or keep PNG and remove the quality setting. |
| Transparent capture still has a solid area | The page itself may paint an opaque background on the element or its contents. | Use omitBackground: true and inspect the page’s CSS backgrounds; this option removes the default background, not arbitrary page styling. |
| Screenshot has unexpected content | Capture happened before page-specific data or layout was ready. | Wait for the selector and the site’s actual readiness condition before calling screenshot(). |
Performance, reliability, and cost
Element capture uses Puppeteer’s page screenshot mechanism after bringing the element into view when needed. The API reference does not promise a fixed capture time or a specific speed benefit from optimizeForSpeed. Page loading and readiness waits are part of the overall workflow, so avoid waiting on conditions the target page does not need.
For reliable output, use a precise selector, wait for the content you need, and handle the possibility of a detached handle. Always close the browser even when a capture fails. If your application retries, bound retries and reacquire the element because the original handle may no longer refer to a live DOM node.
Puppeteer is an open-source browser automation library; this method itself has no per-screenshot API charge. Your costs depend on where and how you run the browser, such as compute and infrastructure. The source documentation provides no benchmark or cost estimate for a particular deployment.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its documentation has the API details. One GET request captures a URL; use the API when you need a page screenshot without managing a browser process in your code.
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}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', bytes));
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; each of those steps can be turned off. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, no card required.
FAQ
Does an element screenshot return the whole page?
The method captures the selected element. It scrolls the element into view by default and delegates the capture to Page.screenshot().
Can I prevent Puppeteer from scrolling the page?
Yes. Set scrollIntoView: false. The documented default is true.
What does the method return if I omit path?
By default it returns binary screenshot data as a Uint8Array. With encoding: 'base64', it returns a string.
Can I capture an element with a transparent background?
Set omitBackground: true. The option omits the default white background; page CSS can still paint backgrounds.
Why does the screenshot fail after the selector was found?
The page may have detached or replaced that DOM node. Resolve a fresh element handle after the page reaches the state you need, then capture it.


