Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Playwright does not expose a print-style DPI field for screenshots. Output dimensions are controlled by the screenshot scale option and the browser context’s deviceScaleFactor (the emulated device pixel ratio, or DPR). Use scale: 'css' for one output pixel per CSS pixel, or scale: 'device' for one output pixel per device pixel. The default is different for page screenshots and screenshot assertions: page.screenshot() defaults to device, while expect(page).toHaveScreenshot() defaults to css.

What Playwright screenshot resolution actually means

A web page is laid out in CSS pixels. A browser context can then emulate a device pixel ratio with deviceScaleFactor. The screenshot scale setting determines how those two coordinate systems become image pixels:

Setting Pixel mapping Typical result
scale: 'css' One image pixel per CSS pixel Smaller, predictable files that match the viewport’s CSS dimensions
scale: 'device' One image pixel per emulated device pixel More pixels on high-DPI contexts and larger image dimensions

The context option deviceScaleFactor defaults to 1. A value of 2 emulates a 2× DPR, but it does not by itself guarantee that every screenshot is twice as wide: the final dimensions also depend on whether you capture the viewport, the full page, or an element.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why “DPI” is usually the wrong measurement

DPI describes physical print density. Playwright’s screenshot API documents CSS-to-device pixel mapping, not an independent print-DPI metadata setting. For reliable automation, specify the image’s pixel dimensions, CSS scale, device scale, viewport, and context DPR. If a downstream print workflow needs a particular physical size, convert that required size to pixels yourself and treat the PNG, JPEG, or WebP as a raster image; do not expect a Playwright option named dpi.

How output dimensions are calculated

Viewport screenshot

With a viewport of 1280 × 800 CSS pixels and deviceScaleFactor: 1, both scale modes normally produce a 1280 × 800 image. At deviceScaleFactor: 2, scale: 'css' remains 1280 × 800, while scale: 'device' produces approximately 2560 × 1600.

Full-page screenshot

fullPage: true expands the capture to the document’s scrollable height. Width follows the page’s CSS layout width; height follows the rendered document. Device scaling multiplies the resulting CSS dimensions, so a long page can create a very large bitmap and consume substantially more memory.

Element screenshot

For an element, the starting dimensions are that element’s rendered bounding box in CSS pixels. Borders, transforms, fractional coordinates, and browser rounding can make the final integer pixel dimensions differ by a pixel. Measure the image rather than assuming a fractional CSS size will survive unchanged.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set resolution deliberately in Playwright

JavaScript example: CSS-pixel output

import { chromium } from 'playwright';

