Free tools Windows power users keep installed
One-click scans. No signup required.
In non-headless Puppeteer, maximize the native Chrome window and remove Puppeteer’s viewport constraint as two separate steps. Use browser.setWindowBounds(windowId, { windowState: 'maximized' }) for the platform window, and page.setViewport(null) so the page can follow the available window. These APIs control different rectangles: the first includes browser chrome and the second controls the web content area.
The complete example below targets Puppeteer 25.12.0 documentation as checked on September 29, 2026. Confirm method names and window support against the version installed in your project.
Use both controls for a visible, full-screen browser
A headful (non-headless) browser has an outer native window, browser user-interface elements, and an inner page viewport. Maximizing only one of these can leave apparent unused space. This script performs the two operations in the correct order:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: false });
const page = (await browser.pages())[0];
// Remove Puppeteer's default viewport restriction.
await page.setViewport(null);
// Maximize the native Chrome window on the current platform screen.
const windowId = await page.windowId();
await browser.setWindowBounds(windowId, { windowState: 'maximized' });
console.log('Maximized visible browser window');
// Keep the browser open while you inspect it, then close it when finished.
// await browser.close();
Puppeteer’s official window-management guide demonstrates obtaining a window ID with page.windowId() and passing it to browser.setWindowBounds(). The same guide demonstrates page.setViewport(null) to remove the default restriction. The combined sequence above is useful, but check compatibility because window behavior depends on the installed Puppeteer and Chrome versions.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC 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 & 11#1 Best Overall
What each size setting actually changes
Native window state
browser.setWindowBounds(windowId, { windowState: 'maximized' }) asks Chrome to maximize its top-level window using the operating system’s available screen. It does not promise a particular pixel width or height. Taskbars, docks, display scaling, remote-desktop policies, window managers, and multi-monitor placement can all affect the resulting bounds.
The call requires a valid ID for a window that supports window management. The official example creates a page configured as a window (browser.newPage({ type: 'window' })) before obtaining its ID. Follow the page and browser-context setup supported by your version rather than assuming every page is interchangeable.
Page viewport
A page viewport is the content rectangle used by layout and JavaScript APIs such as window.innerWidth. It is per page and is distinct from the outer browser window. The Page.setViewport() reference says that passing null resets the viewport to its default value; interpret the resulting behavior using your configured defaults and installed release.
Set the intended viewport before navigation when you need reproducible layout. Puppeteer warns that some viewport changes, especially changes to isMobile or hasTouch, can reload a page. A null viewport is appropriate when you want the visible page to follow the available headful window, not when you need a fixed screenshot size.
Content-area resizing
Page.resize() requests exact content dimensions:
await page.resize({ contentWidth: 1440, contentHeight: 900 });
This targets the page content area and excludes browser UI such as tabs, the address bar, and window borders. The method is marked experimental in the window-management documentation, so use it only when you accept possible API changes. It is not a general replacement for native maximization.
Rank #2
Headless screen configuration
The screen-configuration guide documents the synthetic --screen-info switch for headless mode only. Headful Chrome uses physical platform screens. Without --screen-info, the documented headless screen defaults to 800×600 unless --window-size is supplied. Do not treat that headless default as the size of a maximized visible window.
Build a reliable maximization helper
Putting the operations in a helper makes setup explicit and gives later code a place to measure the result:
import puppeteer from 'puppeteer';
async function launchMaximized() {
const browser = await puppeteer.launch({
headless: false,
// Add your normal executablePath, args, and userDataDir here if needed.
});
const pages = await browser.pages();
const page = pages[0] ?? await browser.newPage();
// Do this before navigation when layout depends on the viewport.
await page.setViewport(null);
const id = await page.windowId();
await browser.setWindowBounds(id, { windowState: 'maximized' });
return { browser, page, id };
}
const { browser, page } = await launchMaximized();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.evaluate(() => ({
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
devicePixelRatio: window.devicePixelRatio
})));
// await browser.close();
The reported innerWidth and innerHeight are the page’s usable dimensions, not the outer window dimensions. If subsequent actions depend on a resize, do not assume the change is synchronous.
Wait for an asynchronous resize before measuring
The window-management guide waits for the browser’s resize event before reading dimensions. You can use the same pattern when changing content dimensions or when your platform takes time to apply a state change:
const dimensions = await page.evaluate(() => new Promise(resolve => {
const read = () => resolve({
innerWidth: window.innerWidth,
innerHeight: window.innerHeight
});
// If the current size is already usable, a short timer avoids waiting forever.
const timer = setTimeout(read, 1000);
window.addEventListener('resize', () => {
clearTimeout(timer);
read();
}, { once: true });
}));
console.log(dimensions);
For a deterministic test, compare the measured dimensions with the minimum your workflow requires instead of assuming a 1920×1080 display. Operating-system chrome and display scaling mean a maximized content area is normally smaller than the physical screen resolution.
When to choose each approach
| Approach | Controls | Best use | Important caveat |
|---|---|---|---|
setWindowBounds(..., { windowState: 'maximized' }) |
Native browser window state | Use the available platform screen in visible Chrome | Needs a valid window ID and supported window context; final bounds are platform-dependent. |
page.setViewport(null) |
Per-page viewport restriction/default behavior | Let page content follow the visible-window setup | Null resets to the version’s default behavior; it is not an explicit pixel size. |
Page.resize({ contentWidth, contentHeight }) |
Page content area | Request exact inner dimensions | Experimental; excludes browser UI and may not produce a maximized native window. |
--screen-info or --window-size |
Synthetic headless screen configuration | Headless display emulation | --screen-info is headless-only; do not use it as proof of headful maximization. |
Common mistakes and fixes
The window is visible but still not maximized
Confirm that headless: false is set and that page.windowId() returns an ID for the page’s actual native window. Call setWindowBounds after the page/window exists. A page created in a context that does not expose a manageable window may not support this operation; use the window creation pattern documented for your release.
The outer window is large but the page remains narrow
A fixed Puppeteer viewport can continue constraining content after the native window is maximized. Call await page.setViewport(null) before navigation, or deliberately choose a fixed viewport if reproducible rendering is more important than using all available space.
Recommended Free Tools
Dimensions are smaller than the monitor’s resolution
This is expected. window.innerWidth excludes tabs, toolbars, borders, and operating-system panels. Display scaling and a dock or taskbar further reduce usable content. Read the actual dimensions in the page instead of hard-coding the monitor’s advertised resolution.
A resize-dependent action runs too early
Wait for the page’s resize event, then measure window.innerWidth and window.innerHeight. The inner size can change asynchronously even when the API call has returned.
--window-size=1920,1080 does not behave like maximize
A command-line size requests dimensions; it does not ask the operating system to maximize a native window. Window decorations, display scaling, and platform window rules can change the result. Use the documented window-state API for headful maximization.
Rank #4
Mobile emulation or touch settings unexpectedly reload
The viewport reference warns that changing isMobile or hasTouch can reload the page. Set those options before navigation and wait for the reload before interacting.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsThe API is missing or behaves differently
Check the installed Puppeteer version and the matching Page class API. The official window-management page displayed version 25.12.0 on September 29, 2026, but APIs and stability labels can change. Do not copy an experimental method into production without pinning and testing the dependency.
Headful maximization versus screenshot reproducibility
Maximizing a visible window is useful for manual inspection, interactive debugging, and workflows that must use the operator’s physical screen. It is less suitable for pixel-stable screenshots: two machines can have different monitors, scaling, browser chrome, and window-manager behavior.
For visual regression or automated capture, choose an explicit viewport before navigation and record the resulting dimensions. For interactive debugging, use the maximized-window approach and log innerWidth, innerHeight, and devicePixelRatio. Keep these goals separate rather than trying to make one setting serve both.
Or skip the browser setup
If your goal is a website screenshot rather than inspecting a local visible browser, ScreenshotNeo provides a one-request capture API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are free, and response headers identify the page verdict and billing status.
Use the API documentation at screenshotneo.com/docs/. Replace the example URL with the page you need:
Best Value
- Used Book in Good Condition
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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
await Bun.write('shot.webp', buffer);
ScreenshotNeo also offers PDF output, full-page captures with lazy images loaded, CSS-selector element shots, dark mode, device presets or custom viewports, retina scale, custom CSS and JavaScript, click and wait actions, blocked resources, headers and cookies, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture for up to 100 URLs per call, a usage API, an OpenAPI specification, and an MCP server with take_screenshot, get_page_info, and capture_pdf 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; every feature is available on every plan, and annual billing gives two months free. Create a free ScreenshotNeo account to try it.
Practical checklist
- Launch with
headless: false. - Get a page associated with a supported native window.
- Call
page.setViewport(null)if the page should follow the available window. - Get
page.windowId()and setwindowState: 'maximized'. - Wait for resize completion before measuring or interacting.
- Log actual inner dimensions and device pixel ratio.
- Use fixed viewport dimensions instead when screenshots must be reproducible across machines.
- Verify APIs against your installed Puppeteer version, especially
Page.resize, which is experimental.
Frequently Asked Questions
Can I maximize a headless Puppeteer browser?
Native window maximization applies to a visible platform window. Headless runs use synthetic screen and window configuration such as the documented --screen-info option instead.
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 →Does maximizing guarantee a 1920×1080 viewport?
No. The usable content area excludes browser and operating-system UI and varies with display scaling and platform configuration.
Should I use Page.resize for normal maximization?
Usually no. It requests content dimensions and is marked experimental; use the native window-state API for headful maximization.
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.

