How to Get the Screen Size in Playwright
Learn when to use Playwright's viewportSize(), window.screen, context emulation, and setViewportSize() with runnable examples and fixes.
In Playwright, “screen size” can mean two different things:
- Viewport size: the page’s visible rendering area. Read it with
page.viewportSize(). - Screen size: the dimensions exposed to page JavaScript through
window.screen. Read it withpage.evaluate().
Use the first when you are asserting Playwright’s configured viewport. Use the second when your application reads the browser Screen API.
1. Get the configured viewport
page.viewportSize() returns an object with width and height, measured in CSS pixels. It returns null when no viewport is configured.
import { test, expect } from '@playwright/test';
test('reads the viewport size', async ({ page }) => {
console.log(page.viewportSize());
// { width: 1280, height: 720 } with the documented default
});
The value describes the emulated page viewport, not the operating system monitor or the browser window’s outer dimensions.
2. Get window.screen dimensions
Evaluate the Screen API inside the page when application code depends on window.screen.width or window.screen.height.
const screen = await page.evaluate(() => ({
width: window.screen.width,
height: window.screen.height,
availWidth: window.screen.availWidth,
availHeight: window.screen.availHeight,
}));
console.log(screen);
Playwright can emulate consistent screen dimensions with the browser context’s screen option. The option is used when a viewport is set.
3. Configure viewport and screen dimensions
Set both values when a test must control rendering and the values exposed to page JavaScript.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
screen: { width: 1440, height: 900 },
});
const page = await context.newPage();
await page.goto('https://example.com');
console.log('viewport:', page.viewportSize());
console.log('screen:', await page.evaluate(() => ({
width: window.screen.width,
height: window.screen.height,
})));
await browser.close();
Keep the two settings separate in your assertions. A page can render at one viewport while reporting another screen size.
4. Resize a page with setViewportSize()
For a single page, call page.setViewportSize({ width, height }). Set it before navigation when the site chooses its layout during startup.
await page.setViewportSize({ width: 390, height: 844 });
await page.goto('https://example.com');
expect(page.viewportSize()).toEqual({ width: 390, height: 844 });
Changing the viewport also resets the screen size. If you need independent, repeatable viewport and screen values, create a context with both viewport and screen instead.
5. Configure Playwright Test projects
Set a project-wide viewport in playwright.config.ts:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
viewport: { width: 1280, height: 800 },
},
});
The documented Playwright Test default viewport is 1280 × 720. Setting viewport: null opts out of consistent viewport emulation and makes the size depend on the host window, which is non-deterministic for automated tests.
You can override the setting per test:
test.use({ viewport: { width: 375, height: 812 } });
test('mobile layout', async ({ page }) => {
await page.goto('https://example.com');
await expect(page.locator('nav')).toBeHidden();
});
6. Distinguish viewport, screen, and device scale factor
| Value | How to read or set it | What it controls |
|---|---|---|
| Viewport | page.viewportSize() or context viewport |
Visible CSS rendering area |
| Screen | window.screen or context screen |
Screen dimensions exposed to page JavaScript |
| Device scale factor | Context deviceScaleFactor or a device descriptor |
Device-pixel density; it is not a width or height |
Device descriptors can configure several of these properties together. If a test depends on exact values, inspect the selected descriptor and override the viewport explicitly.
7. Complete runnable example
import { chromium } from 'playwright';
async function main() {
const browser = await chromium.launch();
const context = await browser.newContext({
viewport: { width: 1280, height: 800 },
screen: { width: 1440, height: 900 },
deviceScaleFactor: 1,
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
const viewport = page.viewportSize();
const screen = await page.evaluate(() => ({
width: window.screen.width,
height: window.screen.height,
}));
console.log(JSON.stringify({ viewport, screen }, null, 2));
await browser.close();
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
8. Troubleshooting
page.viewportSize() returns null
Cause: the context was created with viewport: null, or no emulated viewport is active.
Fix: provide an explicit viewport when creating the context, or handle the null result before reading width and height.
The screen value is not the viewport value
Cause: viewport and Screen API dimensions are separate settings.
Fix: assert the value your application actually uses. Read page.viewportSize() for Playwright configuration and evaluate window.screen for page-side behavior.
Screen dimensions change after resizing
Cause: page.setViewportSize() resets screen size.
Fix: configure viewport and screen together at context creation, then avoid resizing that page when the screen emulation must remain fixed.
Tests pass locally but fail in CI
Cause: viewport: null uses the host window size, which differs between machines.
Fix: set explicit dimensions in the test configuration and avoid assertions based on the physical monitor.
The layout is wrong on the first render
Cause: dimensions were changed after navigation, while the application selected its layout during startup.
Fix: set the context or page viewport before goto().
Device emulation gives unexpected values
Cause: a device descriptor may set viewport, screen, scale factor, user agent, and touch behavior together.
Fix: log page.viewportSize() and the evaluated Screen API values, then override the properties your test requires.
9. Reliability, performance, and cost notes
- Fixed context dimensions make screenshots and responsive assertions reproducible across machines.
- Read dimensions once per test unless the page intentionally changes them; repeated evaluations add small but unnecessary protocol work.
- Use CSS pixels for layout assertions. Device scale factor affects raster output, not the CSS viewport dimensions.
- For full-page screenshots, viewport height controls the initial rendering area while the document’s scroll height controls the final image height.
- Keep viewport, screen, and scale-factor assertions independent so a failure identifies the misconfigured setting.
10. Or skip the browser setup
If your goal is to produce a screenshot at a known viewport rather than run browser assertions, ScreenshotNeo provides a screenshot API. Its options include any viewport, 12 device presets, retina scale, full-page capture, element capture, custom CSS and JavaScript, waits, and PDF output. Read the ScreenshotNeo API documentation for the complete parameter list.
cURL:
curl -G 'https://api.screenshotneo.com/v1/shot' -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get(
'https://api.screenshotneo.com/v1/shot',
params={'access_key': 'YOUR_API_KEY', 'url': 'https://stripe.com'},
timeout=90,
)
r.raise_for_status()
open('shot.webp', 'wb').write(r.content)
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 failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));
Before capture, ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account and get 1,000 screenshots each month with no card.
11. FAQ
Does screen size mean browser window size?
No. Playwright exposes the emulated viewport and the page’s Screen API. Neither is a reliable measurement of the host operating system’s outer browser window.
What is the default Playwright viewport?
Playwright Test documents a default of 1280 × 720 pixels.
Can I set screen without setting viewport?
The BrowserContext screen option is used when a viewport is set. Configure both for deterministic emulation.
Should responsive tests use screen or viewport?
Use viewport for CSS layout and rendering behavior. Use Screen API values only when the application explicitly reads window.screen.
Why does device scale factor not change viewportSize()?
Scale factor controls device-pixel density. The viewport remains measured in CSS pixels.


