ScreenshotNeo

BlogHow-to

How to Get or Set a Puppeteer Page Viewport

Use page.viewport() to read Puppeteer's configured viewport and await page.setViewport() to change it. Learn defaults, device emulation, and common fixes.

By the ScreenshotNeo team4 October 20265 min read

Use page.viewport() to read Puppeteer’s configured viewport, and await page.setViewport({ width, height }) to change it. Set the viewport before navigating when practical. page.viewport() reports Puppeteer’s configured settings; it does not independently measure the browser’s actual page viewport.

Read and set a viewport

This complete Node.js example opens a page, sets a 640 × 480 CSS-pixel viewport, navigates, then reads the configured viewport:

const puppeteer = require('puppeteer');

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

    await page.setViewport({
      width: 640,
      height: 480,
      deviceScaleFactor: 1,
    });

    await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

    const configuredViewport = page.viewport();
    console.log(configuredViewport);
  } finally {
    await browser.close();
  }
})().catch(error => {
  console.error(error);
  process.exitCode = 1;
});

page.setViewport() is asynchronous, so await it before relying on the new dimensions or continuing with navigation. A Page represents one tab; pages in the same browser can have different viewport settings.

Viewport options and defaults

Setting Meaning Guidance
width, height Viewport dimensions in CSS pixels. Set both to the dimensions your page or test requires.
deviceScaleFactor Device pixel ratio used for rendering. Use 1 for standard scale; use a larger value when you need higher-density rendering.
isMobile Enables mobile viewport behavior. Use device emulation when you also need a matching user agent.
hasTouch Enables touch support. Set it when testing touch-specific behavior.
isLandscape Sets landscape orientation where supported. Choose it for landscape device scenarios.

The documented default viewport is { width: 800, height: 600 }. ConnectOptions.defaultViewport configures the viewport for each page created from that browser connection. Passing null to setViewport() resets the page to its configured default.

const browser = await puppeteer.launch({
  headless: true,
  defaultViewport: { width: 1280, height: 800 },
});
const page = await browser.newPage();
console.log(page.viewport()); // configured default for this page

await page.setViewport({ width: 390, height: 844 });
await page.setViewport(null); // reset to configured default

When connecting to an existing browser, use the connection option defaultViewport for the pages managed by that connection. Check the options documented for the Puppeteer version installed in your project.

Choose between manual dimensions and device emulation

Use setViewport() when you need to control viewport metrics. Use page.emulate(device) when you need a known device profile, because emulation applies both device metrics and the user-agent settings.

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

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

    await page.emulate(device);
    await page.goto('https://example.com');
    console.log(page.viewport());
  } finally {
    await browser.close();
  }
})().catch(console.error);

Device definitions can change between Puppeteer versions. Confirm that the selected name exists in the KnownDevices export of your installed version. Call emulate() before navigation where possible.

Set the viewport before navigation

Prefer this order: create the page, set viewport or emulate a device, then navigate. Puppeteer warns that changing viewport settings after navigation can make a page behave unexpectedly. Changes to isMobile or hasTouch can trigger a reload.

  1. Create a page.
  2. Set its viewport or apply a device profile.
  3. Navigate to the target URL.
  4. Wait for the page condition your task needs, then inspect or capture it.

If you must resize after navigation, allow for layout changes and possible reloads. Wait for the relevant page state again before reading dimensions or taking a screenshot.

Viewport versus browser window size

A page viewport and the browser window’s content area are related, but managed separately. page.setViewport() sets page viewport metrics. If you need to change the browser window’s content dimensions, use Puppeteer’s window-management API such as page.resize(); the window-management guide clears the default viewport with page.setViewport(null) before resizing. Do not assume that setting the viewport alone resizes the outer browser window.

Common problems and fixes

Symptom Likely cause Fix
page.viewport() shows 800 × 600. The page is using Puppeteer’s documented default. Set a viewport explicitly, or configure defaultViewport when launching or connecting.
The layout does not match the intended mobile device. Only dimensions were changed; the user agent or touch behavior differs. Use page.emulate(device) for a known profile, or configure the needed mobile and touch settings deliberately.
The page reloads after resizing. A change to isMobile or hasTouch can cause a reload. Set those properties before navigation where possible, and wait for the page again after changing them.
KnownDevices['...'] is undefined. The device name is not in the installed Puppeteer version. Check that version’s available device definitions and select a supported name.
Changing the viewport does not resize the browser window as expected. Page viewport metrics and window content dimensions are separate controls. Use the window-management API for window resizing; clear the default viewport first when following Puppeteer’s documented resize flow.
The page’s measured dimensions differ from page.viewport(). The method reports the configured settings, not an independent measurement of the actual page viewport. Use browser-side measurements such as window.innerWidth and window.innerHeight if you need to inspect the rendered page.

Performance, reliability, and cost

Set the viewport once before navigation to avoid extra layout work, reloads, or waiting for a page to settle after resizing. Use a viewport that matches the test case instead of repeatedly changing it during one capture. Mobile emulation is the more complete choice when responsive behavior depends on user agent or touch support.

Viewport settings do not make navigation deterministic on their own. Pages may still depend on network timing, fonts, scripts, or lazy-loaded content. Wait for a suitable navigation condition and, when necessary, a specific selector or page state before capturing. Puppeteer itself is browser automation software; browser execution and hosting costs depend on where you run it.

Or skip the browser setup

If the goal is a website screenshot at a particular viewport, ScreenshotNeo provides a screenshot API and MCP server. Set the viewport with the width and height parameters; see the ScreenshotNeo API documentation for the request options.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com \
  -d width=640 \
  -d height=480 \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://example.com",
        "width": 640,
        "height": 480,
    },
    timeout=90,
)
r.raise_for_status()
with open("shot.webp", "wb") as f:
    f.write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com',
  width: '640',
  height: '480',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, and cache hits are never billed; response headers report the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does page.viewport() return the actual browser viewport?

No. It returns Puppeteer’s configured viewport settings. Use browser-side measurements if you need to inspect the page’s rendered dimensions.

What does page.setViewport(null) do?

It resets the page to the configured default viewport, which is 800 × 600 unless another default is provided.

Can each tab have a different viewport?

Yes. Set the viewport on each Page independently.

Should I use setViewport() or emulate() for responsive tests?

Use setViewport() for viewport dimensions and metrics. Use emulate() when you want a known device profile that also sets a user agent.

Official Puppeteer references