ScreenshotNeo

BlogHow-to

How to Capture Website Screenshots with a Specific Device Scale Factor

Set a browser’s device scale factor before navigation, then choose screenshot output scale and capture scope to get the dimensions you expect.

By the ScreenshotNeo team4 October 20268 min read

To capture a website screenshot at a specific device scale factor, configure the browser’s emulated device metrics before navigating to the page. In Playwright, set deviceScaleFactor on the browser context. In Puppeteer, set it with page.setViewport(). Then choose the capture scope and output scale separately: those settings determine whether you capture the viewport, an element, or the full page, and how many image pixels represent each CSS pixel.

For a capture spanning W × H CSS pixels at device scale factor d, device-pixel output is expected to be about (W × d) × (H × d) pixels. This follows from the pixel definitions; capture bounds and rounding may affect the final dimensions. See the official Playwright emulation guide and Playwright screenshot documentation.

1. Device scale factor and screenshot scale

A device scale factor (often shortened to DSF) is an emulated device metric. It describes the relationship between CSS pixels and device pixels. A value of 2 means two device pixels per CSS pixel in each dimension, so an image captured at device-pixel scale can have four times as many pixels as the same CSS-sized capture at scale 1.

Keep these controls distinct:

Control What it affects Example
Viewport width and height The page’s CSS layout area and viewport capture bounds 1280 × 800 CSS pixels
Device scale factor The emulated relationship between CSS and device pixels 2 device pixels per CSS pixel
Screenshot output scale The mapping from CSS pixels to output image pixels, when the API exposes it Playwright css or device
Capture scope Which page region is captured Viewport, element, clipped area, or full page

In Playwright, scale: "css" produces one image pixel per CSS pixel, while scale: "device" produces one image pixel per device pixel. Setting deviceScaleFactor: 2 does not by itself guarantee that every screenshot will be twice as wide and high: output scale and capture scope matter too.

2. Playwright: set the context device scale factor

Create a browser context with the desired viewport and device scale factor, then create a page, navigate, and capture. Set screenshot scale explicitly when output dimensions matter.

import { chromium } from 'playwright';

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',
    fullPage: true,
    scale: 'device',
  });
  await context.close();
} finally {
  await browser.close();
}

This is a complete ES module example for an environment with Playwright installed. The viewport and scale factor are example choices, not universal recommendations.

  • Use scale: "device" when the image should use device pixels. At DSF 2, a 1280 CSS-pixel-wide capture will generally be about 2560 output pixels wide.
  • Use scale: "css" when you want one output pixel per CSS pixel, even if the context emulates a higher-density device.
  • Set fullPage: true to capture the full page; omit it for viewport capture. For an element capture, use the locator screenshot API, for example await page.locator('main').screenshot({ path: 'main.png', scale: 'device' }).
  • For a custom region, use the screenshot API’s clip option with CSS-pixel bounds. Check the documentation for your installed Playwright version for supported screenshot options.

Playwright’s emulation guide demonstrates setting a viewport and deviceScaleFactor on a browser context. Context-level configuration makes the intended device metrics explicit and applies them before the page is loaded.

3. Puppeteer: set the viewport before navigation

In Puppeteer, pass deviceScaleFactor to page.setViewport() before calling page.goto(). Puppeteer advises setting the viewport before navigation because some sites do not expect phones to change size.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({
    width: 1280,
    height: 800,
    deviceScaleFactor: 2,
  });
  await page.goto('https://example.com', { waitUntil: 'load' });
  await page.screenshot({
    path: 'page.png',
    fullPage: true,
    type: 'png',
  });
} finally {
  await browser.close();
}

The example requests a full-page PNG. For viewport capture, set fullPage: false or omit the option. Puppeteer’s screenshot API also supports options such as clipping; consult the reference for your installed version when choosing exact option names and behavior: Page.setViewport() and Puppeteer screenshots.

4. Chrome DevTools Protocol: override device metrics directly

When your automation layer does not expose device scale factor, Chromium’s Chrome DevTools Protocol provides a lower-level route through Emulation.setDeviceMetricsOverride. For example, using a Playwright CDP session with Chromium:

import { chromium } from 'playwright';

const browser = await chromium.launch();
try {
  const page = await browser.newPage();
  const session = await page.context().newCDPSession(page);
  await session.send('Emulation.setDeviceMetricsOverride', {
    width: 1280,
    height: 800,
    deviceScaleFactor: 2,
    mobile: false,
  });
  await page.goto('https://example.com', { waitUntil: 'load' });
  await page.screenshot({ path: 'page.png' });
} finally {
  await browser.close();
}

The protocol’s device metrics override accepts viewport dimensions and deviceScaleFactor; a value of zero disables the override. Protocol support and behavior can depend on the browser version. Check the current Chrome DevTools Protocol Page and Emulation references for the browser you use.

5. Manual capture in Chrome DevTools

For a one-off manual screenshot, Chrome DevTools device mode simulates device conditions and provides a viewport screenshot workflow. Its documentation also describes capturing a device frame in device-specific mode. The documented workflow does not establish a general way to enter any arbitrary custom device scale factor in the screenshot dialog; use scripted browser emulation or the protocol when the exact factor must be controlled. See Simulate mobile devices with device mode.

6. Choose scope and output dimensions

Decide what the resulting image needs to include before capturing:

