ScreenshotNeo

BlogHow-to

Why Is My Mobile Website Screenshot Blurry on a High-DPI Device?

Find out whether blur comes from the viewport, image assets, canvas, or screenshot export—and how to capture a sharp mobile screenshot.

By the ScreenshotNeo team4 October 20268 min read

A mobile screenshot can look blurry on a high-DPI device when its pixels are enlarged to fill a denser display, when the page is laid out in a viewport wider than the device and scaled down, or when the screenshot is resized after capture. A canvas with a low-resolution backing store and raster images with too few source pixels can also look soft. First find out whether the live page is blurry or only the saved file; then check the affected content and the capture dimensions.

A CSS pixel is a layout unit. window.devicePixelRatio (DPR) describes the relationship between physical display pixels and CSS pixels; it commonly exceeds 2 on modern high-resolution phones. DPR does not tell you the intrinsic resolution of an image or guarantee that an exported screenshot has enough pixels. MDN explains DPR and how zoom can affect it.

1. Find where the blur enters

  1. Open the page on the target phone and inspect it at its normal viewing size.
  2. Compare the live page with the saved screenshot. View the screenshot at its native pixel size if possible; a viewer that scales the image can make a sharp file look soft.
  3. Identify what is blurry: all content, only raster images, a canvas, or one transformed element.
  4. Record the browser, operating system, CSS viewport dimensions, DPR, screenshot pixel dimensions, and whether the image was resized after capture.

If the page looks crisp but the file looks soft, investigate capture resolution, export settings, and later resizing first. If both are blurry, inspect the viewport and the content type. This is a diagnostic inference: browser rendering and screenshot export have separate sizing controls.

console.log({
  dpr: window.devicePixelRatio,
  viewportWidth: document.documentElement.clientWidth,
  viewportHeight: document.documentElement.clientHeight,
  screenWidth: window.screen.width,
  screenHeight: window.screen.height
});

The viewport values above are CSS dimensions, not the screenshot file’s pixel dimensions. Measure the actual saved image separately.

2. Check screenshot dimensions and capture settings

Compare the screenshot’s pixel width and height with the CSS area you intended to capture. A screenshot with roughly one output pixel per CSS pixel may appear soft when displayed across a high-DPI screen. Also check whether the capture is of the visible viewport or the full page, and whether an image editor, CMS, or messaging app resized or recompressed it.

In Chrome DevTools, enable device mode, select the mobile dimensions and DPR, and capture either the visible viewport or the full page. Chrome documents these controls in Simulate mobile devices with device mode. Emulation helps reproduce dimensions, but verify the result on the actual target browser when the distinction matters.

Keep capture dimensions and page rendering separate in your diagnosis. Increasing the capture output size will not repair a low-resolution logo embedded in the page. Likewise, fixing an image source will not correct a screenshot that is downscaled after capture.

3. Check the viewport before changing resolution

A mobile page without an appropriate viewport declaration may use a wider virtual layout viewport and shrink the page to fit. This can make the entire page appear smaller or softer even though the display density is high. For a responsive page, a common starting point is:

<meta name="viewport" content="width=device-width, initial-scale=1">

MDN’s viewport reference recommends setting the viewport width to the device width. It notes that initial-scale=1 can help avoid unwanted shrinking in some cases and advises avoiding horizontal overflow. Android’s web app guidance also recommends targeting the device width.

Check for wide fixed-width containers, tables, images, or other content that overflows horizontally. A viewport declaration does not add pixels to an undersized image, so fix layout and asset resolution as separate issues if both are present.

4. Check raster images at their rendered size

If text and vector artwork look crisp while a photo or logo looks soft, inspect that asset first. Compare its intrinsic pixel dimensions with its rendered CSS dimensions and the target display density. A small bitmap enlarged to fill a high-density screen can look blurry. Android’s guidance describes images being scaled up on higher-density screens, and MDN’s viewport guidance discusses high-DPI bitmap artwork in the context of mobile displays.

  • Provide a higher-resolution source when the existing bitmap is being enlarged.
  • Use responsive image sources or density variants where appropriate, and confirm which source the browser selected.
  • Check that a build, CDN, or image optimization step has not substituted a smaller asset.
  • Inspect the original file as well as the rendered page; a sharp source can still be blurred by CSS scaling or later processing.

Do not apply a global resolution change when only one image is soft. Match the fix to the affected content.

5. Give a canvas a high-DPI backing store

A canvas has a CSS display size and a separate pixel backing store set by its width and height attributes. If the backing store has too few pixels for the displayed size and DPR, the browser scales it up and drawing can look soft. Set the backing dimensions to the measured CSS size multiplied by DPR, then scale the drawing context so drawing coordinates can remain in CSS pixels.

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

