ScreenshotNeo

BlogHow-to

Why Does My HTML Screenshot Have the Wrong Viewport Width?

A screenshot’s pixel width and a page’s CSS viewport width are different measurements. Trace the mismatch through viewport settings, device scale, mobile emulation, and capture extent.

By the ScreenshotNeo team4 October 20267 min read

A screenshot’s raster width is not necessarily the page’s viewport width. The browser viewport controls layout in CSS pixels; device scale factor and screenshot scale determine how those CSS pixels map to image pixels. Mobile emulation and the page’s viewport meta tag can affect responsive layout, while full-page or clipped capture changes the image extent.

To diagnose the mismatch, compare the requested CSS viewport with the saved image dimensions, then check device scale, mobile settings, viewport metadata, and capture mode. The title alone is not enough to identify which layer caused a particular screenshot.

1. Separate viewport width from screenshot width

Measurement What it means Where to inspect it
CSS viewport width The layout width available to page content, measured in CSS pixels. Browser context or page viewport configuration.
Screenshot raster width The number of image pixels across the saved file. Image dimensions and screenshot scale settings.
Capture extent The region represented: visible viewport, a clip, or the full scrollable page. Screenshot options.

These values are related but not interchangeable. For example, a screenshot twice as wide in raster pixels as the configured CSS viewport could be consistent with device-pixel scaling. That is one possibility to check, not a diagnosis of any particular image.

2. Check the browser viewport and configuration order

Start with the actual browser context viewport in CSS pixels. In Playwright, inspect the viewport supplied when creating the context and any later page.setViewportSize() call. Device presets can provide viewport settings; a later explicit override can change them.

When you use a device preset, inspect the effective settings after applying the preset and after your own overrides. Record the final width and height rather than relying on the values you intended to set.

import { chromium } from 'playwright';

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

console.log('viewport in CSS pixels:', page.viewportSize());
await page.screenshot({ path: 'viewport.png' });
await browser.close();

If your script calls page.setViewportSize() later, that later value is the one to compare with your result. Playwright’s emulation guide describes device emulation and viewport overrides, and its Page API documents viewport and screenshot options.

3. Compare CSS pixels with raster pixels

Check the context’s deviceScaleFactor and the screenshot’s scale option. Device-scale screenshots can use device pixels, producing more raster pixels per CSS pixel on a high-density configuration. Playwright screenshot scale can also be set to device scale or CSS scale; CSS scale emits one image pixel per CSS pixel.

Do not infer the layout viewport from the output file’s dimensions alone. First check the configured CSS width, then inspect screenshot scaling and the image width. If the viewport is 1280 CSS pixels and the output width is 2560 pixels, a scale factor of two is a diagnostic lead to investigate, not proof of the cause.

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

Consult the Playwright API parameters for viewport, device scale factor, mobile behavior, and screenshot scale settings.

4. Check mobile emulation and the viewport meta tag

Mobile emulation affects how the browser interprets the page. In Playwright, isMobile controls whether the page’s meta viewport tag is taken into account. A narrow-screen page should generally declare its intended viewport in the document head:

<meta name="viewport" content="width=device-width">

Without an appropriate viewport declaration, some narrow-screen browsers can use a wider virtual layout viewport and scale the page down. That can make responsive layout behave differently from what you expect at the emulated device width. Check the actual HTML delivered by the page, including any server-rendered or dynamically modified head content.

MDN explains the viewport meta element and the relationship between a virtual viewport and device width.

5. Confirm what area the screenshot captures

A viewport screenshot captures the visible browser area. A full-page screenshot captures scrollable page content, so its height can differ substantially from the viewport height. A clip defines a capture region that can differ from the viewport. Check whether your screenshot is viewport-only, full-page, or clipped before comparing its dimensions with the browser viewport.

Full-page or clipped capture changes the represented image extent; it does not by itself establish that the layout viewport was wrong. Playwright documents these options in its Page screenshot API. Puppeteer’s ScreenshotOptions also documents full-page and clipping options.

6. Reproduce and record the mismatch

  1. Set an explicit viewport width and height in CSS pixels.
  2. Record the effective viewport after applying device presets and any later overrides.
  3. Record deviceScaleFactor, mobile emulation settings, and screenshot scale.
  4. Inspect the page’s viewport meta declaration as delivered to the browser.
  5. Record whether capture is viewport-only, full-page, or clipped.
  6. Compare the configured CSS width with the saved image’s raster width.
  7. Repeat with a CSS-scale screenshot to check whether the raster-to-CSS mapping explains the difference.

For a useful bug report or support request, include browser and version, automation library and version, requested viewport, device scale factor, mobile setting, viewport meta content, screenshot scale, output image dimensions, and capture mode. Without those details, the exact cause cannot be isolated from the title alone.

7. Troubleshooting common causes

Symptom Likely layer to inspect What to do
The image has more pixels across than the requested viewport width. Device scale factor or screenshot scale. Compare CSS viewport width to raster width and try screenshot scale css.
The page layout looks like a desktop page inside a mobile capture. Mobile emulation and viewport meta tag. Check isMobile and confirm the delivered HTML includes width=device-width where appropriate.
The result differs from the configured viewport after using a device preset. Configuration order or later viewport override. Inspect effective context settings and any later page.setViewportSize() call.
The image dimensions do not match the visible browser viewport. Full-page capture or clip. Review capture options and compare the same region.
The mismatch appears only on one page. Page-specific markup or runtime changes. Inspect the page’s delivered viewport meta tag and record the exact URL and browser settings.

These are diagnostic paths, not guaranteed explanations. A specific cause requires the configuration and output dimensions for the capture in question.

8. Performance, reliability, and cost considerations

For repeatable captures, make viewport, device scale, mobile settings, screenshot scale, and capture extent explicit. Record them with the resulting image so a later comparison uses the same conditions. If a page changes its markup or content at runtime, keep the page URL and relevant capture configuration with the result; otherwise, two captures may differ for reasons beyond viewport width.

Choose raster scale based on the intended output: CSS scale gives one image pixel per CSS pixel, while device-scale output can preserve higher-density rendering with a larger image. Full-page captures can produce taller files than viewport captures. The research sources do not establish universal timing, reliability, or monetary cost figures for these settings, so measure them in the browser and workload you actually use.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Make one GET request with the page URL to receive a screenshot; see the API documentation for the available parameters.

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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; higher plans are Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000, and Business at $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan. Create a free account for 1,000 screenshots a month, with no card required.

FAQ

Does the screenshot file tell me the CSS viewport width?

No. The file reports raster dimensions. Check the browser viewport configuration separately.

Should I always use CSS screenshot scale?

Use it when you want one raster pixel per CSS pixel. Choose based on the output you need; device-scale output can represent more pixels per CSS pixel.

Can a viewport meta tag change my screenshot’s pixel dimensions?

It can affect how a mobile browser lays out the page. The screenshot’s raster dimensions also depend on scale and capture extent, so inspect those separately.

What details are needed to diagnose one screenshot?

Provide the browser and automation versions, effective viewport, device scale factor, mobile setting, viewport meta content, screenshot scale, output dimensions, and capture mode.