ScreenshotNeo

BlogGuides

Playwright Screenshot Tests on Mobile Viewports: Device Emulation Guide

Configure Playwright for reliable mobile viewport screenshots with device presets, projects, visual baselines, CI fixes, and optional Android checks.

By the ScreenshotNeo team4 October 202611 min read

Use Playwright’s device presets when a test needs a coherent mobile browser profile, or set the CSS viewport directly when you need to test a particular responsive breakpoint. Run those settings as Playwright Test projects, create screenshot baselines with toHaveScreenshot(), and generate and compare baselines in a consistent environment. Emulation is useful for responsive layout checks; connected Android testing is a separate option when hardware behavior matters.

This guide covers mobile viewport configuration, project setup, screenshot assertions, CI stability, troubleshooting, and the point where a real Android device adds value. The main workflow requires no phone.

1. How do I take screenshots at mobile viewport sizes in Playwright?

Set a viewport and capture the page with Playwright. For a simple one-off screenshot, use the library API. For repeatable visual regression checks, use Playwright Test and toHaveScreenshot(), which creates a reference image on its first run and compares later captures with it.

Install Playwright Test and its browser binaries using the commands in the official installation guide. A standalone TypeScript script can set a viewport explicitly:

import { chromium } from '@playwright/test';

const browser = await chromium.launch();
const page = await browser.newPage({
  viewport: { width: 390, height: 844 },
  deviceScaleFactor: 1,
});

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

Save this as a TypeScript file and run it with your project’s TypeScript runner or adapt it to your existing Playwright setup. The viewport dimensions are CSS pixels. Choose dimensions that correspond to the layouts and breakpoints your application supports; there is no universally correct phone size.

For a test-managed baseline, add a test such as:

import { test, expect } from '@playwright/test';

test('mobile landing page matches its visual baseline', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('landing-mobile.png', {
    fullPage: true,
  });
});

The first run writes the reference screenshot. Review it and commit the intended baseline through your normal source-control workflow. Later runs compare captures against that image.

2. Viewport override or device preset?

A viewport override sets page dimensions. A device preset is a starting profile that can include viewport, screen size, user agent, device scale factor, touch support, and mobile behavior. Use a viewport override for a particular CSS breakpoint; use a preset when the test needs several mobile browser properties together.

Choice Use it when What it represents
Viewport only You are checking layout at a known CSS breakpoint. Page width and height in CSS pixels; other browser properties remain as configured.
Device preset You want a documented mobile profile as a starting point. A bundle of browser context settings such as viewport, user agent, scale factor, touch, and mobile behavior.
Preset plus override You need most preset behavior but a deliberate viewport or scale adjustment. The preset values you retain, with explicit overrides taking precedence.
Connected Android You need checks on Android Chrome or WebView running on a connected device. A hardware-backed Android browser or WebView session, configured separately from ordinary emulation.

Playwright’s device registry changes over time. Names such as Pixel 5 and iPhone 12 are examples in the documentation, not a complete or permanent catalog. Check the registry for the Playwright version installed in your project. A preset simulates browser properties; it does not guarantee identical rendering to a physical phone. See Playwright’s emulation guide.

Set the viewport directly

For a test that only needs responsive CSS at selected dimensions, configure the viewport in the test or project:

import { test, expect } from '@playwright/test';

test.use({ viewport: { width: 375, height: 812 } });

test('narrow layout fits the viewport', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('narrow-layout.png');
});

You can also change dimensions on an existing page with await page.setViewportSize({ width, height }). Set the viewport before capturing so the page has time to respond to the resize and settle.

Use a preset and override only what the test needs

Spread the preset first, then place overrides after it so your values win:

import { test, expect, devices } from '@playwright/test';

test.use({
  ...devices['Pixel 5'],
  viewport: { width: 390, height: 844 },
  deviceScaleFactor: 2,
});

test('mobile profile at the required viewport', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('mobile-profile.png');
});

Use deviceScaleFactor when pixel density is relevant to the output. CSS responsive behavior is generally governed by the CSS viewport, so choose that dimension deliberately. Keep scale factor consistent between baseline creation and comparison.

The isMobile setting affects whether the page’s meta viewport tag is taken into account and enables touch events. Presets may already specify mobile settings. Avoid adding conflicting values without a test-specific reason. Playwright documents these context options, along with screen dimensions, in its emulation guide.

