Crashes, 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 minutePC 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 & 11iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Call page.screenshot() with fullPage: true. Puppeteer then captures the document beyond the current viewport. The smallest complete example is to launch a browser, open the URL, wait for navigation, save the image, and close the browser.
Minimal Puppeteer full-page screenshot
Install Puppeteer in a Node.js project, then save this as screenshot.mjs:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({
path: 'page.png',
fullPage: true,
});
} finally {
await browser.close();
}
Run npm install puppeteer, followed by node screenshot.mjs. The resulting page.png contains the full rendered page rather than only the visible viewport. The official Screenshots guide uses this same launch, navigation, capture, and close sequence.
What fullPage changes
fullPage belongs to Puppeteer’s page-level screenshot method and defaults to false. Setting it to true asks for the entire page. It is different from a viewport screenshot, which is limited to the current browser window. See the ScreenshotOptions reference for the documented option definitions.
#1 Best Overall
The capture represents the page state at the instant the screenshot runs. A navigation wait is necessary, but it is not proof that every application-rendered component, image, animation, or lazy-loaded section is ready. Treat networkidle2 as a useful starting point, then add a readiness signal for the site you are capturing.
Set up a repeatable capture script
1. Install and launch
Create a project and install Puppeteer:
mkdir page-capture
cd page-capture
npm init -y
npm install puppeteer
Use an .mjs file (or enable ES modules in package.json) so the import statement in the example runs directly. The finally block matters: it closes Chromium even when navigation or screenshot capture throws an error.
2. Choose a navigation wait
waitUntil: 'networkidle2' waits for a period with no more than two active network connections. It is the condition shown in Puppeteer’s guide, not a universal “page is finished” test. Single-page applications can render after that point, and some sites keep analytics or streaming connections open indefinitely.
When the page exposes a reliable application signal, wait for it explicitly:
Rank #2
await page.goto('https://example.com/dashboard', {
waitUntil: 'domcontentloaded',
});
await page.waitForSelector('[data-ready="true"]');
await page.screenshot({ path: 'dashboard.png', fullPage: true });
Replace the selector with a marker your application adds only after the content needed in the image is present. A fixed delay can help with a known animation, but a selector or other application-specific condition is usually more deterministic.
3. Trigger lazy-loaded content when necessary
Full-page capture does not guarantee that every lazy image has already loaded. If the page loads sections only after scrolling, scroll it before capturing and wait for the page’s own loading signal. This example is a starting pattern, not a universal lazy-loading solution:
await page.goto('https://example.com/articles', { waitUntil: 'networkidle2' });
await page.evaluate(async () => {
await new Promise(resolve => {
let y = 0;
const step = 600;
const timer = setInterval(() => {
window.scrollBy(0, step);
y += step;
if (window.innerHeight + window.scrollY >= document.body.scrollHeight || y > 100000) {
clearInterval(timer);
resolve();
}
}, 100);
});
});
await page.screenshot({ path: 'articles.png', fullPage: true });
For production jobs, prefer a page-specific signal that images have completed, and consider waiting for a selector after the scroll. Pages with infinite scrolling may never reach a final height; impose a limit or capture a defined state instead.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Save an image or keep it in memory
The path option writes the result to disk. Puppeteer infers the image type from the filename extension when a path is supplied. If you omit path, the method returns image data instead of creating a file. By default that result is a Uint8Array; requesting base64 encoding returns a string, as documented for Page.screenshot().
const bytes = await page.screenshot({ fullPage: true });
await writeFile('page.png', bytes);
const base64 = await page.screenshot({
fullPage: true,
encoding: 'base64',
});
Use the byte form when uploading directly to object storage or returning an HTTP response. Use base64 only when the receiving interface requires text; it increases the amount of data that must be represented in memory.
Screenshot options that matter for whole pages
| Option | What it does | Important detail |
|---|---|---|
fullPage |
Captures the full document when true. |
Defaults to false. |
path |
Saves the image to a file. | The extension determines the image type when a path is supplied. |
type |
Selects the image format. | The documented default is PNG. |
encoding |
Controls the returned data representation. | The documented default is binary; base64 returns a string. |
clip |
Restricts the capture to a rectangle. | A clip changes the capture area, so it is not an unbounded whole-page image. |
captureBeyondViewport |
Controls capture outside the viewport. | The reference documents a default of false with no clip and true when a clip is present. |
omitBackground |
Omits the default background. | Useful when you need transparency and the page supports it. |
quality |
Controls lossy image quality. | Applies to formats other than PNG. |
fromSurface |
Selects the browser surface used for capture. | Keep protocol-specific behavior in mind when changing it. |
optimizeForSpeed |
Requests speed-oriented encoding. | Choose it only when its output trade-off suits your workflow. |
Not every option is available in every browser or protocol mode. In particular, Puppeteer’s WebDriver BiDi documentation lists the supported screenshot parameters and warns that the complete screenshot option set is not supported there.
Whole page versus one element
Use Page.screenshot({ fullPage: true }) for the document. If the requirement is a card, chart, invoice, or other single node, locate that node and call ElementHandle.screenshot() instead:
Recommended Free Tools
const card = await page.waitForSelector('.invoice-card');
if (!card) throw new Error('Invoice card was not found');
await card.screenshot({ path: 'invoice-card.png' });
ElementHandle.screenshot() scrolls the element into view when needed. It can fail if the element has been detached from the DOM between lookup and capture, which is common in frequently re-rendered interfaces; locate it again after the render settles.
Rank #4
Control the rendering environment
A whole-page image is affected by the viewport, device scale factor, color scheme, fonts, and authentication state. Set these before navigation when they are part of the result you want:
await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
await page.emulateMediaFeatures([
{ name: 'prefers-color-scheme', value: 'light' },
]);
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'light-desktop.png', fullPage: true });
Use a consistent viewport in automated comparisons. If a site serves different markup to mobile and desktop, capture each intended viewport separately rather than assuming one “full page” represents all layouts.
Troubleshoot incomplete or failed captures
The image stops at the viewport height
- Confirm the option is exactly
fullPage: trueonpage.screenshot(), not on an unrelated call. - Check whether a
cliprectangle limits the capture. - Make sure you are opening the newly written file, not an older artifact from a previous run.
Images or lower sections are blank
networkidle2may have occurred before application rendering finished.- Wait for a page-specific selector, scroll to activate lazy loading, and wait for the page’s image-ready signal.
- Verify that the browser process can reach the image host and that required fonts or resources are not blocked.
Navigation never completes
- Long-lived connections can prevent a network-idle condition.
- Use
domcontentloadedand then wait for the exact selector or state your application defines as ready. - Keep a job timeout around navigation so a broken page cannot hold a worker forever.
An element screenshot throws a detached-node error
The framework replaced the node after you selected it. Wait for the re-render to finish, select the element again, and capture the fresh handle.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →BiDi rejects an option
Consult the supported-parameter list in the BiDi documentation. Switch to an option supported by that protocol or use the normal Puppeteer protocol mode when your deployment permits it.
Best Value
- Used Book in Good Condition
Performance, reliability, and concurrency
Full-page images can be substantially taller than the viewport, so memory and encoding time grow with document dimensions and image format. Keep pages bounded when infinite scrolling is involved, avoid needlessly large device scale factors, and choose JPEG or WebP only when their quality characteristics fit the use case. PNG remains the documented default.
Close every browser you launch. For a service that handles many URLs, reuse a browser process carefully while isolating pages or browser contexts, and enforce navigation and capture timeouts at the job level. Puppeteer coordinates some operations automatically: within a BrowserContext, newPage(), Browser.newPage(), and Page.close() wait for screenshot completion. Page.bringToFront() does not wait for an existing screenshot, so do not use it as a completion signal when coordinating concurrent work.
Or skip the browser setup
ScreenshotNeo provides a single-request website screenshot API when you do not want to operate Chromium yourself. Before capture it accepts the cookie or consent banner as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
Use the API key and target URL in one GET request (the ScreenshotNeo documentation lists all options):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request from 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)
Or from Node.js without launching Puppeteer:
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 data = Buffer.from(await res.arrayBuffer());
Every ScreenshotNeo feature is included on every plan. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots, followed by Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000, and Business at $249 for 1,000,000. Yearly billing provides two months free. Create a free ScreenshotNeo account to get the 1,000 monthly screenshots without a card.
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.

