ScreenshotNeo

BlogHow-to

How to Capture a Website Screenshot with a Custom Device Scale Factor

Set a browser’s device scale factor and screenshot output scale independently. See runnable Playwright and Chrome DevTools Protocol examples, plus troubleshooting tips.

By the ScreenshotNeo team4 October 20268 min read

To capture a website screenshot with a custom device scale factor, configure the browser’s emulated device pixel ratio before loading the page, then capture it. In Playwright, set deviceScaleFactor on the browser context. In Chrome DevTools Protocol (CDP), send Emulation.setDeviceMetricsOverride before Page.captureScreenshot.

Keep two controls separate: deviceScaleFactor changes the browser’s emulated device scale, while Playwright’s screenshot scale chooses output density. For a reproducible capture, record both, as well as viewport dimensions, browser version, format, and whether you captured the viewport, an element, or the full page.

1. Understand device scale factor and screenshot scale

A CSS pixel is a layout unit. A device pixel is a physical or emulated display pixel. The device scale factor (often associated with device pixel ratio) describes how many device pixels correspond to a CSS pixel in the emulated environment.

Playwright’s context option deviceScaleFactor defaults to 1. Its screenshot scale is a separate setting:

Setting Controls Typical choice
deviceScaleFactor The browser context’s emulated device scale factor and related page environment. Set deliberately when matching a target device or test condition.
scale: 'css' Writes one output image pixel per CSS pixel. Use for CSS-pixel-sized output.
scale: 'device' Writes one output image pixel per device pixel. Use when the output should reflect the emulated device pixel density.

Changing screenshot scale does not itself configure the browser context’s emulated device scale. Conversely, setting a context factor does not tell every screenshot method to emit device-density output: choose the screenshot scale explicitly when the API offers it. See the [Playwright BrowserType API](https://playwright.dev/docs/api/class-browsertype#browser-type-new-context) and [Page screenshot API](https://playwright.dev/docs/api/class-page#page-screenshot).

2. Capture with Playwright

This JavaScript example launches Chromium, creates a context at a 1280 × 800 CSS-pixel viewport with a factor of 2, navigates to a page, and writes a PNG at device-pixel scale.

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', { waitUntil: 'load' });
    await page.screenshot({ path: 'page.png', scale: 'device' });
    await context.close();
  } finally {
    await browser.close();
  }
})();

Install Playwright and its Chromium browser in your project before running the script (for example, npm install playwright and npx playwright install chromium). This code illustrates documented API options; it is not a report of a live test.

Choose output scale intentionally

For one output pixel per CSS pixel, use scale: 'css'. For one output pixel per device pixel, use scale: 'device'. At a factor above 1, device-scale output can be substantially larger in pixel dimensions and file size. If you omit scale, check the behavior documented for the Playwright version installed in your project rather than assuming it matches your desired density.

// CSS-pixel output density
await page.screenshot({ path: 'page-css-scale.png', scale: 'css' });

// Device-pixel output density
await page.screenshot({ path: 'page-device-scale.png', scale: 'device' });

Viewport, element, and full-page captures

By default, page.screenshot() captures the current viewport. To capture the full scrollable page, set fullPage: true. To capture one element, use its locator’s screenshot method. The documented screenshot tool does not combine full-page mode with a target element.

// Full scrollable page
await page.screenshot({ path: 'full-page.png', fullPage: true, scale: 'device' });

// One selected element
await page.locator('main article').screenshot({ path: 'article.png' });

For element captures, confirm the selected element is present and visible before capture. If you need matching output density across page and element screenshots, consult the method-specific options for your Playwright release.

Use a different factor or viewport

Set a positive factor and the viewport explicitly for each context. A factor such as 2.625 is valid as an example value in Chrome’s protocol documentation, but it is not a universal recommendation. Choose the value that matches your test target.

const context = await browser.newContext({
  viewport: { width: 390, height: 844 },
  deviceScaleFactor: 3,
});

For reliable comparisons, keep viewport width and height constant while changing only the factor. A different viewport can trigger different responsive breakpoints and layout, independently of output density.

3. Capture with Chrome DevTools Protocol

CDP exposes the device scale factor through Emulation.setDeviceMetricsOverride. Apply the metrics override before requesting the screenshot. The CDP reference says a value of zero disables the device scale override; use a positive value when you want to set one.

The following is a protocol sequence, not a complete WebSocket client. Send each JSON command on the CDP session attached to the target page, using the session’s command mechanism and valid command IDs:

// 1. Configure emulated metrics on the page's CDP session.
{
  "id": 1,
  "method": "Emulation.setDeviceMetricsOverride",
  "params": {
    "width": 1280,
    "height": 800,
    "deviceScaleFactor": 2,
    "mobile": false
  }
}

// 2. After the override is applied, request a screenshot.
{
  "id": 2,
  "method": "Page.captureScreenshot",
  "params": {
    "format": "png",
    "captureBeyondViewport": false
  }
}

Use the returned screenshot data from the protocol response and decode it from base64 to save the PNG. The exact setup for attaching a CDP session and sending commands depends on the automation client. The [CDP protocol reference](https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setDeviceMetricsOverride) documents the metrics override, and the [Page domain](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-captureScreenshot) documents screenshot capture. The [Chrome DevTools Protocol overview](https://developer.chrome.com/docs/devtools/protocol/) demonstrates applying an override and then requesting a screenshot.

4. Reproduce and compare captures

When a screenshot differs between machines or runs, record these inputs before diagnosing the difference:

  • Browser and automation framework, including versions.
  • Viewport width and height in CSS pixels.
  • Emulated deviceScaleFactor.
  • Screenshot output scale and image format.
  • Capture mode: viewport, selected element, or full page.
  • Target URL and any relevant page state, such as loaded fonts, animation state, or authenticated content.

For a controlled comparison, change one variable at a time. First hold the viewport, page state, browser, and output scale constant while changing the factor. Then compare CSS-scale and device-scale output with the context held constant.

5. Troubleshooting

Symptom Likely cause Fix
The image has the expected layout but the wrong pixel dimensions. The context factor and screenshot output scale were treated as one setting. Set deviceScaleFactor on the context and choose screenshot scale separately.
The page layout changes when changing the factor. The browser environment changed; the page may use device-density information or other device-dependent behavior. Keep viewport dimensions fixed and inspect responsive or device-aware page logic.
CDP screenshots ignore the requested factor. The screenshot command ran before the emulation override was applied, or the override was sent to a different target session. Apply Emulation.setDeviceMetricsOverride on the target page session, wait for its response, then call Page.captureScreenshot.
The CDP override resets or behaves unexpectedly. A later command or client setup changed emulation metrics; zero specifically disables the scale override. Inspect all emulation commands and send the intended positive factor immediately before capture.
The output is unexpectedly large or memory use increases. Device-scale output multiplies image dimensions as density rises; full-page capture also covers more content. Use CSS scale if it meets the requirement, lower the factor, or capture a smaller region.
Full-page and element options conflict. The documented Playwright screenshot tool does not allow full-page mode together with a target element. Capture the full page separately, or capture the selected element without full-page mode.
Automation code rejects an option. The installed framework version may differ from the API version used by an example. Check the installed version’s official API reference and use the option on the correct context or screenshot method.

6. Performance, reliability, and cost

Higher device-scale output can increase pixel dimensions, encoding work, memory use, and file size. Full-page captures can add further work because they include content beyond the initial viewport. Use the smallest factor and capture area that satisfy the downstream need. For visual regression, keep the browser version, viewport, factor, output scale, and page state stable to reduce unrelated differences.

A local browser capture has no per-screenshot API charge, but it requires browser installation, runtime resources, and maintenance of the automation environment. Hosted capture can remove that setup work; compare the service’s billing rules, failure handling, supported controls, and output formats before choosing it.

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. Make one GET request with a URL to receive an image or PDF. Its API accepts the parameter names used by other screenshot APIs, which can make switching easier. See the ScreenshotNeo site and API documentation for the available parameters and configuration.

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say the page verdict and whether the request was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan.

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

8. Frequently asked questions

Does a factor of 2 mean the browser viewport is twice as wide?

No. The viewport width and height are specified in CSS pixels. The factor describes emulated device density, not a change to the CSS viewport dimensions.

Can I use a fractional device scale factor?

CDP’s protocol example uses 2.625. Confirm support and behavior in the target browser and automation version, and record the exact value in reproducibility notes.

Should I use Playwright or CDP?

Use Playwright when its context and screenshot APIs cover the capture you need. Use CDP when you need the lower-level Chrome protocol workflow or are integrating directly with a CDP client.

Does Puppeteer support screenshots?

Puppeteer documents page screenshots and element screenshots. Its device-scale configuration depends on the Puppeteer version and device-emulation API in use, so check that version’s reference before relying on a particular option.

Sources