ScreenshotNeo

BlogHow-to

How to Change the Screenshot Scale in Playwright

Choose CSS-pixel or device-pixel output in Playwright, understand how it differs from deviceScaleFactor, and configure screenshots and visual tests.

By the ScreenshotNeo team4 October 20267 min read

To change the output scale of a Playwright page screenshot, pass scale: 'css' or scale: 'device' to page.screenshot(). Use 'css' for one output pixel per CSS pixel; use 'device' for one output pixel per device pixel. A regular page.screenshot() defaults to 'device'. Playwright Test’s toHaveScreenshot() also accepts both values, but defaults to 'css'. The option is a string choice, not an arbitrary numeric multiplier. Page API · PageAssertions API

1. Capture a screenshot with the scale you want

This complete Node.js example opens a page and saves a CSS-pixel screenshot. Change the value to 'device' if you want output at the emulated device pixel ratio.

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({
      viewport: { width: 1440, height: 900 },
    });

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

Install Playwright in a project with npm install playwright and install its browser binaries with npx playwright install chromium. The screenshot option itself is the same with Firefox or WebKit. fullPage: true controls how much of the page is captured; it does not change scale.

Choose CSS pixels or device pixels

Setting Meaning Useful when Default
scale: 'css' One output pixel per CSS pixel You want dimensions aligned with CSS layout pixels and typically smaller image dimensions on a high-DPI context page.screenshot(): no
scale: 'device' One output pixel per device pixel You want to preserve the emulated device pixel density in the output page.screenshot(): yes

For a viewport of 1440 × 900 CSS pixels with a device scale factor of 2, the device-pixel output can be 2880 × 1800, while CSS-pixel output corresponds to 1440 × 900. This follows from the documented pixel mapping; exact image dimensions also depend on the capture extent and clipping. At high device scale factors, device output can be twice as large or larger in each dimension. The resulting pixel count, and often the file size and processing cost, can therefore be much higher.

2. Keep screenshot scale separate from deviceScaleFactor

scale chooses how rendered CSS pixels map into the screenshot file. deviceScaleFactor sets the browser context’s emulated device pixel ratio (DPR). The context option defaults to 1. They are related but distinct: changing screenshot scale does not change the page’s CSS layout or its DPR. Set the context’s DPR when you want the page to behave as if it were on a denser or lower-density device; set screenshot scale to choose the output mapping. BrowserType API

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  try {
    const context = await browser.newContext({
      viewport: { width: 1280, height: 800 },
      deviceScaleFactor: 2,
    });
    const page = await context.newPage();
    await page.goto('https://example.com');

    // Output one pixel per CSS pixel, even though the emulated DPR is 2.
    await page.screenshot({ path: 'css-pixels.png', scale: 'css' });

    // Output one pixel per emulated device pixel.
    await page.screenshot({ path: 'device-pixels.png', scale: 'device' });
  } finally {
    await browser.close();
  }
})();

Set deviceScaleFactor on the browser context before creating or using the page. If you need a mobile preset, Playwright’s device descriptors combine device-related context settings; the screenshot’s scale remains its own option. Use the context options reference for the current available settings.

3. Set scale in a Playwright Test screenshot assertion

In a visual test, pass the option to expect(page).toHaveScreenshot(). Its documented default is 'css', unlike the 'device' default of page.screenshot(). State the choice explicitly when saved screenshots and test baselines need the same pixel mapping.

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

test('page visual snapshot uses CSS-pixel scale', async ({ page }) => {
  await page.setViewportSize({ width: 1280, height: 800 });
  await page.goto('https://example.com');

  await expect(page).toHaveScreenshot('homepage.png', {
    scale: 'css',
    fullPage: true,
  });
});

For the device-pixel version, use scale: 'device'. If you have already configured shared screenshot assertion options in playwright.config.ts, the expect.toHaveScreenshot.scale setting can provide a project-wide default; a per-assertion option makes the intent visible at the call site. Check the TestConfig API for the current configuration shape.

4. Select scale alongside the other screenshot options

Scale only answers how pixels are represented in the output. Choose other options independently for the capture you need:

