Playwright Screenshot Is Cut Off on an Ultra-Wide Monitor: Viewport Fix
Fix a cut-off Playwright screenshot by matching the CSS viewport, capture extent, and image scale to what you need.
If a Playwright screenshot is cut off, first identify what is missing. If the page is using the wrong responsive layout, set the intended CSS viewport before navigation. If content below the visible area is missing, use fullPage: true. If the layout looks correct but the image dimensions are unexpected, check screenshot scale. These options change different things.
The example below uses a 2560 × 1080 CSS-pixel viewport as an illustration. Choose dimensions that match the display size or layout your test needs; “ultra-wide” does not prescribe one universal viewport.
1. Set the viewport before navigation
For a repeatable wide layout, configure the viewport in your Playwright Test project or when creating the browser context. Setting it before navigation lets the site render against those dimensions from the start. Playwright documents both approaches in its emulation guide.
Playwright Test configuration in TypeScript
import { test } from '@playwright/test';
test.use({
viewport: { width: 2560, height: 1080 },
});
test('wide layout screenshot', async ({ page }) => {
await page.goto('https://example.com');
await page.screenshot({ path: 'wide.png' });
});
Put the setting in the relevant test file or project configuration so the test gets the same viewport every run. A project or context setting can override the viewport supplied by a device preset.
Browser context setup
Use a context when you want explicit control outside Playwright Test, or when you need to configure screen dimensions separately from viewport dimensions.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext({
viewport: { width: 2560, height: 1080 },
});
const page = await context.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'wide.png' });
await context.close();
await browser.close();
Resize a page that is already open
You can also resize a page with page.setViewportSize():
await page.setViewportSize({ width: 2560, height: 1080 });
await page.goto('https://example.com');
await page.screenshot({ path: 'wide.png' });
Playwright advises setting dimensions before navigation when a site may respond to its initial viewport. Its API also notes that setViewportSize() resets the screen size. If your app depends on screen and viewport being different, set both in browser.newContext() instead. See the Page API.
2. Choose the capture extent and pixel scale
Once the page is using the intended viewport, choose what the screenshot should contain. Viewport width controls responsive layout; it does not mean the screenshot automatically includes every part of the document.
| Option | What it controls | Use it when |
|---|---|---|
viewport: { width, height } |
CSS layout dimensions used by the page | The page renders at the wrong responsive breakpoint or width. |
fullPage: true |
Vertical capture extent | You need content below the visible viewport. It captures the full scrollable page; it does not widen the responsive layout. |
clip: { x, y, width, height } |
The screenshot rectangle | You need a defined region rather than the full viewport or page. |
scale: 'css' or 'device' |
Raster pixel density | The layout looks right but output pixel dimensions or file size are unexpected. |
Context screen and viewport |
Screen and viewport values independently | The app reads both and you need to control them separately. |
Full-page capture
await page.screenshot({
path: 'wide-full-page.png',
fullPage: true,
});
Without fullPage, page.screenshot() captures the currently visible viewport. A full-page capture extends the image vertically over the scrollable document. It does not fix a too-narrow viewport or horizontal overflow.
Capture a specific rectangle
await page.screenshot({
path: 'region.png',
clip: { x: 0, y: 0, width: 1800, height: 900 },
});
The clip rectangle selects an output region by its position and dimensions. It does not change the page’s CSS layout.
Choose CSS-pixel or device-pixel output
await page.screenshot({
path: 'wide-css-pixels.png',
scale: 'css',
});
With scale: 'css', each CSS pixel produces one image pixel. With scale: 'device', output pixels follow device pixels, so a high-DPI setting can make the image twice as large or larger in each dimension. The Page API documents device as the screenshot method’s default; check the documentation for the particular screenshot or assertion API you use, since defaults can differ.
Set screen and viewport separately
const context = await browser.newContext({
screen: { width: 2560, height: 1440 },
viewport: { width: 2560, height: 1080 },
});
Use this only when the distinction matters to the application. For finer control over both values, Playwright recommends setting them through the browser context.
3. Diagnose what “cut off” means
- The layout is narrower than intended. Check the configured viewport and set the required width in the test or context before navigating.
- Content below the fold is absent. Add
fullPage: true; the default capture is only the visible viewport. - The page layout is right, but the PNG dimensions are wrong. Check
scaleand whether the chosen API returns CSS-pixel or device-pixel output. - The page is clipped at its right edge even with a wide viewport. Inspect the page’s own horizontal overflow, fixed-width containers, and responsive CSS breakpoints. A screenshot setting cannot fix an application layout that overflows its viewport.
- Screen-dependent behavior differs from viewport-dependent behavior. Configure both
screenandviewportin the context, rather than relying onpage.setViewportSize(), which resets screen size.
For a useful debugging record, note the configured viewport, window.innerWidth, the document’s scroll width, browser and project, Playwright version, and the screenshot. These details help distinguish a capture boundary problem from CSS overflow or an environment-specific issue.
4. Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| The screenshot uses a tablet or desktop breakpoint unexpectedly. | The context kept its default or device-preset viewport. | Set an explicit viewport in the test or context and confirm it is applied to the page being captured. |
| The bottom of a long page is missing. | The screenshot only captured the visible viewport. | Use fullPage: true. |
| The output image is larger in pixels than expected. | Device-pixel scaling is increasing raster dimensions. | Use scale: 'css' if one image pixel per CSS pixel is the intended output. |
| Changing viewport also changes a screen-dependent result. | page.setViewportSize() resets screen size. |
Set screen and viewport on the browser context. |
| The screenshot remains cut off horizontally with the expected viewport. | The app may have horizontal overflow, a fixed-width region, or CSS rules that clip content. | Inspect the rendered layout and overflow at the configured width; the title alone cannot identify the app-specific cause. |
| Visual comparison screenshots differ between runs or machines. | Rendering can vary with host OS, browser version, settings, hardware, power source, and headless mode. | Generate and compare baselines in the same environment, as recommended in Playwright’s visual comparisons guide. |
5. Reliability, performance, and cost considerations
Use a fixed viewport for repeatable responsive tests, and keep the browser version and execution environment consistent when comparing image baselines. Playwright notes that rendering can vary with the host OS, browser version, settings, hardware, power source, and headless mode.
Full-page screenshots can be much taller than viewport screenshots because they include the scrollable document. Choose them when below-the-fold content is part of the requirement; use a viewport shot or clip when it is not. Device-pixel output can also increase image dimensions and file size, especially at high DPI. Select the smallest capture extent and scale that preserve the details you need.
The cited Playwright guidance does not specify a universal runtime or cost for these capture choices. Actual time and storage depend on the page, capture dimensions, and environment. For hosted screenshot API costs, check the provider’s current pricing and billing rules.
6. Or skip the browser setup
If you need a screenshot without managing a Playwright browser, ScreenshotNeo takes a screenshot through one GET request and supports PNG, JPEG, WebP, or PDF. Its API supports viewport dimensions, full-page capture, device presets, retina scale, element capture, and other capture controls. 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://example.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo removes cookie banners, popups, and chat widgets before capture. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.
FAQ
Does an ultra-wide monitor automatically set Playwright’s viewport?
No. Set the viewport dimensions your test requires in the test configuration or browser context; the physical monitor does not define the emulated page viewport.
Will fullPage: true fix a narrow layout?
No. It captures more of the document vertically. Set the viewport width to change the responsive layout.
Should I use CSS scale or device scale?
Use CSS scale when you want one output pixel per CSS pixel. Use device scale when you need device-pixel detail and accept larger output dimensions.
Why can screenshots differ across machines?
Browser rendering can vary by operating system, browser version, settings, hardware, power source, and headless mode. Keep the comparison environment consistent.


