Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The 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.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use the API documentation at screenshotneo.com/docs/. Replace the example URL with the page you need:

Best Value
The SQL Programming Language: .
  • 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 set windowState: '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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.