Goal Capture choice Dimension considerations
What a visitor sees without scrolling Viewport Viewport CSS dimensions multiplied by output pixels per CSS pixel
A particular component Element or locator screenshot Element bounds determine the CSS area; device output scales those bounds
A particular region Clipped screenshot Clip coordinates and dimensions are generally expressed in CSS pixels; verify your library’s API
The entire document Full-page screenshot Page height can be much larger than viewport height; high scale increases total pixels accordingly

When exact output dimensions are a requirement, capture a known region and inspect the generated image dimensions. Full-page output can vary with document height, content loading, and capture behavior, so do not infer its final height from the viewport alone.

7. Device scale factor options and practical choices

  • Factor 1: Useful when you want one device pixel per CSS pixel under device-scale output.
  • Factor above 1: Use when emulating a higher-density display or generating a denser raster image. The resulting image uses more pixels if output is captured at device scale.
  • Viewport dimensions: Choose these independently. DSF changes pixel density; viewport dimensions control the CSS layout size.
  • Mobile emulation: If testing mobile-specific rendering, configure the relevant mobile metrics as well as DSF. A scale factor alone does not make a desktop viewport behave like a phone.
  • Output format: PNG, JPEG, and other formats are separate from emulation. Select a format and quality settings supported by your screenshot API.
  • Version: Browser automation APIs and protocol schemas can change. Match the documentation to your installed package and browser version.

8. Troubleshooting incorrect screenshot dimensions

The image has the expected CSS dimensions, not the larger device dimensions

Cause: In Playwright, screenshot scale may be css, which produces one image pixel per CSS pixel.
Fix: Set scale: "device" when device-pixel output is intended, and verify the context’s deviceScaleFactor.

The page layout changed unexpectedly

Cause: The viewport was changed after navigation or the CSS viewport dimensions differ from the ones expected by the page.
Fix: Configure the viewport and DSF before navigation. Keep viewport width and height separate from the scale factor.

The screenshot is blurry or appears resampled

Cause: The captured output may be at CSS scale, or a later image-processing step may resize it.
Fix: Capture at device scale when you need denser output, and avoid downscaling or upscaling after capture unless intended.

The output is much larger than expected

Cause: Device-scale output increases pixel count in both dimensions; full-page capture can also add substantial height.
Fix: Use CSS scale for one pixel per CSS pixel, lower the DSF, capture only the needed scope, or resize the resulting image deliberately.

Mobile behavior does not match a real device

Cause: DSF controls pixel density, not every aspect of device emulation.
Fix: Configure the viewport and other mobile metrics your workflow requires. Consult the automation framework’s emulation documentation.

The page has missing images or unfinished content

Cause: The screenshot was taken before the relevant content finished loading, or the site loads images lazily as they enter the viewport.
Fix: Choose an appropriate navigation readiness condition, wait for a known selector or application state, and scroll or otherwise trigger lazy content where necessary. Avoid assuming that network idle always means the page is visually complete.

A CDP command fails or has no visible effect

Cause: The browser may not support the command or may interpret parameters differently from the protocol version you expected.
Fix: Check the protocol reference corresponding to the browser version and confirm the session is attached to the intended page target.

9. Performance, reliability, and cost

Higher device-scale output increases image dimensions in both directions. At factor d, the pixel count for a fixed CSS area grows approximately with d²; this is a mathematical consequence of scaling both dimensions, not a benchmark. Larger images can take more memory to encode, require more transfer bandwidth, and occupy more storage. Full-page captures amplify this effect because they include additional page height.

For repeatable results, pin the browser automation package and browser version, set viewport and DSF before navigation, choose screenshot scale explicitly where available, and wait for page-specific readiness. Use the smallest capture scope and output density that meet the requirement. There is no physical capture hardware required for this browser-rendering configuration.

10. Or skip the browser setup

If you want a screenshot API call rather than managing a browser, ScreenshotNeo accepts a URL and returns a screenshot. Its API supports 12 device presets and custom viewports, but the supplied product options do not specify an arbitrary device scale factor control; use Playwright, Puppeteer, or CDP when you specifically need to set an exact custom DSF.

See the ScreenshotNeo API documentation. Example request:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
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)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie and consent banners are accepted or removed before the shot, along with known newsletter popups and chat widgets; each cleanup step can be turned off.
  • Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses include X-Page-Verdict and X-Billed headers.
  • An MCP server gives AI agents tools including take_screenshot, get_page_info, and capture_pdf.
  • The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan.

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

11. Frequently asked questions

Is device scale factor the same as browser zoom?

No. Device scale factor is an emulated device metric. Browser zoom is a separate rendering control and should not be substituted for DSF when your goal is device-pixel output.

Does setting DSF change the CSS layout width?

Not by itself. The viewport’s CSS width and height determine the layout area; DSF determines the device-pixel relationship.

Can I set an arbitrary scale factor in Chrome’s screenshot dialog?

The documented device-mode workflow supports viewport capture and device conditions, but does not establish arbitrary custom DSF input in the screenshot dialog. Use browser automation or CDP for explicit control.

Which approach should I use?

Use Playwright or Puppeteer for scripted captures, Playwright when its documented CSS-versus-device screenshot scale choice is useful, CDP for lower-level Chromium control, and DevTools device mode for manual viewport captures.