How to Create Mobile Website Screenshots at Multiple Device Pixel Ratios
Learn how viewport size and device pixel ratio affect mobile screenshots, then capture repeatable images with Chrome DevTools or Playwright.
To create mobile website screenshots at multiple device pixel ratios (DPRs), keep the CSS viewport dimensions fixed and capture the page once for each DPR you want to compare. In Chrome DevTools, set the viewport and DPR in Device Mode, then capture; for repeatable batches, use Playwright contexts with deviceScaleFactor set to each DPR. Choose screenshot scale: 'device' for device-pixel-sized output or scale: 'css' for CSS-pixel-sized output.
Viewport and DPR control different things. The viewport, measured in CSS pixels, affects responsive layout. DPR controls the emulated density: it is the ratio of physical display pixels to logical CSS pixels. A 390 CSS-pixel-wide viewport at DPR 2 typically produces about 780 image pixels across with device scaling, while CSS scaling keeps the image about 390 pixels wide. See the Chrome Device Mode guide.
1. Choose the viewport, DPR, and output scale
Start with the question your screenshot should answer:
- Testing responsive layout? Select widths around your site’s breakpoints. Hold the viewport fixed while comparing DPRs so that layout changes do not obscure pixel-density differences.
- Checking both layout and density? Vary viewport and DPR independently. Record each value so you can tell which setting caused a difference.
- Need CSS-pixel dimensions? Use CSS scaling. This is useful when the artifact should match the configured viewport dimensions.
- Need device-pixel resolution? Use device scaling. The output dimensions grow with DPR, subject to browser rounding and capture details.
- Need the visible screen or the whole document? Capture the viewport for above-the-fold review; use full-page capture only when the deliverable should include the scrollable page.
There is no universal DPR set that fits every site. For a basic multi-DPR check, include a low-density and a high-density setting, then add values relevant to the devices or visual-review matrix you support. Device emulation is useful for responsive review, but it is not a substitute for checking actual handset-specific behavior.
2. Capture a few screenshots with Chrome DevTools
- Open the page in Chrome, open DevTools, and toggle the Device Toolbar.
- Choose Responsive to enter your own dimensions, or select a device preset. Treat presets as convenient starting points rather than a complete device-coverage plan.
- Enter the target width and height in CSS pixels.
- Open More options → Add device pixel ratio if the DPR control is not visible, then choose the desired DPR.
- Choose a mobile device type if you need mobile rendering and touch-event emulation. Device Mode remains browser emulation.
- Use More options → Capture screenshot for the visible viewport, or Capture a full size screenshot for the full page. A device frame is optional presentation context; it does not change the page’s CSS layout.
- Repeat for each DPR, leaving the viewport unchanged when isolating density effects.
Name captures with the page, viewport, DPR, browser, and orientation, for example home-390x844-dpr2-chromium-portrait.png. This makes a set of manually saved images easier to compare later.
Chrome describes Device Mode as a “first-order approximation” of a mobile experience and notes that it does not run code on an actual mobile device. Use a physical handset when the question concerns real-device performance, platform-specific browser behavior, hardware rendering, or touch interaction.
3. Automate a DPR matrix with Playwright
For repeated captures, create a browser context for each viewport/DPR pair. The following runnable Node.js example uses Chromium, captures a 390 × 844 CSS-pixel mobile viewport at DPR 1, 2, and 3, and saves device-scale PNGs.
import { chromium } from 'playwright';
const url = 'https://example.com';
const viewport = { width: 390, height: 844 };
const dprs = [1, 2, 3];
const browser = await chromium.launch({ headless: true });
try {
for (const dpr of dprs) {
const context = await browser.newContext({
viewport,
deviceScaleFactor: dpr,
isMobile: true,
hasTouch: true,
});
const page = await context.newPage();
try {
await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
await page.screenshot({
path: `mobile-390x844-dpr${dpr}.png`,
scale: 'device',
animations: 'disabled',
caret: 'hide',
});
} finally {
await context.close();
}
}
} finally {
await browser.close();
}
To use the example, install Playwright in a Node.js project with npm install playwright, then run it with Node.js. If the site keeps connections open and never reaches network idle, replace that navigation condition with waitUntil: 'domcontentloaded' and wait for a meaningful page-specific selector before capture.
Set scale: 'css' instead when the output should be one image pixel per CSS pixel. Set scale: 'device' for one image pixel per emulated device pixel. Add fullPage: true when you need the entire scrollable page. Inspect exceptionally tall full-page output: it can be unusually large and may not represent ordinary scrolling behavior.
Playwright device descriptors can provide viewport, user-agent, touch, and other device settings. Use a descriptor when it matches the target; use explicit context values when you need a controlled DPR matrix. Playwright documents context emulation in its Emulation guide and screenshot parameters in its Screenshot API reference.
4. Make the screenshots repeatable
A screenshot is a snapshot of a page state as well as a viewport configuration. Before capture, wait for the content that matters, such as a heading, product image, or web font. A fixed sleep can work for a known delay but is less reliable than waiting for a meaningful condition.
- Use the same browser name and version, operating system, headless setting, and capture environment for a baseline and its comparison runs.
- Keep viewport, DPR, orientation, screenshot scale, and full-page setting in the output filename or a companion manifest.
- Disable or freeze animation and hide a blinking caret when they are not part of the comparison.
- Control timestamps, rotating content, random data, ads, and other volatile areas where appropriate. If using screenshot styles to mask them, ensure the styles do not hide content under review.
- Wait for relevant images and fonts to load. For lazy-loaded images below the fold, scroll through the page before a full-page capture if the page requires scrolling to trigger them.
- Keep the scroll position stable for viewport captures.
Playwright warns that screenshots can vary with operating system, browser version, settings, hardware, power source, and headless mode. Its visual-comparison guidance recommends using the same environment for generating baselines and comparison images. Font rasterization and antialiasing differences can otherwise create changes unrelated to your page code. See Playwright’s visual comparisons guide.
5. Understand dimensions, file size, and reliability
For a device-scale viewport capture, a rough dimensional estimate is CSS dimension × DPR. For example, 390 CSS pixels wide at DPR 2 ordinarily means about 780 output pixels wide. Browser rounding, cropping, and full-page behavior can affect the exact result, so inspect the saved image dimensions when exact dimensions matter. With CSS scale, output dimensions remain approximately the CSS viewport dimensions.
Device-scale images can use more memory and storage as DPR rises because the pixel count grows in both dimensions. A 2× scale can therefore produce about four times as many pixels for the same CSS area; actual file size also depends on page content and image encoding. Use CSS scale when CSS-pixel output is sufficient, and reserve high-DPR captures for checks that need the additional raster detail.
For stable automation, set navigation timeouts deliberately, wait for the page content you care about, and close each context after saving. A failed navigation should be reported with its URL and configuration so a rerun can reproduce it. For long pages, capture only the needed scope or divide the review into representative sections if a single full-page bitmap becomes unwieldy.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its one-call endpoint accepts a URL and returns an image or PDF. For a standard mobile screenshot, use the viewport and DPR parameters documented in the ScreenshotNeo API docs; the parameter names used by other screenshot APIs also work.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-d width=390 \
-d height=844 \
-d device_scale_factor=2 \
-o mobile-dpr2.webp
Cookie banners are accepted and 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 cost nothing, and response headers say the page verdict and whether the request was billed. The MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up free and take your first 1,000 screenshots a month without a card.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Layout changes between DPR captures | The viewport, device preset, or mobile emulation settings changed as well as DPR. | Hold viewport dimensions and other context settings constant; vary only deviceScaleFactor. |
| Image is larger or smaller than expected | Screenshot scale differs, or browser rounding/cropping affects the capture. | Check scale, compare actual image dimensions, and use CSS scale for CSS-pixel-sized output. |
| Capture is blurry on a high-density target | The screenshot may have been saved at CSS scale. | Use scale: 'device' when you need device-pixel resolution. |
| Screenshot contains a spinner or incomplete content | Navigation completion did not mean the relevant content was ready. | Wait for a page-specific selector or an application-ready condition; check image and font loading. |
| Playwright times out waiting for network idle | The site has persistent network activity or long-lived connections. | Navigate at domcontentloaded and explicitly wait for the content needed in the image. |
| Full-page image is unexpectedly tall or missing lazy images | Lazy content may need scrolling to load; full-page capture can differ from ordinary scrolling. | Scroll through the page to trigger lazy loading, then capture; inspect the resulting dimensions. |
| Visual diff reports changes on unchanged code | Browser, OS, headless mode, fonts, animation, caret, or dynamic content differs. | Use the baseline environment and stabilize or mask volatile elements carefully. |
| DevTools has no DPR control | The control has not been added to the Device Toolbar. | Use More options → Add device pixel ratio, then select a value. |
| Screenshot does not behave like a real phone | Device Mode emulates a mobile environment; it is not a physical handset. | Validate device-specific rendering and interactions on actual target phones. |
FAQ
Does changing DPR change the CSS layout?
With the CSS viewport and emulation settings held constant, DPR changes pixel density rather than layout width. A changed device preset or viewport can change layout independently.
Should I use full-page capture for mobile screenshots?
Use it when the deliverable must show the whole document. For responsive checks of what a person sees on screen, a viewport capture is usually the relevant artifact.
Does a DPR screenshot prove how a physical phone renders my site?
No. It records an emulated browser configuration. Use a physical device for hardware- or platform-specific verification.
Which DPR values should I include?
Choose values relevant to your target devices and test goals. To demonstrate density behavior, compare at least one low-density and one high-density setting while keeping the CSS viewport fixed.