Option What it controls Important distinction
fullPage: true Captures the full scrollable page rather than the viewport Changes capture extent, not pixel scale
clip: { x, y, width, height } Captures a specified rectangle Coordinates and dimensions are in page CSS pixels; output mapping still follows scale
type: 'png' | 'jpeg' Selects the image encoding Encoding is independent of scale; JPEG quality applies only where supported
omitBackground: true Allows a transparent background for supported output Not applicable to JPEG
quality Controls lossy image quality when using JPEG It does not reduce pixel dimensions

For element screenshots, use locator.screenshot({ scale: 'css' }) or the corresponding supported element screenshot method. The same CSS-versus-device distinction applies. A clipped or element capture may have dimensions different from the viewport because the captured region is different.

5. Troubleshoot unexpected screenshot dimensions

The output image is twice as wide and tall as expected

Cause: page.screenshot() defaults to 'device', and the context may have a DPR of 2. Fix: explicitly set scale: 'css', or lower the context’s deviceScaleFactor if the emulated device density itself should change.

The test snapshot differs from a saved screenshot

Cause: The standalone screenshot defaults to device scale, while toHaveScreenshot() defaults to CSS scale. Fix: pass the same explicit scale to both APIs and use the same viewport, browser, and context settings.

Passing a number causes a type or option error

Cause: Screenshot scale accepts 'css' or 'device', not 2 or another numeric multiplier. Fix: use one of the two strings. To emulate a different DPR, configure numeric deviceScaleFactor on the browser context.

The page looks different after changing scale

Cause: The change may actually be to deviceScaleFactor, viewport, or a mobile device descriptor. DPR-sensitive assets and page behavior can differ when emulation changes. Fix: keep the context and viewport fixed while comparing 'css' and 'device'; change DPR only when that is the behavior being tested.

The screenshot has more or fewer pixels than the viewport

Cause: fullPage, clip, or an element capture changes the captured area. Device scale then maps that area to output pixels. Fix: compare both the requested capture region and the scale setting.

Visual tests are flaky across machines

Cause: Rendering can vary with host operating system, browser version, settings, hardware, power source, and headless mode. Fix: generate and compare visual baselines in a consistent environment, with pinned browser dependencies and the same context, viewport, and scale. Playwright’s visual comparison guide

6. Performance, reliability, and cost considerations

  • Image size: CSS scale can produce fewer pixels on a high-DPI context, reducing output dimensions and usually storage or transfer needs. Device scale preserves more output pixels and may be appropriate where that density is required.
  • Capture time and memory: Larger images require more pixel processing and memory in downstream encoding, storage, and comparison. Full-page captures can compound this by increasing the captured area. Avoid capturing a full page at device scale unless the additional detail is useful.
  • Visual stability: Scale does not make a page render deterministically. Keep browser and host environment consistent, wait for the needed page state, and account for animated or dynamic content when comparing snapshots.
  • Billing: Self-hosted Playwright has no per-screenshot API charge, but browser compute, CI minutes, storage, and bandwidth have their own costs. An external screenshot service has its own pricing and billing rules; verify those before moving a workload.

7. Use ScreenshotNeo when you do not want to run the browser

Playwright is the right choice when the browser session, test context, or custom automation is part of the job. For a URL-to-image request without browser setup, ScreenshotNeo provides a screenshot API and MCP server. A single GET request returns an image or PDF. See the ScreenshotNeo API documentation for its request options. Its service handles output settings through API parameters; it is not Playwright’s scale option.

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,
)
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}`);
await Bun.write('shot.webp', res);

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

8. Frequently asked questions

Can I set screenshot scale to 1.5?

No. The documented Page screenshot setting is the string 'css' or 'device'. Set context DPR with deviceScaleFactor if you need different device emulation.

Does fullPage make a screenshot higher resolution?

No. It captures more of the page vertically. Scale determines the CSS-to-output-pixel mapping.

Which scale should I use for visual regression tests?

Pick the mapping that matches your baseline requirements, set it explicitly, and keep the rendering environment consistent. Playwright Test defaults to CSS scale for screenshot assertions.

When was the option added?

The Playwright release notes identify the screenshot scale option as introduced in v1.21. Consult the current API reference for current behavior: Playwright release notes.