Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsIn Puppeteer, a Page represents a tab-like page, a viewport is the area where that page renders content, and a native browser window has its own position, outer dimensions, and state. Use Browser.setWindowBounds() to move or maximize a native window, Page.resize() to request a content-area size, and Page.setViewport() to control viewport dimensions or emulate a device. These controls solve different problems, so choose based on what you need to measure or change.
The examples below follow the Puppeteer API documented in versions 25.9.0 and 25.12.0. Check the version installed in your project because APIs can evolve.
As an Amazon Associate I earn from qualifying purchases.
Choose the Puppeteer API for the change you need
| Goal | API | What it controls | Important detail |
|---|---|---|---|
| Move, maximize, restore, or inspect a native browser window | Browser.getWindowBounds() and Browser.setWindowBounds() |
Window position, bounds, and state | Use the window ID for the relevant window; create a window-type page where needed. Puppeteer Window management. |
| Request a specific content-area size | Page.resize() |
Browser window size derived from desired content dimensions | A default viewport may constrain the window; clear it if appropriate and wait for the resize event. Puppeteer Window management. |
| Set a responsive layout or device-like viewport | Page.setViewport() |
The page viewport | It does not set native window bounds. Changing isMobile or hasTouch can reload the page. Page.setViewport(). |
| Keep sessions separate | Browser.createBrowserContext() and its pages |
Page grouping and isolated storage | Popups belong to their opener’s context; closing a context closes its pages. BrowserContext. |
Launch a browser and open pages
A browser can have multiple Page instances. Open a browser and create a page with newPage() for a straightforward tab-like page:
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 & 11const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
try {
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
} finally {
await browser.close();
}
})();
Set headless: false when you need to see or interact with a visible browser window. For a task that only needs page rendering and does not need native window interaction, use the launch behavior appropriate to your installed Puppeteer version and environment.
#1 Best Overall
How do I resize a Puppeteer browser window?
Set native window position, bounds, or state
Puppeteer’s window-management guide directs users to Browser.getWindowBounds() and Browser.setWindowBounds() for native window position and state. Create a page of type window, get its window ID, then inspect or change that window:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
try {
const page = await browser.newPage({ type: 'window' });
const windowId = await page.windowId();
const bounds = await browser.getWindowBounds(windowId);
console.log('Current window bounds:', bounds);
await browser.setWindowBounds(windowId, { windowState: 'maximized' });
// Do work in the maximized window.
await browser.setWindowBounds(windowId, { windowState: 'normal' });
} finally {
await browser.close();
}
})();
To set ordinary bounds, pass the desired position and dimensions in the bounds object supported by your installed Puppeteer version. The window ID identifies which window to control; do not assume the page viewport dimensions are equivalent to its outer window dimensions.
Request a specific content area
Use Page.resize({contentWidth, contentHeight}) when the required measurement is the page’s content area rather than a device-emulated viewport. A default viewport can constrain the window, so clear it first if that is interfering. The resize is asynchronous; wait for the resize event before reading dimensions.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
try {
const page = await browser.newPage({ type: 'window' });
await page.setViewport(null);
await page.evaluate(() => new Promise(resolve => {
window.addEventListener('resize', resolve, { once: true });
}));
await page.resize({ contentWidth: 600, contentHeight: 400 });
const dimensions = await page.evaluate(() => ({
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
outerWidth: window.outerWidth,
outerHeight: window.outerHeight
}));
console.log(dimensions);
} finally {
await browser.close();
}
})();
For a resize listener that is guaranteed to be installed before the resize request, register it in Node before calling resize():
Rank #2
const resized = page.evaluate(() => new Promise(resolve => {
window.addEventListener('resize', resolve, { once: true });
}));
await page.resize({ contentWidth: 600, contentHeight: 400 });
await resized;
Browser chrome adds to the outer dimensions, so requesting a 600×400 content area does not mean a 600×400 outer window. Puppeteer’s guide shows an example environment where an inner size of 600×400 corresponded to an outer size of 600×487; that is an example, not a universal chrome-size constant. Window management guide.
When should I use Page.setViewport()?
Use Page.setViewport() when the task is about the page’s rendering area, responsive breakpoints, or device emulation—not moving or resizing the native browser window. Set it before navigation when possible so the page initially loads at the intended viewport.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto('https://example.com');
} finally {
await browser.close();
}
})();
Viewport settings can be configured separately for each page. Be aware that changing isMobile or hasTouch can reload the page. See the Page.setViewport API reference for the current option details.
How do I manage multiple tabs, windows, and sessions?
List pages currently open in a browser
Use browser.pages() to inventory open pages across browser contexts:
Rank #3
const pages = await browser.pages();
for (const [index, page] of pages.entries()) {
console.log(index, page.url());
}
Browser.pages() returns open pages but omits non-visible pages such as background pages by default. Its optional includeAll flag can include them. Use the Browser.pages() API reference for the method signature in your installed version.
Separate browser sessions with contexts
Create a browser context when pages need independent cookies and local storage. Pages opened in a context share that context’s session storage environment, while contexts isolate browser storage from one another. A popup opened by a page remains in the opener’s context.
const contextA = await browser.createBrowserContext();
const contextB = await browser.createBrowserContext();
const pageA = await contextA.newPage();
const pageB = await contextB.newPage();
// Closing a context also closes the pages created in it.
await contextA.close();
await contextB.close();
For details on browser launch, connection, and lifecycle, see Browser management.
Recommended Free Tools
Close the browser or disconnect?
Choose cleanup based on who owns the browser process:
Rank #4
- Call
browser.close()to close a browser launched for the task, including its pages. - Call
browser.disconnect()when Puppeteer is attached to a browser managed by another controller and should only detach. The browser and its pages keep running.
Put cleanup in a finally block so it runs if navigation or page operations fail.
Troubleshooting window and page sizing
- The viewport changed, but the visible window did not:
setViewport()controls the page rendering area, not native window bounds. Use the window-bounds API for window position or state, orresize()for a requested content area. - The content area is smaller than the outer dimensions: Browser chrome occupies part of the native window. Measure
innerWidth/innerHeightseparately fromouterWidth/outerHeight. - The measured dimensions appear stale after resize: The resize is asynchronous. Wait for a window
resizeevent after initiating the resize before reading the dimensions. - The requested content size is constrained: A configured viewport may be limiting the window. Try
await page.setViewport(null)beforepage.resize()when appropriate. - Changing device options reloads the page: This can occur when
isMobileorhasTouchchanges. Set the viewport and emulation options before navigation if possible. - A page is missing from
browser.pages(): Background pages are excluded by default. Use the optionalincludeAllbehavior when those pages matter. - Closing a context also closes tabs: That is expected; closing a browser context closes the pages it owns. Create a separate context for sessions that must remain independent.
- The browser disappears after cleanup:
browser.close()closes the process. Usebrowser.disconnect()if another controller owns it and it must keep running.
Or skip the browser setup
For a screenshot without writing and maintaining Puppeteer window setup, ScreenshotNeo accepts one GET request with a URL and returns a clean PNG, JPEG, WebP, or PDF. Its API also supports controls such as full-page capture, CSS-selector element capture, viewport and device presets, custom CSS or JavaScript, waiting for a selector or network idle, and PDF settings. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies page verdict and billing status with X-Page-Verdict and X-Billed headers. 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.
Free tools Windows power users keep installed
One-click scans. No signup required.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
Frequently Asked Questions
Can Puppeteer control the position of a browser window?
Yes. Use a window-type page to obtain its window ID, then call browser.setWindowBounds() with the desired position or state.
Does browser.pages() return tabs from every browser context?
It returns open pages across contexts, but omits non-visible pages such as background pages by default; the optional includeAll behavior can include those.
Does browser.disconnect() stop the browser?
No. It detaches Puppeteer while leaving the browser and its pages running.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →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.




