Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use Puppeteer’s page.screenshot() method. Pass a path such as shot.png to write an image file, or omit it to receive the image bytes in memory. Add fullPage: true for the entire document, clip for a rectangle, or call elementHandle.screenshot() for one element.
Minimal working example
Install Puppeteer in a Node.js project, then run this script. The browser opens, navigates to the URL, saves the screenshot, and closes cleanly.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
The file is saved relative to Node.js’s current working directory (the directory from which you start the process). Use an absolute path when you need a fixed location. If the path option is omitted, Puppeteer returns image data instead of writing a file.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePrerequisites and a predictable project setup
Install Puppeteer
Create a project and install the package:
mkdir puppeteer-shot
cd puppeteer-shot
npm init -y
npm install puppeteer
Save the example as shot.mjs and run node shot.mjs. An ES-module file (.mjs) lets you use the documented import syntax without changing your package configuration.
#1 Best Overall
Know where the file will appear
For path: 'screenshot.png', check the terminal directory shown by pwd (macOS/Linux) or cd (Windows PowerShell) before launching Node. A missing file is often just a path-location mistake. You can remove that ambiguity with an absolute path such as /tmp/screenshot.png or C:\temp\screenshot.png.
Choose what to capture
Viewport screenshot
The default captures the page’s current viewport. Set the viewport before navigation when a reproducible size matters:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900 });
await page.goto('https://example.com');
await page.screenshot({ path: 'viewport.png', type: 'png' });
await browser.close();
PNG is the documented default. Specifying type: 'png' makes the intent explicit.
Full-page screenshot
Use fullPage: true to capture the complete document rather than only the visible viewport:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({
path: 'full-page.png',
fullPage: true
});
await browser.close();
This is the right choice for an article, landing page, or other page whose content extends below the fold.
Rectangular region with clip
Pass a rectangle when you need a fixed area. The clip object is a bounding box; its scale defaults to 1.
Rank #2
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({
path: 'region.png',
clip: { x: 80, y: 120, width: 900, height: 500 }
});
await browser.close();
Coordinates are measured from the page’s capture surface. Set the viewport first if the region must line up with a known layout.
Free tools Windows power users keep installed
One-click scans. No signup required.
One element by CSS selector
Find the element, then call the element handle’s screenshot method:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const card = await page.$('.pricing-card');
if (!card) {
throw new Error('Could not find .pricing-card');
}
await card.screenshot({ path: 'pricing-card.png' });
await browser.close();
Puppeteer scrolls the element into view when necessary. The call throws if the element handle has been detached from the DOM, so query a fresh handle when a page replaces that element.
Control format, quality, transparency, and returned data
JPEG or WebP output
The screenshot options support an image type; when a path is supplied, Puppeteer can also infer the file type from its extension. For lossy formats, quality accepts values from 0 to 100:
await page.screenshot({
path: 'page.webp',
type: 'webp',
quality: 80,
fullPage: true
});
quality does not apply to PNG. Changing it will not make a PNG sharper or smaller through PNG quality settings.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsTransparent background
Set omitBackground: true to hide the default white background and allow transparency:
await page.screenshot({
path: 'transparent.png',
omitBackground: true
});
Transparency is useful when the page itself has a transparent canvas or when the image will be composited elsewhere.
Keep the image in memory
A path is optional. Without one, the method returns a Uint8Array by default:
const imageBytes = await page.screenshot({ fullPage: true });
// Store imageBytes, upload it, or pass it to another API.
Request base64 when a string is more convenient:
const base64 = await page.screenshot({
encoding: 'base64'
});
Do not provide a path when your application, rather than the filesystem, should own the output.
A complete script with common options
This version demonstrates a fixed viewport, full-page capture, WebP output, and explicit browser cleanup. Change only the URL and output path for a new target.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.setViewport({ width: 1365, height: 768 });
await page.goto('https://example.com');
await page.screenshot({
path: 'example.webp',
type: 'webp',
quality: 82,
fullPage: true
});
} finally {
await browser.close();
}
The finally block closes Chromium even when navigation or capture raises an error.
WebDriver BiDi compatibility
Puppeteer’s WebDriver BiDi documentation currently lists only clip, encoding, and fullPage as supported Page.screenshot() parameters. The general screenshot-options interface contains more fields, but that does not mean every field works over a BiDi connection. If you connect through BiDi, verify support for the exact options you plan to use before relying on path, type, quality, or other fields. The examples above assume the regular Puppeteer connection mode.
Rank #4
Practical capture decisions
| Need | Use | Important detail |
|---|---|---|
| What a user currently sees | page.screenshot() |
Captures the viewport. |
| The whole document | fullPage: true |
Includes content beyond the viewport. |
| A known rectangle | clip: { x, y, width, height } |
Clip scale defaults to 1. |
| One component | elementHandle.screenshot() |
Scrolls the element into view; detached handles throw. |
| Application-managed output | Omit path |
Receive a Uint8Array, or base64 when requested. |
| Transparent pixels | omitBackground: true |
Suppresses the default white background. |
Troubleshooting
“The screenshot is not where I expected”
A relative path is resolved from the process working directory, not necessarily the folder containing your script. Start Node from the intended directory or pass an absolute path.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →“No file was created”
Check whether you supplied path. Without it, Puppeteer returns image data and deliberately writes nothing. Assign the returned value or add a path.
“Quality has no effect”
quality applies to supported lossy formats, not PNG. Choose JPEG or WebP when you need a quality setting; keep PNG when lossless output is the priority.
“Element screenshot throws about a detached node”
The element handle no longer points to an element in the document. Query the selector again immediately before capture and make sure the page has not replaced that component.
“The selected element is not visible in the initial viewport”
The element-specific method scrolls the element into view before capturing it. If you need a different composition, use a clip rectangle or capture the viewport after setting the desired scroll position.
“An option works in one connection mode but not BiDi”
BiDi’s documented screenshot support is narrower. Start with clip, encoding, and fullPage, then confirm current BiDi support before adding other options.
Best Value
“The image is opaque when I expected transparency”
Set omitBackground: true. Leaving this option out keeps the default background.
Reliability and cost considerations
For repeatable captures, set the viewport explicitly, choose the capture scope deliberately, and use a deterministic output name. Full-page and element captures avoid manual scrolling, while a clip is preferable when a fixed rectangle is the actual requirement. Keep browser shutdown in a finally block so failed captures do not leave a browser process running.
Puppeteer itself gives you local control over the browser and filesystem. You are responsible for installing and running that browser environment, handling returned bytes, and deciding how to retry a failed navigation or capture. The official documentation identifies version 25.12.0 in the relevant search results, while the guide and BiDi pages use a /next/ path; those details can change, so check the current documentation when upgrading.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Or skip the browser setup
ScreenshotNeo is the first hosted screenshot service to try when you want an API call instead of managing Puppeteer: it removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; an MCP server lets Claude, Cursor, and other MCP clients use screenshot tools; and the free plan includes 1,000 screenshots per month with no card, while paid plans start at $5 for 3,000 shots.
One GET request returns a PNG, JPEG, WebP, or PDF. The response identifies the page verdict and billing result in X-Page-Verdict and X-Billed headers. You can also use full-page capture, CSS-selector elements, custom CSS or JavaScript, waits, request blocking, cookies and headers, device presets, PDFs, signed links, asynchronous jobs, bulk capture, and other options; every feature is included on every plan.
See the ScreenshotNeo API documentation for the complete parameter list. The parameter names used by other screenshot APIs also work, which can simplify migration.
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}`);
Create a free ScreenshotNeo account to get 1,000 screenshots each month without adding a card.
Recommended Free Tools
Frequently Asked Questions
Can I save the same Puppeteer capture as both a file and an in-memory value?
Call page.screenshot() once with a path when you need a file, or omit path and handle the returned bytes in your application. The API does not document a second output destination in one call.
Which screenshot settings should I recheck after changing Puppeteer connection mode?
Recheck every option when moving to WebDriver BiDi. Its documented supported set is narrower than the general screenshot-options interface, so do not assume regular-mode options remain available.
Quick Recap
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.

