Browser Viewport: Definition, Defaults and Captures

The browser viewport is the visible area a page lays out in. See one page at three widths, the default sizes of each tool, and how to set the viewport.

By Simon Chiu · Updated

The browser viewport is the rectangle of a web page that the browser window shows at one time, measured in CSS pixels; its width decides which responsive layout the page uses.

In a screenshot, the viewport is the single setting with the biggest effect. Change it from 1280 to 390 pixels wide and you capture a different design: other breakpoints, other navigation, other images. This entry is part of the screenshot and rendering glossary.

A plain explanation

On a desktop, the viewport is the inside of the browser window, without the tabs and address bar. On a phone, it is the screen. A headless browser has no window, so you choose the viewport in code. Media queries such as @media (max-width: 600px) test the viewport width, so the page rearranges itself for whatever size you set.

One page at three viewport widths

We captured a test page with two breakpoints at three common widths. The page uses the viewport meta tag, so the widths apply as set:

The same page at three widths, shown at the same scale. At 390 pixels the cards stack in one column. At 768 pixels they form two columns. At 1280 pixels they sit in one row of three columns.
Captured with Puppeteer page.setViewport() at 390 x 844, 768 x 1024 and 1280 x 800 on 2026-10-15, the top 300 CSS pixels shown at 50% scale.

We also measured what each tool uses when you set nothing, on the same page:

Setting innerWidth x innerHeight clientWidth Columns
Puppeteer, no setViewport 800 x 600 800 2
Playwright, default newPage() 1280 x 720 1280 3
Puppeteer setViewport 390 x 844 390 x 844 390 1
Puppeteer setViewport 768 x 1024 768 x 1024 768 2
Puppeteer setViewport 1280 x 800 1280 x 800 1280 3

Tested on 2026-10-15 with Node 22.18, Puppeteer 24.43.1 (headless shell mode, Chrome 148) and Playwright 1.64.1 (Chromium 156) on macOS. The page was 1,400 pixels taller than the viewport, so it scrolled.

The defaults disagree: the same script ported from Puppeteer to Playwright captures a different layout unless you set the size. And clientWidth equalled innerWidth even on the scrolling page: headless Chrome reserved no space for a scrollbar here. A desktop browser with classic scrollbars, common on Windows, lays out a few pixels narrower, so a breakpoint right at the edge can differ between your browser and the capture.

How it works technically

Browsers keep two viewports. The layout viewport is the box that CSS positions things in; its width is what media queries and 100vw read. The visual viewport is the part on screen right now, smaller when the user pinch-zooms or a phone keyboard is open, and readable through window.visualViewport. In automation without zoom, both match.

On a phone, the layout viewport is not automatically the screen width. Without a viewport meta tag, mobile browsers lay pages out at 980 pixels and shrink them. Mobile emulation in automation tools copies that behaviour.

The viewport sets the CSS size; the device pixel ratio sets how many image pixels each CSS pixel becomes. A 390 x 844 viewport at ratio 3 gives a 1170 x 2532 image.

How to set it in Puppeteer, Playwright and RenderScreenshot

Puppeteer, per page, or for every page with defaultViewport at launch:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ defaultViewport: { width: 1280, height: 800 } });
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 390, height: 844, deviceScaleFactor: 3, isMobile: true });
  await page.goto('https://example.com');
  await page.screenshot({ path: 'phone.png' });
} finally {
  await browser.close();
}

Playwright, per context or per page:

import { chromium, devices } from 'playwright';

const browser = await chromium.launch();
try {
  const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });
  const page = await context.newPage();
  await page.goto('https://example.com');
  await page.screenshot({ path: 'desktop.png' });

  const phone = await browser.newContext({ ...devices['iPhone 13'] }); // viewport, ratio, mobile, user agent
  await (await phone.newPage()).goto('https://example.com');
} finally {
  await browser.close();
}

RenderScreenshot takes width and height from 1 to 7680 and 1 to 4320, defaulting to 1280 x 800, plus scale and mobile. A device such as iphone_14 sets them all. See viewport options and the devices reference.

curl --get https://api.renderscreenshot.com/v1/screenshot \
  -H "Authorization: Bearer $RS_API_KEY" \
  --data-urlencode 'url=https://example.com' \
  -d width=768 -d height=1024 \
  --output tablet.png
import { Client, TakeOptions } from 'renderscreenshot';

const client = new Client(process.env.RS_API_KEY);
const tablet = await client.take(TakeOptions.url('https://example.com').width(768).height(1024));

The RenderScreenshot snippets follow the API docs and were not run for this page.

Common mistakes

  • Relying on defaults. Puppeteer's 800-pixel width sits below many desktop breakpoints. Set the size explicitly in every capture.
  • Doubling the viewport for a sharper image. That changes the layout. Raise the device pixel ratio instead.
  • A phone width without mobile emulation. You get the narrow layout, but pages that check touch or the user agent still serve desktop behaviour. Use a device preset.
  • Expecting the height to limit a full-page capture. Full-page mode grows to the document height; the viewport height only affects elements sized in vh, such as hero sections.

The mobile screenshots guide shows when to use a device preset and when a custom size is better. To capture your own page at several widths, get a free API key.

Frequently asked questions

What is the default viewport size in Puppeteer and Playwright?
In our test, Puppeteer 24 pages started at 800 x 600 and Playwright 1.64 pages at 1280 x 720. RenderScreenshot defaults to 1280 x 800.
Is the viewport the same as the screenshot size?
For a viewport capture, the image is the viewport size multiplied by the device pixel ratio. A full-page capture keeps the viewport width but grows in height to fit the page.
What is the difference between the layout viewport and the visual viewport?
The layout viewport is the area CSS lays out in. The visual viewport is the part currently shown, which shrinks when a user pinch-zooms or a phone keyboard opens. In a screenshot without zoom they are the same.

Related in this topic

Try RenderScreenshot free

150 free credits every month, no credit card required.