How to Fix Blurry Website Screenshots on Retina Displays
Understand CSS pixels, device pixels, and devicePixelRatio, then choose the right screenshot scale for sharp Retina captures in Playwright.
A Retina screenshot can look blurry when the capture contains one output pixel per CSS pixel even though the display uses multiple physical pixels for each CSS pixel. First check window.devicePixelRatio; then set your screenshot tool to capture at device-pixel scale when you need fine detail. In Playwright, use scale: "device" for a high-resolution image or scale: "css" for compact output whose pixel dimensions match the CSS layout.
These are different output goals, not a universal sharpness switch. Device-scale output is larger on high-density displays. If it remains soft, inspect the page’s source images and any resizing or compression applied after capture.
1. CSS pixels, device pixels, and Retina displays
CSS pixels describe layout dimensions: for example, a page element may be 800 CSS pixels wide. Device pixels are the physical pixels used to render that layout on a display. window.devicePixelRatio reports the ratio of physical pixels to CSS pixels. MDN gives 2 as an expected value for HiDPI or Retina displays, though the actual value depends on the display and its configuration.
At a device pixel ratio of 2, an 800 CSS-pixel-wide viewport corresponds to 1,600 device pixels across. A screenshot tool can save either an image sized around 800 pixels wide, with one output pixel per CSS pixel, or one sized around 1,600 pixels wide, with one output pixel per device pixel. Playwright exposes this choice through its screenshot scale option.
| Capture scale | Output dimensions | Best for | Trade-off |
|---|---|---|---|
"device" |
Device-pixel resolution; typically larger on high-DPI displays | Design review, fine detail, or a high-resolution asset | Larger image and file size |
"css" |
One output pixel per CSS pixel | Compact screenshots aligned to CSS layout dimensions | Less output detail than device-scale capture |
Do not compare the two images as if they have the same target dimensions. A CSS-scale screenshot can be a correct capture for a compact, CSS-sized deliverable even if it looks less detailed when enlarged on a Retina screen.
2. Diagnose the screenshot before changing settings
- Open the page in the browser and run
window.devicePixelRatioin the developer console. Record the result. - Check the screenshot tool’s scale setting. Determine whether it emits CSS-pixel or device-pixel output.
- Inspect the saved image dimensions. Compare them with the viewport’s CSS dimensions and the device pixel ratio.
- Decide what the file is for: detailed review or a compact image matching CSS dimensions.
- If the image is still soft at device scale, check for low-resolution images on the page and for resizing or compression after capture.
The device pixel ratio is not itself a sharpness score. It helps explain why the same CSS viewport can correspond to different screenshot dimensions.
3. Capture a sharp screenshot with Playwright
Playwright’s screenshot API supports scale: "device" and scale: "css". Set the choice explicitly so the output matches the intended deliverable. The example below is a complete Node.js script using Playwright’s documented screenshot API.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({
viewport: { width: 1280, height: 800 },
deviceScaleFactor: 2,
});
await page.goto('https://example.com', { waitUntil: 'networkidle' });
console.log('devicePixelRatio:', await page.evaluate(() => window.devicePixelRatio));
// Use "device" for high-resolution detail, or "css" for CSS-sized output.
await page.screenshot({ path: 'screenshot.png', fullPage: true, scale: 'device' });
await browser.close();
})();
Install the dependency and run the script with Node.js:
npm install playwright
node screenshot.js
The browser context’s deviceScaleFactor sets the emulated device scale factor; the screenshot’s scale determines whether output pixels follow CSS or device pixels. Choose the scale deliberately and verify the saved dimensions. The official details are in the Playwright screenshot API documentation.
Choose the right scale
- Use
scale: "device"when the deliverable needs the device-pixel detail of a high-density capture. - Use
scale: "css"when you need a smaller image with one output pixel per CSS pixel. - Keep the viewport fixed when comparing captures. Changing viewport dimensions changes layout and makes the comparison harder to interpret.
For a reproducible bug report, record the browser and capture tool, viewport dimensions, device pixel ratio, screenshot scale, and saved image dimensions.
4. Other screenshot workflows: cURL, Python, and Node.js
For a direct browser automation workflow, use Playwright’s scale option above. If you already capture through another screenshot API, check its documentation for whether it captures CSS pixels or device pixels and whether it offers an output scale or device scale factor. The following generic examples save an API response; they do not set a provider-specific Retina scale, because that option and its parameter name vary by service.
cURL
curl -L 'SCREENSHOT_ENDPOINT?url=https%3A%2F%2Fexample.com' -o screenshot.png
Python
import requests
response = requests.get(
"SCREENSHOT_ENDPOINT",
params={"url": "https://example.com"},
timeout=90,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image:
image.write(response.content)
Node.js
const endpoint = new URL('SCREENSHOT_ENDPOINT');
endpoint.searchParams.set('url', 'https://example.com');
const response = await fetch(endpoint);
if (!response.ok) {
throw new Error(`Screenshot request failed: ${response.status}`);
}
await Bun.write('screenshot.png', new Uint8Array(await response.arrayBuffer()));
Replace SCREENSHOT_ENDPOINT with the provider’s documented endpoint and add its authentication and scale parameters as documented. Confirm the response is an image before saving it if the provider can return JSON errors.
5. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its scale option supports high-resolution captures. A GET request returns an image or PDF; see the ScreenshotNeo API documentation for the API options and authentication details.
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}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));
Cookie banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. An 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; paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month with no card.
6. Troubleshooting blurry output
| Symptom | Likely cause | What to check or do |
|---|---|---|
| Screenshot dimensions match the CSS viewport, but fine details look soft when enlarged | The tool captured one output pixel per CSS pixel | Choose device-pixel output; in Playwright set scale: "device". |
| Screenshot is larger than expected | Device-scale output creates more pixels on a high-DPI display | Use scale: "css" if compact CSS-sized dimensions are the goal. |
| Screenshot is high resolution, but page images still look blurry | The source images may not have enough detail for the rendered size | Inspect the page’s image sources and compare them with their displayed size. |
| Image looked sharp before export or upload | A later resize or compression step may have softened it | Compare the original capture with the final file and check each processing step. |
| Two captures have different dimensions or layout | Viewport, device scale factor, or page state differed | Keep the viewport and page state consistent; record the DPR and screenshot scale. |
Increasing screenshot scale cannot restore detail that is absent from the page’s source assets, and it cannot reverse later resizing. Treat scale as a way to choose output resolution, then trace remaining softness through the page assets and the image-processing pipeline.
7. Performance, reliability, and file size
- File size: Device-scale screenshots contain more output pixels on high-density displays and therefore can produce larger files. The exact size also depends on image content and encoding.
- Capture time and memory: A larger output image requires more pixels to render and encode. For batch jobs, use CSS scale where high-resolution detail is not needed, and avoid capturing more page area than the deliverable requires.
- Repeatability: Fix the viewport, scale choice, browser, and page state when comparing screenshots. Record dimensions and DPR with the output.
- Reliability: Wait for the page content needed in the screenshot to load. A high-resolution capture of an incomplete page will still be incomplete; use a suitable navigation or readiness condition for the site.
- Cost: For a self-hosted browser workflow, account for the compute and storage needed for larger images. For an API, check its billing and failure policy rather than assuming all requests have the same cost.
8. FAQ
Does every Retina screenshot need device scale?
No. Use device scale when detail is the priority. Use CSS scale when matching the layout’s CSS dimensions and keeping the file compact matter more.
Is devicePixelRatio always 2 on a Retina display?
No. Two is an expected value for HiDPI or Retina displays, but the reported ratio can vary with display and configuration. Check it in the actual browser session.
Will device-scale capture fix blurry images inside the website?
Not if the page’s source image is already low resolution or the screenshot is resized or compressed afterward. Device scale controls capture output resolution; it does not add missing source detail.


