How to Capture a Web Page Screenshot at 2x Resolution in Playwright
Set Playwright’s device scale factor to 2 and capture at device scale for a 2× screenshot. Learn how to capture full pages, troubleshoot sizing, and verify output.
To capture a web page screenshot at 2× resolution in Playwright, set deviceScaleFactor: 2 on the browser context and use scale: 'device' in the screenshot call. A 1280 × 800 CSS-pixel viewport will produce a 2560 × 1600 pixel image. For a full-page image, also set fullPage: true.
The examples below use Playwright’s JavaScript API. The same context and screenshot options are available in Playwright’s other language bindings, but this guide focuses on JavaScript because that is the language in the title. Page screenshot API · Browser context API
1. Capture a viewport at 2×
Here is a complete Node.js example using Playwright’s Chromium browser. Install Playwright, save this as screenshot.js, then run it with Node.js:
npm install playwright
npx playwright install chromium
// screenshot.js
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
try {
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
deviceScaleFactor: 2,
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle' });
await page.screenshot({ path: 'page-2x.png', scale: 'device' });
await context.close();
} finally {
await browser.close();
}
})();
The viewport dimensions are CSS pixels. At device scale factor 2, device-pixel output doubles both dimensions. The example’s expected output is 2560 × 1600 pixels. This follows from the documented pixel mapping; it is not a promise about file size, which depends on the page and image format.
2. Understand device scale and screenshot scale
There are two settings involved:
deviceScaleFactorsets the browser context’s device pixel ratio. It defaults to1.scaleonpage.screenshot()chooses whether output pixels represent CSS pixels or device pixels.
| Setting | Effect | Typical use |
|---|---|---|
deviceScaleFactor: 2 and scale: 'device' |
Two output pixels per CSS pixel on each axis | 2× assets or high-density captures |
deviceScaleFactor: 2 and scale: 'css' |
One output pixel per CSS pixel | Keep output dimensions at CSS size |
deviceScaleFactor: 1 and scale: 'device' |
One output pixel per CSS pixel | Ordinary 1× capture |
Set both options explicitly when you need a deliberate 2× result. Setting only scale: 'device' does not make a context with device scale factor 1 produce 2× pixels. Setting only the context factor leaves the intended output scale implicit. Playwright documents device as the screenshot scale default, but spelling it out makes the code’s purpose clear. See the screenshot options and context options.
3. Capture the full scrollable page at 2×
fullPage: true captures beyond the viewport to include the page’s full scrollable height. It changes the image’s extent, not its pixel density. Keep the same context and device-scale settings:
await page.screenshot({
path: 'full-page-2x.png',
fullPage: true,
scale: 'device',
});
The output width is twice the CSS width. The output height is twice the page’s captured CSS height, which varies with the page. Very long pages can produce large images and take longer to capture. Pages that load content only after scrolling may also need a deliberate scroll-and-wait step before capture; fullPage alone does not guarantee that every lazy-loaded asset has finished loading.
4. Capture one element at 2×
For a component or card rather than the whole viewport, take a locator screenshot. The browser context’s device scale factor still applies, and explicitly selecting device scale requests device-pixel output:
const card = page.locator('[data-testid="product-card"]');
await card.screenshot({
path: 'product-card-2x.png',
scale: 'device',
});
Use a selector that identifies one element reliably. If it matches multiple elements, make the locator unique with a more specific selector or an appropriate locator filter. Locator screenshots capture the element’s bounds; they do not turn the capture into a full-page screenshot. See the Playwright screenshots guide.
5. Choose output dimensions and verify the file
For a viewport screenshot, calculate expected dimensions from the CSS viewport:
output width = viewport CSS width × deviceScaleFactor
output height = viewport CSS height × deviceScaleFactor
At a 1280 × 800 viewport and a factor of 2, expect 2560 × 1600 pixels. For an element screenshot, use the element’s captured CSS bounds. For a full-page screenshot, the captured page height determines the output height.
Check the actual image dimensions when a downstream system requires an exact size. A 2× capture describes pixel density relative to CSS dimensions; it does not guarantee a particular encoded file size. PNG, JPEG, and WebP compression, page content, and image complexity affect bytes on disk.
6. Make captures stable for visual comparisons
High resolution and repeatable output are separate concerns. Increasing device scale gives more output pixels, but does not make browser rendering deterministic. Playwright notes that output can vary with the operating system, browser version, browser settings, hardware, power source, and headless mode. For screenshot comparisons:
- Use the same Playwright and browser versions for the baseline and current capture.
- Run both captures in a consistent operating system and rendering environment.
- Keep the viewport, device scale factor, screenshot scale, and page state the same.
- Wait for the specific content your page needs before taking the screenshot.
- Use Playwright Test screenshot assertions when the goal is visual regression testing; consult its screenshot comparison guidance.
Even with a stable setup, dynamic content such as timestamps, rotating banners, or remote data can change between runs. Control or mask those regions as appropriate for your comparison workflow.
7. Troubleshoot unexpected dimensions or output
| Symptom | Likely cause | Fix |
|---|---|---|
| Image is the same pixel size as the CSS viewport | The context uses a device scale factor of 1, or the screenshot uses CSS scale. | Set deviceScaleFactor: 2 on the context and scale: 'device' on the capture. |
| Image is 2× when you wanted CSS-sized output | The screenshot uses device-pixel output with a factor of 2. | Use scale: 'css' to produce one output pixel per CSS pixel. |
| Full-page capture is unexpectedly tall or large | fullPage: true includes the entire scrollable page, and 2× output doubles each dimension. |
Capture the viewport or a specific element, or reduce the viewport/page content if appropriate. |
| Images or below-the-fold content are missing | Content may be lazy-loaded or may not have finished loading when the screenshot ran. | Wait for a relevant locator or load condition; for lazy content, scroll through the page and wait for assets before capturing. |
| Screenshot differs between machines | Rendering environment or page state differs. | Keep browser, operating system, viewport, settings, and content state consistent as described above. |
| Capture fails before writing the file | Navigation, selector resolution, browser installation, or a page error may have failed. | Check the first thrown error, confirm Chromium is installed with npx playwright install chromium, verify the URL and selector, and increase the relevant navigation or locator timeout if the page needs more time. |
8. Performance, reliability, and cost
A 2× capture contains four times as many pixels as a 1× capture of the same CSS width and height: both width and height double. This is arithmetic, not a benchmark. More pixels can mean more image processing, memory use, and output bytes, though the exact overhead depends on the page and encoder. Full-page captures multiply the captured area further, so use viewport or element screenshots when those are all you need.
Playwright itself is a browser automation library; the setup runs in your environment and has no per-screenshot API charge from Playwright. You are responsible for the runtime and infrastructure where the browser runs. Navigation and rendering reliability depend on the target page, your waits, network conditions, and the browser environment. Avoid treating networkidle as universal proof that a page’s application content is ready; waiting for a page-specific locator is often a clearer readiness condition.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. A single GET request returns a PNG, JPEG, WebP, or PDF. Its screenshot options include a device preset or custom viewport and retina scale. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
With Python:
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)
With Node.js:
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 import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture. 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 lets Claude, Cursor, and other MCP clients 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. Create a free ScreenshotNeo account.
FAQ
Does 2× mean the browser viewport is twice as wide?
No. Keep the viewport at the CSS dimensions you want to render. The device scale factor determines how many output pixels represent each CSS pixel.
Can I use a device scale factor higher than 2?
Yes. The factor controls the relationship between CSS and device pixels. Higher values create larger pixel dimensions and can increase capture memory and file size.
Does 2× improve the page’s visual quality?
It produces more output pixels for the same CSS-sized capture. It cannot add detail that the page’s assets or browser rendering do not provide.
Will a full-page screenshot include content that appears only after scrolling?
Not necessarily. Some pages load content or images in response to scrolling. Scroll and wait for that content when it must appear in the result.


