Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsTo capture a webpage at its document height with headless Chrome, use Puppeteer and set fullPage: true:
await page.screenshot({ path: 'page.png', fullPage: true });
Puppeteer documents fullPage as “takes a screenshot of the full page”; its default is false. Chrome’s standalone --screenshot flag uses the window dimensions you provide, so a tall window is not the same as automatically measuring the document.
What “auto-height” means in headless Chrome
A viewport screenshot captures only the visible rectangle. An auto-height or full-document screenshot captures the page from the top through the current document height, including content below the fold. In the Puppeteer API, that behavior is requested explicitly with fullPage: true.
There are two separate concerns:
- Geometry: how much of the page is captured. Use
fullPagefor the ordinary full-document case, orclipand viewport-related options for a specific region. - Readiness: whether the content you want has finished loading. A full-page flag does not guarantee that asynchronous requests, timers, lazy images or infinite-scroll content are complete.
Capture the full document with Puppeteer
Install and run a minimal script
Install Puppeteer in a Node.js project, then create a script such as capture.js:
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 →#1 Best Overall
npm install puppeteer
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com/', { waitUntil: 'networkidle2' });
await page.screenshot({
path: 'page.png',
fullPage: true
});
await browser.close();
})();
Run it with node capture.js. The result is a PNG containing the full page rather than only the initial viewport. Replace the URL and output path for your target.
Choose a viewport deliberately
Full-page mode determines vertical extent, but the viewport still determines responsive layout and the resulting width. Set it before navigation when desktop or mobile rendering matters:
await page.setViewport({
width: 1440,
height: 900,
deviceScaleFactor: 1
});
await page.goto('https://example.com/', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'desktop-full.png', fullPage: true });
A narrow viewport can trigger a mobile layout; a larger deviceScaleFactor produces a higher-density image and increases memory use.
Wait for the content your page actually needs
waitUntil: 'networkidle2' is a useful starting point, not a universal definition of “ready.” Pages may continue rendering after navigation because of timers, client-side requests or user interaction. Wait for a known selector when possible:
await page.goto('https://example.com/dashboard', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-report-ready]', { timeout: 30000 });
await page.screenshot({ path: 'report.png', fullPage: true });
If the application has a documented delay rather than a readiness element, use an explicit delay and explain why it is needed. Keep the timeout finite so a broken page does not hold a worker forever.
Handling lazy images, animations and long pages
Lazy-loaded images
Some sites request images only when an element approaches the viewport. A full-page capture does not establish that every lazy image has been requested. If the page uses ordinary scroll-triggered loading, you can scroll through it before the screenshot:
await page.evaluate(async () => {
await new Promise(resolve => {
let y = 0;
const step = 500;
const timer = setInterval(() => {
window.scrollBy(0, step);
y += step;
if (y >= document.documentElement.scrollHeight) {
clearInterval(timer);
window.scrollTo(0, 0);
resolve();
}
}, 100);
});
});
await page.waitForTimeout(1000);
await page.screenshot({ path: 'lazy-loaded.png', fullPage: true });
This is site-specific: an infinite list may keep increasing in height, and a page may use an intersection observer with different thresholds. Set a maximum scroll duration or item count in production and verify the output.
Animations and sticky elements
Animated content can differ between runs, while sticky headers can appear at their pinned position as the page is stitched. If deterministic output matters, add page-specific CSS through page.addStyleTag to disable transitions and animations, and test whether fixed or sticky elements overlap content. There is no universal Puppeteer setting that resolves every sticky-header, animation or extremely tall-document case.
Recommended Free Tools
Specific regions instead of the whole page
Use clip when you need a rectangle, and review captureBeyondViewport for captures extending outside the viewport. These are separate from fullPage. In the Puppeteer 25.12.0 reference, fullPage defaults to false; captureBeyondViewport has a default that depends on whether a clip is supplied. For a normal document screenshot, explicitly setting fullPage: true is clearer than relying on those other options.
Use Chrome’s headless command line
For a simple one-off capture without browser scripting, Chrome supports --headless and --screenshot. You can choose the window dimensions:
chrome --headless --screenshot --window-size=412,892 https://example.com/
Use the executable name installed on your system (for example, a platform-specific Chrome binary). The documented example demonstrates a fixed 412-by-892 window. The CLI documentation does not describe --window-size as automatically measuring the page’s full document height, so this command should be treated as a viewport-sized capture unless your installed Chrome version and workflow provide additional behavior.
Control waiting with CLI flags
--timeout sets a maximum wait before capture. It is a time limit, not proof that all asynchronous work has finished; capture can begin while loading continues. For pages driven by timers, --virtual-time-budget can fast-forward virtual time before capture:
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 minutechrome --headless --screenshot=timed.png
--window-size=1440,900
--timeout=10000
--virtual-time-budget=5000
https://example.com/
Use virtual time only when it matches the page’s behavior. It does not replace checking a page-specific readiness signal.
Puppeteer or the Chrome CLI?
| Consideration | Puppeteer | Chrome CLI |
|---|---|---|
| Full-document control | Explicit fullPage: true option |
Documents screenshot and window-size flags, not automatic document-height sizing |
| Automation | Script navigation, selectors, cookies, scrolling and post-load actions | Single command with limited orchestration |
| Dimensions | Set viewport width, height and device scale; full-page mode extends vertically | Set a fixed --window-size=WIDTH,HEIGHT |
| Readiness | Wait for selectors, navigation states or application-specific logic | Use timeout and, for timer-driven pages, virtual-time budget |
| Best fit | Repeatable jobs and dynamic sites | Quick local or CI captures where a fixed window is sufficient |
Troubleshoot a cropped or incomplete screenshot
Only the viewport appears
Confirm that the Puppeteer call contains fullPage: true. If you are using the CLI, remember that a tall --window-size is still a chosen window, not a documented auto-height measurement.
Images or charts are missing
Wait for a selector that signals completion, scroll to trigger lazy loading, or wait for the specific network request in your application. Increase a finite timeout only after identifying what is still loading.
The page is blank or partially rendered
Check the URL, navigation errors, authentication and JavaScript console output. A headless browser may reach a login page, bot challenge or an origin that rejects automated requests. Save an error screenshot and HTML during diagnosis, and do not assume a longer timeout will fix an access failure.
Free tools Windows power users keep installed
One-click scans. No signup required.
The screenshot changes between runs
Fonts, animations, ads, current time and network responses can change pixels. Pin the viewport, disable nonessential animation for the test, wait for a stable application marker and use consistent browser and font versions.
The process hangs or runs out of memory
Close the browser in a finally block, cap navigation and selector timeouts, and avoid unbounded scrolling on infinite pages. Extremely tall documents can consume substantial memory; capture a defined region or split the job when a complete document is not operationally necessary.
CLI flags behave differently on another machine
Keep the installed Chrome version in mind. Command-line details can evolve; the Chrome documentation’s compatibility notes, including historical changes to PDF header and footer flags, are a reminder to validate flags against the binary used in CI.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Reliability, performance and output choices
- Reuse a browser process: for batches, launch once and create or close pages per job instead of starting Chrome for every URL.
- Bound every wait: navigation, selectors, scrolling loops and virtual-time budgets should all have limits.
- Control network cost: block unnecessary analytics or large resources only when doing so cannot alter the layout you need to capture.
- Record context: store the URL, viewport, browser version, timestamp and readiness condition alongside the image.
- Choose a format: PNG preserves lossless detail; JPEG is smaller for photographic pages but introduces compression; WebP can offer a smaller modern image where your pipeline accepts it.
- Validate dimensions: check output width and height and inspect a few pages with sticky headers, long tables and lazy media before trusting a batch.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One request returns a PNG, JPEG, WebP or PDF. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and whether it was billed.
For a direct call, see the ScreenshotNeo API documentation:
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 also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or any viewport, retina scale, PDF paper size and page ranges, custom CSS and JavaScript, click-before-capture actions, hide selectors, selector/delay/network-idle waits, request and resource blocking, custom headers, cookies, user agents and Authorization, timezone and geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API and an OpenAPI specification. Its parameter names also match those used by other screenshot APIs, which helps when migrating.
An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Does fullPage change the browser viewport height?
No. It tells Puppeteer to capture the full document while retaining the viewport width and responsive layout you selected.
Can Chrome CLI guarantee that a page is fully loaded?
No. Its timeout is a maximum wait, and capture may proceed while loading continues. Use Puppeteer when you need application-specific readiness checks.
When should I use captureBeyondViewport?
Use it when your capture involves a clipped region or content outside the current viewport. It is not a replacement for the ordinary full-document fullPage: true setting.
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.

