ScreenshotNeo

BlogHow-to

How to Set Mobile Viewport Dimensions in Puppeteer

Set a mobile-sized Puppeteer viewport with CSS-pixel dimensions, choose the right touch and mobile flags, or emulate a named device profile.

By the ScreenshotNeo team4 October 20267 min read

Use page.setViewport() with a width and height measured in CSS pixels. Set it before navigating so the page’s responsive layout is evaluated at the intended size on its first load:

const page = await browser.newPage();

await page.setViewport({
  width: 390,
  height: 844,
  deviceScaleFactor: 1,
  isMobile: true,
  hasTouch: true,
});

await page.goto('https://example.com');

The 390 × 844 values are an example test size, not a Puppeteer standard or a universal phone size. Choose dimensions and mobile-related flags to match the behavior you need to test. Puppeteer recommends setting the viewport before navigation. Puppeteer: Page.setViewport()

1. Choose between a viewport size and a device profile

For a responsive breakpoint test, set the exact dimensions that matter to your test. Add isMobile or hasTouch only when the page behavior under test depends on mobile viewport handling or touch input.

For a named device configuration, use page.emulate() with a Puppeteer device profile. This applies the profile’s viewport metrics and user agent, making it a convenient choice when those settings should travel together. Puppeteer: Page.emulate()

import puppeteer from 'puppeteer';
import { KnownDevices } from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.emulate(KnownDevices['iPhone 17 Pro']);
  await page.goto('https://example.com');
  console.log('Applied viewport:', page.viewport());
} finally {
  await browser.close();
}

Use a profile name available in the Puppeteer version installed in your project. A device profile is a bundle of emulation settings; it does not make the browser identical to a physical phone in every respect.

2. Set dimensions and flags deliberately

width and height are CSS-pixel dimensions. The viewport options also let you configure device scale factor, mobile viewport behavior, touch support, and landscape orientation. Select only the settings relevant to the scenario. Puppeteer: Viewport interface

Option What it controls When to set it
width, height Viewport dimensions in CSS pixels. Always choose these for a manually sized viewport.
isMobile Whether the page’s meta viewport tag is taken into account. Set it when your test depends on mobile viewport handling. It is not required for every narrow responsive-layout test.
hasTouch Whether the viewport supports touch events. Set it when interactions or feature detection depend on touch support.
deviceScaleFactor Device scale factor for rendering. Set it when testing scale-dependent rendering. The example uses 1; choose a value appropriate to the scenario.
isLandscape Whether the viewport is landscape. Set it when orientation is part of the behavior being tested.

For example, to test a narrow layout without enabling touch emulation, keep the configuration focused:

await page.setViewport({
  width: 360,
  height: 800,
  deviceScaleFactor: 1,
});
await page.goto('https://example.com');

Use isMobile: true when you specifically need the meta viewport tag to be considered, and hasTouch: true when touch support matters. Viewport size alone does not reproduce every aspect of a physical device.

3. Apply the viewport before navigation

  1. Create the page.
  2. Set the viewport, or apply a device profile with page.emulate().
  3. Navigate to the target URL.
  4. Run assertions or capture the page after it has loaded to the state your test needs.

Changing viewport properties after navigation can produce different results from loading the page at that size. Puppeteer also notes that setting viewport properties can reload the page in some cases when changing isMobile or hasTouch. Set those values up front when possible. Puppeteer viewport timing and reload behavior

Each page can have its own viewport. page.viewport() reports the settings last applied to that page, or the default viewport from the browser connection options; it does not inspect the browser’s actual rendered viewport. Use it to check the configured values, not as proof that a page rendered exactly as expected.

4. Complete runnable example

This example launches Puppeteer, applies a mobile viewport before loading the page, takes a screenshot, and closes the browser even if navigation or capture fails. Install Puppeteer with npm install puppeteer, then save this as mobile-shot.mjs and run node mobile-shot.mjs.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();

  await page.setViewport({
    width: 390,
    height: 844,
    deviceScaleFactor: 1,
    isMobile: true,
    hasTouch: true,
  });

  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'mobile.png', fullPage: true });

  console.log('Configured viewport:', page.viewport());
} finally {
  await browser.close();
}

The dimensions are illustrative. Replace them with the CSS-pixel width and height required by your breakpoint or test case. networkidle2 is a navigation wait choice, not a guarantee that every application has finished rendering; applications with persistent network activity may need a more specific readiness condition.

5. Reset to the default viewport

To return a page to its default viewport settings, pass null:

await page.setViewport(null);

The resulting default comes from the browser connection options. If the page was created with a configured default viewport, that is the default to which it returns. Puppeteer: resetting the viewport

6. Troubleshooting

Symptom Likely cause Fix
The page still looks like its desktop layout. The viewport was set after navigation, or the tested CSS breakpoint does not match the chosen width. Set the viewport before page.goto() and verify the intended breakpoint uses the configured CSS-pixel width.
The page is narrow, but mobile viewport behavior is wrong. isMobile was omitted even though the test depends on the meta viewport tag. Set isMobile: true before navigation and check the page’s viewport metadata.
Touch interactions or touch-based feature checks do not behave as expected. The viewport does not advertise touch support. Set hasTouch: true before navigation when touch support is part of the test.
The page reloads after changing the viewport. Puppeteer may reload in some cases when mobile or touch settings change. Apply all viewport options before navigating, then wait for the page’s required ready state.
page.viewport() reports the configured size, but the screenshot seems different. The method reports the last settings applied, not the actual rendered viewport. The page may also have its own scaling or layout behavior. Check the screenshot and page behavior directly; verify the viewport configuration and relevant page metadata.
A device profile import or profile name is unavailable. The installed Puppeteer version may not expose that profile name or import shape. Check the API and device list for the installed version, or use page.setViewport() with explicit dimensions and flags.

7. Performance, reliability, and cost

Setting a viewport is a local browser configuration step. Its main reliability benefit is consistency: define the dimensions and emulation flags before navigation, and use the same configuration for comparable runs. For repeatable checks, record the viewport values alongside the test result and avoid changing mobile-related options mid-page.

There is no single viewport that represents every phone. Test the breakpoints and interaction modes your application supports, and use a named profile when you need its bundled metrics and user agent. A viewport configuration by itself does not establish physical-device performance or behavior.

Running Puppeteer means managing a browser process and its execution environment. If your goal is to obtain a screenshot rather than control a browser session, a screenshot API can avoid setting up that browser capture path. ScreenshotNeo provides a screenshot API and MCP server; its plan prices and billing rules are described below.

Or skip the browser setup

To capture a page with one request, call the ScreenshotNeo screenshot API. See the ScreenshotNeo API documentation for the available parameters.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Python

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)

Node.js

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}`);
const bytes = new Uint8Array(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 capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers identify the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan. Sign up free for 1,000 screenshots a month, with no card.

Frequently asked questions

Are viewport width and height measured in physical pixels?

No. Puppeteer defines them in CSS pixels. Device scale factor is a separate setting.

Do I need isMobile: true for every responsive test?

No. Use it when the behavior under test depends on the meta viewport tag being taken into account. A width-only breakpoint test may need only dimensions.

Does a device profile emulate a complete physical phone?

No. Puppeteer documents the profile as applying device metrics and a user agent. It does not imply that every hardware or operating-system behavior is reproduced.

Can different pages use different viewport dimensions?

Yes. Viewport settings belong to a page, so configure each page for the scenario it needs.