3. Run desktop and mobile configurations with Playwright projects

Projects let one test suite run under multiple browser or device configurations. Keep the matrix intentional: cover supported browser engines, representative mobile profiles, and the breakpoints that carry product risk rather than assuming every device is needed for every test.

Here is a compact TypeScript configuration:

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  projects: [
    {
      name: 'desktop-chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'mobile-chrome',
      use: { ...devices['Pixel 5'] },
    },
    {
      name: 'mobile-safari',
      use: { ...devices['iPhone 12'] },
    },
  ],
});

These device names follow Playwright’s documented examples; confirm they exist in your installed version. Projects can also target different browser engines. Refer to the projects guide and browser documentation for configuration and browser support details.

Run all configured projects with:

npx playwright test

Select one project by its configured name:

npx playwright test --project=mobile-chrome

For narrower coverage, add projects that reflect actual support requirements—for example, another viewport at a breakpoint where navigation changes. Browser engine, viewport, mobile behavior, pixel density, runtime environment, and need for hardware validation are useful axes for deciding what belongs in the matrix.

4. Create, review, and update visual baselines

toHaveScreenshot() captures and compares an image. On the first run, Playwright creates the expected screenshot. On later runs it compares the new output with that reference. The assertion retries capture until two consecutive screenshots match and stores the last one, which helps avoid capturing a page while it is still changing. Read the visual comparisons guide for baseline and assertion details.

  1. Run the test in the environment that will own the baseline.
  2. Inspect the newly created screenshot for correctness, including content below the fold if using fullPage.
  3. Commit the reference image with the test code so reviewers can inspect changes.
  4. When an intentional UI change alters the image, regenerate with npx playwright test --update-snapshots.
  5. Review the resulting image diffs before accepting the new baseline.

Do not update snapshots reflexively to clear a failure. First determine whether the product changed intentionally, the page capture is unstable, or the environment drifted.

Control known visual noise carefully

Screenshot assertions support comparison controls such as maxDiffPixels and a custom stylesheet through stylePath. A stylesheet can hide known volatile elements, such as a timestamp, when that content is unrelated to the visual behavior under test. Keep such rules narrow: a broad mask can conceal a real layout regression.

import { test, expect } from '@playwright/test';

test('stable page screenshot', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('stable-page.png', {
    fullPage: true,
    maxDiffPixels: 100,
    stylePath: './tests/screenshot.css',
  });
});

Create tests/screenshot.css only for specific, understood sources of capture noise. The threshold is an assertion tolerance, not a substitute for examining a suspicious diff.

5. Configure other conditions only when they matter

Viewport size is one part of browser context. Playwright also documents emulation options for locale, timezone, geolocation, permissions, and color scheme. Configure these when the page’s appearance or behavior depends on them; avoid adding irrelevant state that makes a test harder to understand.

import { test, expect, devices } from '@playwright/test';

test.use({
  ...devices['Pixel 5'],
  locale: 'en-US',
  timezoneId: 'America/Los_Angeles',
  colorScheme: 'dark',
  geolocation: { latitude: 37.7749, longitude: -122.4194 },
  permissions: ['geolocation'],
});

test('mobile page in dark mode at a location', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveScreenshot('mobile-dark-local.png');
});

Use valid values for your application and the documented Playwright option types. If a page requests location, configure the permission along with the location data. See the emulation reference for supported settings.

6. Why do Playwright screenshot tests fail on CI?

Visual screenshots can vary with host operating system, browser version, browser settings, hardware, power source, and headless mode. Playwright recommends generating and comparing references in the same environment. A baseline created on a developer laptop may differ from CI even when the page code has not changed.

  • Different browser build: use a consistent Playwright version and its corresponding browser installation in baseline and comparison runs.
  • Different operating system or rendering environment: generate and compare snapshots on the same OS and use a consistent CI image for visual tests.
  • Different viewport or scale factor: check project configuration, test-level overrides, and whether preset values are being replaced in the intended order.
  • Unsettled page content: wait for the specific content needed by the test, or use the assertion’s retry behavior; avoid arbitrary delays unless the page requires a known delay.
  • Volatile page regions: scope a stylesheet or other supported comparison control to the known changing element and keep the rest of the screenshot meaningful.
  • Baseline changed without review: inspect diffs and update only for an intentional change or an understood correction to the reference environment.

