ScreenshotNeo

BlogHow-to

How to Set the Viewport Size in Puppeteer

Set Puppeteer’s viewport with page.setViewport before navigation. Learn how to choose dimensions, emulate devices, resize browser windows, and troubleshoot common issues.

By the ScreenshotNeo team4 October 20266 min read

Use await page.setViewport({ width, height }) before navigating. Width and height are viewport dimensions in CSS pixels. For example:

await page.setViewport({ width: 640, height: 480 });
await page.goto('https://example.com');

Set the viewport on the Puppeteer Page, and await the call before continuing. Puppeteer recommends setting it before navigation because some sites do not expect a phone-sized viewport to change after the page loads. In some cases, changing isMobile or hasTouch can reload the page. See the official Page.setViewport() reference.

1. Set a page viewport

This complete example launches Chromium, creates a page, sets its viewport, navigates, and captures a screenshot. Install Puppeteer in your project with npm install puppeteer; the package includes a compatible browser installation.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();

    await page.setViewport({
      width: 1080,
      height: 1024,
      deviceScaleFactor: 1,
    });

    await page.goto('https://example.com', {
      waitUntil: 'networkidle2',
    });
    await page.screenshot({ path: 'page.png' });
  } finally {
    await browser.close();
  }
})();

The viewport belongs to a page, so separate pages in one browser can use separate viewport sizes. Puppeteer’s getting started guide also shows setting a viewport before navigation.

2. Choose dimensions and viewport options

Pass a viewport object to page.setViewport(). The basic choice is width and height. The official example also specifies deviceScaleFactor; use the installed Puppeteer version’s API reference and type definitions for the complete set of supported fields rather than assuming an example is exhaustive.

Setting What it controls When to use it
width Viewport width Match the CSS viewport your page should render at.
height Viewport height Set the visible viewport height for layout and capture.
deviceScaleFactor Device scale factor Specify a scale factor when the capture or emulation needs one. The official example uses 1.

These dimensions describe the page viewport, not necessarily the entire browser window or the final size of a full-page screenshot. Choose values that match the layout conditions you want to exercise. Avoid changing mobile-related settings after navigation unless you are prepared for a possible reload.

3. Configure a default viewport for pages

If you connect to a browser with Puppeteer’s connection options, defaultViewport sets a viewport for each page. For example:

const browser = await puppeteer.connect({
  browserWSEndpoint: process.env.PUPPETEER_WS_ENDPOINT,
  defaultViewport: { width: 800, height: 600 },
});

try {
  const page = await browser.newPage();
  await page.goto('https://example.com');
} finally {
  await browser.disconnect();
}

This is a connection-level default. Use page.setViewport() when you need to set or change the dimensions of a particular page. The official ConnectOptions reference documents defaultViewport.

4. Emulate a device when you need more than dimensions

For device testing, use page.emulate(device) with a profile from Puppeteer’s KnownDevices. Emulation sets device metrics and the user agent; Puppeteer documents it as a shortcut for setting the user agent and viewport. Do this before navigation.

const puppeteer = require('puppeteer');
const { KnownDevices } = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  try {
    const page = await browser.newPage();
    const iPhone = KnownDevices['iPhone 13'];

    await page.emulate(iPhone);
    await page.goto('https://example.com');
    await page.screenshot({ path: 'mobile.png' });
  } finally {
    await browser.close();
  }
})();

Use a device profile when matching its metrics and user agent is part of the test. Use setViewport() when you only need a specific viewport configuration. Check the Page.emulate() reference for the installed version’s supported device profiles and API details.

5. Resize browser-window content instead of the page viewport

A page viewport and browser-window content dimensions are different controls. If your goal is to resize the browser window’s content area, Puppeteer’s window-management guide demonstrates removing the default viewport and then using page.resize():

await page.setViewport(null);
await page.resize({ contentWidth: 600, contentHeight: 400 });

The inner window size changes asynchronously. Wait for the resize event before reading dimensions or relying on the new size. See the official Window management guide for its event-waiting workflow. Use setViewport() for viewport configuration and the window-management API when you need to change browser-window content sizing.

6. Reset the viewport

Pass null to restore the page’s default viewport:

await page.setViewport(null);

This is useful when a page should return to the browser’s default viewport behavior. It is also part of the documented window-management workflow before resizing browser-window content.

7. Common problems and fixes

Symptom Likely cause Fix
The page renders at the old size. The viewport call was not awaited, ran after navigation, or targeted a different page. Call and await page.setViewport() on the page you will use, before page.goto().
A mobile page reloads after changing settings. Changing isMobile or hasTouch can trigger a reload in some cases. Set the intended viewport or device emulation before navigation.
The screenshot’s dimensions do not match the viewport. A full-page screenshot can extend beyond the visible viewport, or the capture uses a different page. Check whether the capture is full-page, confirm which page was configured, and distinguish viewport dimensions from output image dimensions.
Resizing the viewport does not resize the browser window. setViewport() configures the page viewport, not browser-window content sizing. Follow the window-management guide: clear the default viewport with setViewport(null), then use page.resize() and wait for the resize event.
page.resize or a viewport field is unavailable. The project’s installed Puppeteer version may differ from the documentation version or may not expose the API/field being used. Check the API reference and type definitions for the installed version, and update or adapt the code to that version.

8. Performance, reliability, and cost considerations

  • Set once, early: configure the viewport before navigation so the page’s initial layout uses the intended dimensions and avoids a later mobile-related reload.
  • Keep page settings explicit: set a per-page viewport when pages in the same browser need different sizes; use defaultViewport when a shared connection default is appropriate.
  • Use the right kind of resize: viewport configuration, device emulation, and browser-window resizing affect different aspects of rendering. Choosing the matching API prevents confusing layout results.
  • Account for browser resources: each browser and page has runtime and memory costs in your environment. Reuse a browser for related captures where appropriate, and close or disconnect it when finished.
  • Validate version-sensitive behavior: Puppeteer APIs evolve. Check the docs matching your installed version, especially for less common viewport fields and device profiles.

9. Or skip the browser setup

If your goal is to get a screenshot rather than manage Chromium, ScreenshotNeo provides a website screenshot API and MCP server. Send one GET request with a URL to receive a PNG, JPEG, WebP, or PDF. 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
  • Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before capture; each step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Responses identify page verdict and billing status in 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 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan.

Sign up for ScreenshotNeo’s free 1,000 screenshots a month, with no card required.

10. FAQ

Does the viewport belong to the browser or the page?

It belongs to a Puppeteer page. Multiple pages in one browser can have their own viewport settings.

Should I use a device profile for a responsive layout check?

Use setViewport() when you want to test a chosen viewport size. Use page.emulate(device) when device metrics and a matching user agent are also needed.

Can I set a viewport for every page created through a connection?

Yes. The connection option defaultViewport applies a default viewport to each page.

Where can I find the complete list of viewport fields?

Consult the API reference and type definitions for the Puppeteer version installed in your project. The examples here do not claim to list every supported field.