A screenshot taken at 1× looks soft on almost every screen people use today: phones, most laptops and many monitors draw two or three physical pixels per CSS pixel. A "retina" or high-DPI screenshot captures the page at that density, so text and icons stay crisp when the picture is shown at its intended size. This page shows how in Puppeteer, Playwright and our API, and what the extra pixels cost in file size.
How we measured. On 2026-11-08 we captured python.org's first screen at a 1280×800 viewport through our API at pixel ratios 1, 2 and 3, as PNG and WebP, plus a full page at 2× and two over-wide requests to see the cap.
What the pixel ratio does
The page does not change. A 1280×800 viewport lays the page out at 1280 CSS pixels wide in every case, with the same breakpoints, the same line breaks and the same layout. Only the drawing changes: at ratio 2 each CSS pixel is drawn as 2×2 image pixels, at ratio 3 as 3×3. Text is rasterised at the higher density, so the letters are sharper, not just bigger. In the browser the same number is window.devicePixelRatio.
That is different from a bigger viewport. 2560×1600 at 1× is a different layout — the page sees a wide desktop and may show more columns — and its text stays the same physical size, so it looks tiny when the picture is shrunk to fit.
Puppeteer and Playwright
// Puppeteer
await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: 2 });
await page.screenshot({ path: 'retina.png' });
// Playwright
const context = await browser.newContext({ viewport: { width: 1280, height: 800 }, deviceScaleFactor: 2 });
const page = await context.newPage();
await page.screenshot({ path: 'retina.png' });
Puppeteer's deviceScaleFactor is documented as "Specify device scale factor. See devicePixelRatio for more info" (Puppeteer: Viewport). Playwright adds a scale option on screenshot(): "device" (the default) keeps one image pixel per device pixel, "css" one per CSS pixel, so "screenshots of high-dpi devices will be twice as large or even larger" with the default (Playwright: page.screenshot). Device descriptors set the ratio for you: an iPhone 15 is 3.
Our API: scale
curl -X POST "https://shareglint.com/v1/screenshots?wait=true" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.python.org/", "scale": 2, "format": "webp", "block_cookie_banners": true}'
scale takes 1, 2 or 3 (1.5 was refused with "scale must be one of: 1, 2, 3."); device presets bring their own ratio unless you set it. What came back:
| Ratio | Picture | PNG | WebP (quality 85) |
|---|---|---|---|
| 1 | 1280×800 | 133 KB | 56 KB |
| 2 | 2560×1600 | 323 KB | 129 KB |
| 3 | 3840×2400 | 533 KB | 208 KB |
| 2, full page | 2560×5216 | 1.1 MB | — |
Four times the pixels at 2× cost 2.4 times the PNG bytes and 2.3 times the WebP bytes: flat areas compress no matter how many pixels they cover. Render times were 6.5–9.0 s for all of them, the page's own loading dominating; the pixel ratio barely showed.
The width cap
A file is at most 7,680 px wide. When viewport_width × scale would exceed that, the ratio is lowered to fit instead of refusing the request: a 3840×1080 viewport at scale: 3 came back as 7680×2160 — the same picture as scale: 2, and in fact the same file, because the lowered request matched the cached one. Chrome itself captures up to 16,384 px; the lower cap keeps files at a size anyone can open.
The height of a full-page capture has its own cap, 16,000 px of picture, and it counts image pixels, not CSS pixels. At 2× a long page is therefore cut after half as much of the page as at 1×, and at 3× after a third. For a very long article or a documentation page, a full-page capture at 1× shows the whole page where a 3× one stops partway; pick the ratio by how the picture will be used, not by habit.
Which ratio to use
- 2× for anything shown on a web page, in docs, in a slide or an email at its natural size. It matches most laptops and many phones, and it is the sweet spot of sharpness per byte.
- 3× for phone screenshots meant to look native on a phone (App Store-style images; our
iphone-15preset uses 3) and for print at small sizes. - 1× for thumbnails you will shrink anyway, visual-regression baselines (smaller diffs, faster comparisons) and anything where file size matters more than detail.
If the picture will be displayed smaller than its CSS size — a 1280 px page shown 400 px wide — 1× is already more than enough pixels; capture at 1× and resize (website thumbnails). Ratio only helps when the image is shown at or near its CSS size on a dense screen.
In HTML: tell the browser what you have
A 2× image shown at its CSS size needs its CSS size in the markup, or it is drawn twice as large:
<img src="shot-2x.webp" width="1280" height="800" alt="python.org home page">
<!-- or offer both and let the browser pick -->
<img src="shot-1x.webp" srcset="shot-1x.webp 1x, shot-2x.webp 2x" width="1280" height="800" alt="python.org home page">
To check what a page actually shows, open the image in DevTools and compare its naturalWidth (pixels in the file) with its rendered width (CSS pixels on the page): a 2× screenshot shown correctly has a naturalWidth twice the rendered width. If the two are equal on a retina screen, the browser is stretching a 1× picture, which is the usual reason a screenshot looks soft in a blog post or a README.
Cost
The pixel ratio does not change the price: a viewport capture is 1 render of the quota at any scale, a full page 2, and repeats with the same options within 24 hours are free (pricing). For phone-sized pictures with the right ratio and user agent, see mobile website screenshots; for why 1× pictures look blurry, blank or blurry screenshots.