Emulation does not reproduce every physical device characteristic or operating-system UI. Use it for responsive layout and mobile-browser conditions represented by the selected profile. If browser builds, hardware, or native-app WebView behavior matter, add targeted checks on representative real devices.

7. When does connected Android testing add value?

Playwright’s Android automation can discover connected Android devices, launch Chrome, work with WebView, and capture screenshots. This is a separate workflow from a mobile-emulation project. Use it when the test question depends on Android Chrome or WebView behavior on hardware. A phone is not required for the viewport and device-emulation workflow in this guide.

Connected-device automation has additional setup requirements and limitations; check the Android API documentation before adding it to a test system. Keep the test goal specific: hardware validation should cover a risk that an emulated context cannot answer.

8. Troubleshooting checklist

Symptom Likely cause Fix
Mobile layout looks like desktop The context uses only a narrow viewport and not the relevant mobile behavior, or the page’s viewport configuration is absent. Use an appropriate device preset or configure the needed mobile context fields. Check the page’s viewport metadata and ensure the test uses the intended project.
Preset key is undefined The selected device name is not present in the installed Playwright registry. Check the current device descriptors for your installed version and choose a supported profile.
Screenshot dimensions differ from expectation Confusion between CSS viewport dimensions, full-page output, screen size, and device scale factor. Set the CSS viewport deliberately, inspect whether fullPage is enabled, and keep scale factor consistent.
First run reports or creates a missing baseline No reference screenshot exists yet for that test and project. Inspect the generated expected image, then commit it as the reviewed baseline.
CI reports image diffs that are absent locally OS, browser build, headless mode, settings, hardware, or other rendering conditions differ. Run baseline generation and comparison in the same stable environment, as advised by the visual comparison guide.
Every run has a slightly different screenshot Content or layout is still changing, or a volatile element is visible. Wait for the relevant state, stabilize the input, or narrowly hide the known volatile element with a screenshot stylesheet.
Snapshot update clears a failure but hides a bug The reference was replaced without investigating the change. Review the image diff first; update only after confirming an intentional product change or correcting the baseline environment.
Emulated test passes but Android device differs The emulated profile does not reproduce all hardware, OS, browser, or WebView behavior. Add a targeted connected Android check for the behavior that requires a physical browser or WebView.

9. Performance, reliability, and cost

Each additional project increases the number of test executions and screenshot comparisons. Keep the matrix tied to supported browsers, responsive breakpoints, and areas of risk. Use focused tests for routine pull requests and broader project coverage where your CI schedule permits.

For reliability, hold the Playwright version, browser binaries, operating system, viewport, scale factor, and screenshot settings steady between baseline generation and comparison. Stable inputs and narrowly scoped noise controls make diffs easier to interpret. Connected Android checks add a distinct hardware validation path and its associated device setup; use them where they answer a real compatibility question.

The dossier documents no runtime benchmark or universal device count, so choose the suite size based on your project’s execution budget and support commitments. Playwright itself is the browser test workflow; the screenshot API alternative below has its own published usage plans.

Or skip the browser setup

If the goal is to capture a page image rather than maintain a browser-based visual regression test, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF; this example saves a WebP capture:

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

See the ScreenshotNeo API docs for request parameters and configuration. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status. An MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000.

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

FAQ

How do I emulate an iPhone in Playwright?

Use an iPhone device descriptor from the installed devices registry in a project or browser context, then verify that the descriptor is available in your Playwright version. A preset simulates browser settings; it is not proof of identical physical-device rendering.

Should every mobile test use a device preset?

No. Use a direct viewport when the test is about a CSS breakpoint. Choose a preset when the test needs a bundle of mobile browser properties such as touch and mobile viewport behavior.

Can a passing emulated screenshot replace Android testing?

Only when emulation covers the risk you care about. Add connected Android Chrome or WebView checks when hardware-backed browser behavior is part of the requirement.

When should I update Playwright snapshots?

After confirming the visual change is intentional or correcting a known baseline-environment mismatch. Inspect the diff before accepting regenerated references.