function resizeCanvas() {
  const rect = canvas.getBoundingClientRect();
  const dpr = window.devicePixelRatio || 1;

  canvas.width = Math.floor(rect.width * dpr);
  canvas.height = Math.floor(rect.height * dpr);
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

  // Redraw using CSS-pixel coordinates after resizing.
  drawChart(ctx, rect.width, rect.height);
}

resizeCanvas();
window.addEventListener("resize", resizeCanvas);

function drawChart(ctx, width, height) {
  ctx.clearRect(0, 0, width, height);
  ctx.beginPath();
  ctx.moveTo(8, height - 8);
  ctx.lineTo(width - 8, 8);
  ctx.stroke();
}

This is a reusable pattern, not a tested fix for a particular site. Assigning canvas dimensions resets its drawing buffer and context state, so redraw after resizing and reapply any styles or state your drawing needs. Recheck the measured size when the canvas’s layout changes, not only on window resize. MDN demonstrates DPR-aware canvas sizing in its devicePixelRatio reference; see also web.dev’s High DPI Canvas.

6. Separate device scale, zoom, and transforms

Several mechanisms can change how content appears:

  • Device scale: the relationship between physical pixels and CSS pixels, reported in part by DPR.
  • Browser page zoom: can affect devicePixelRatio.
  • Pinch zoom: MDN notes that pinch zoom does not affect devicePixelRatio.
  • CSS or SVG transforms: can scale an individual element or graphic.

These mechanisms do not all change the layout viewport in the same way. WebKit’s Scales and Zooms reference describes the distinction between device scale, page scale, and page zoom. Browser behavior can vary, so inspect the actual target browser instead of assuming identical behavior across platforms.

7. Troubleshooting checklist

Symptom Likely cause What to check or change
The whole mobile page looks reduced or soft The layout viewport is wider than the device, or content overflows Set an appropriate viewport width, inspect fixed-width elements, and check for horizontal overflow.
Live page is crisp but the saved screenshot is soft Capture output is too small, or the file was resized or recompressed Compare the saved pixel dimensions with the intended capture area; inspect export and upload steps.
Text and vector shapes are sharp, but a photo or logo is blurry The selected raster source has too few pixels or is enlarged Inspect intrinsic dimensions and the selected source; provide an appropriate higher-density asset.
Only a chart or drawing is blurry The canvas backing store is smaller than its CSS display size at the target DPR Size the backing store using measured CSS dimensions multiplied by DPR, then redraw.
Blur changes when zooming Page zoom, pinch zoom, or an element transform changes scale Record the zoom state and inspect DPR and transforms separately.
A device emulation capture differs from the phone Emulation and the actual browser or operating system may render differently Compare browser and OS, viewport, DPR, and capture mode; confirm on the target device.
The page is sharp until it is uploaded or shared A downstream service resized or recompressed the file Compare the original capture with the downloaded copy and review the service’s image settings.
Canvas content disappears or styles change after resizing Changing canvas width or height reset its drawing buffer and context state Redraw the canvas and restore the required context state after each dimension change.

8. Performance, reliability, and cost considerations

Higher-resolution screenshots contain more pixels and can take more memory to process and more storage or bandwidth to transfer. Capture only the dimensions and page area you need, and avoid repeatedly resizing a large image through lossy formats. For canvas, redraw only when the size or density changes rather than doing unnecessary work on every frame.

For repeatable comparisons, record the browser and OS, CSS viewport, DPR, capture mode, output dimensions, and any post-processing. This makes it easier to tell a rendering change from an export change. DevTools emulation is useful for a controlled reproduction, while the target device remains the relevant check for device-specific behavior.

Or skip the browser setup

If you need a clean screenshot for a URL without setting up browser capture, ScreenshotNeo is a website screenshot API and MCP server. One GET request can return an image or PDF. See the ScreenshotNeo API documentation for options, including device presets, custom viewport dimensions, and retina scale.

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 bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are never billed; the response identifies the page verdict and billing status in headers. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000 screenshots.

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

FAQ

Does a high DPR automatically make every screenshot sharp?

No. DPR describes a display relationship; image source resolution, canvas backing dimensions, capture output size, and later resizing still matter.

Should I set DPR manually in my website?

Usually, first check how the page is captured and whether specific assets or canvases lack pixels. DPR is a browser-reported value, while the right fix depends on the blurry stage and content.

No. It helps control mobile layout width and scaling. A low-resolution raster logo needs a more suitable source image.

Does full-page capture change the page’s resolution?

It changes the captured area. Check the resulting file dimensions and the capture tool’s device scale separately.