const browser = await chromium.launch();
const context = await browser.newContext({
  viewport: { width: 1440, height: 900 },
  deviceScaleFactor: 2
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle' });

await page.screenshot({
  path: 'css-scale.png',
  scale: 'css'
});

await browser.close();

Although the context emulates 2× DPR, the screenshot requests one output pixel per CSS pixel. This is the useful choice when image dimensions must track the declared viewport.

JavaScript example: device-pixel output

import { chromium } from 'playwright';

const browser = await chromium.launch();
const context = await browser.newContext({
  viewport: { width: 1440, height: 900 },
  deviceScaleFactor: 2
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle' });

await page.screenshot({
  path: 'device-scale.png',
  scale: 'device'
});

await browser.close();

Here the target is device-pixel output, so the viewport portion is approximately 2880 × 1800 pixels. Confirm dimensions with an image inspector because page content, clipping, and rounding affect the exact result.

TypeScript configuration for repeatable captures

import { chromium, type Page } from 'playwright';

async function capture(page: Page, path: string, scale: 'css' | 'device') {
  await page.screenshot({
    path,
    fullPage: true,
    scale,
    animations: 'disabled'
  });
}

const browser = await chromium.launch();
const context = await browser.newContext({
  viewport: { width: 1280, height: 720 },
  deviceScaleFactor: 1
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await capture(page, 'baseline.png', 'css');
await browser.close();

Keep viewport, browser engine, Playwright version, context DPR, scale, fonts, and page state identical when producing visual-regression baselines. Changing any of these can change pixels even when the application code is unchanged.

Page screenshots versus screenshot assertions

Do not carry the default from one API into the other. The documented default for page.screenshot() is scale: 'device'. The documented default for expect(page).toHaveScreenshot() is scale: 'css'. Make the choice explicit in tests so an upgrade or a context change cannot silently alter baseline dimensions.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await expect(page).toHaveScreenshot('home.png', {
  fullPage: true,
  scale: 'css'
});

If an existing baseline was generated with device scaling, changing the assertion to CSS scaling will produce a different image size and invalidate the baseline. Regenerate baselines intentionally, not as an automatic response to a mismatch.

Choosing CSS or device scaling

  • Choose CSS scaling when files should remain small, dimensions should equal the CSS viewport, or visual tests need stable, easy-to-review artifacts.
  • Choose device scaling when you need pixels at the emulated DPR, are matching a high-density display capture, or require finer raster detail.
  • Lower the DPR for full-page captures that exceed memory or storage limits. A 2× width and 2× height means roughly four times as many pixels before compression.
  • Fix the scale in configuration rather than relying on defaults, especially when several teams or APIs produce the same baselines.

Neither mode makes text or vector artwork intrinsically sharper after the fact. Device scaling samples the rendered page at more pixels; it cannot restore detail that the browser did not render or that a low-resolution source image does not contain.

Common resolution problems and fixes

“My screenshot is twice as large”

Check deviceScaleFactor and the scale mode. A 2× context with scale: 'device' commonly doubles width and height relative to CSS dimensions. Set scale: 'css' or use deviceScaleFactor: 1 when CSS-sized output is required.

“The assertion image is smaller than page.screenshot()”

This is often the documented default difference: page screenshots use device scaling and assertions use CSS scaling. Pass an explicit scale value to both calls, then recreate baselines if the intended dimensions changed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“Changing DPR did nothing”

You may still be using scale: 'css', which intentionally keeps one image pixel per CSS pixel. DPR can also be overridden by a device descriptor or by creating a different context than the one used for the capture. Log the context options and inspect the resulting image dimensions.

Rank #4
Sale
Stunning Digital Photography
  • Used Book in Good Condition

“Full-page capture runs out of memory”

Reduce viewport width, use CSS scaling, capture sections or elements separately, and avoid unnecessarily high DPR. Very tall pages create large intermediate bitmaps even when the final file is compressed.

“The dimensions differ by one pixel”

Fractional layout coordinates, transforms, borders, scrollbar behavior, and browser rounding can affect element bounds. Prefer integer viewport sizes, avoid fractional transforms in test fixtures, and assert a stable target element rather than relying on a computed fractional box.

“The image looks different on another machine”

Fonts, browser binaries, operating-system rendering, animations, caret visibility, network-loaded content, and timezone or locale can alter pixels. Pin the Playwright browser version, install identical fonts, disable animations where appropriate, wait for the same readiness condition, and use one controlled execution environment for baselines.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Verify the result instead of guessing

  1. Record the context viewport and deviceScaleFactor.
  2. Record the screenshot API and explicit scale.
  3. Record whether the capture is viewport, full-page, clipped, or element-based.
  4. Inspect the saved file’s pixel width and height with an image tool or library.
  5. Compare those dimensions with the expected CSS dimensions multiplied by the selected device scale, allowing for element bounds and rounding.

For reproducible pipelines, store these settings beside each baseline or artifact. “300 DPI” is not enough information to reproduce a Playwright screenshot; “1280 CSS pixels, DPR 2, device scale” is.

Or skip the browser setup

If you need a URL rendered to an image or PDF rather than a locally controlled Playwright context, ScreenshotNeo provides a website screenshot API and MCP server. Its clean-shot pipeline accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.

One GET request is enough:

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

See the ScreenshotNeo API documentation for parameters. The same request in 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)

And in 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}`);

ScreenshotNeo also supports full-page and element captures, dark mode, device presets or custom viewports, retina scale, custom CSS and JavaScript, waits, request blocking, headers and cookies, timezone and geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous webhooks, bulk capture, usage reporting, and PDF options. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Cost, performance, and reliability considerations

  • Device-scale images contain more pixels and generally take more CPU, memory, storage, and transfer time than CSS-scale images.
  • Full-page captures are affected by document height, lazy-loaded assets, fonts, animations, and third-party requests; wait for the state your screenshot is meant to represent.
  • For visual tests, deterministic settings are more valuable than maximum pixel count. A consistent CSS-scale baseline is often easier to diff and store.
  • For design handoff or high-density display output, device scaling can be appropriate, but define the target viewport and DPR explicitly so recipients know what the dimensions mean.

Frequently Asked Questions

Can I set screenshot DPI to 300 in Playwright?

No documented screenshot option sets print DPI. Choose CSS or device pixel output and, if necessary, convert the resulting pixel dimensions for your print workflow.

Does `deviceScaleFactor: 2` always make a screenshot twice as wide?

Only device-scaled output follows the emulated DPR. With `scale: ‘css’`, dimensions remain tied to CSS pixels; full-page and element bounds can also change the final size.

What scale should I use for visual regression tests?

Use one explicit scale consistently for baseline creation and comparison. CSS scaling is usually simpler because image dimensions track the CSS viewport, but device scaling is valid when your test target is device-pixel output.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.