Screen configuration for automation and testing with Chrome Headless

Peter Kvitek
Peter Kvitek

We're happy to announce that both Chrome Headless Mode (chrome --headless) and Headless Shell (chrome-headless-shell) now use a fully configurable virtual headless screen which is independent of physical displays attached to the system Chrome is running on. Initial headless screen configuration can be specified using the --screen-info command line switch. This switch defines properties like origin, size, scale factor, orientation, and work area for each display.

While Chrome is running in headless mode, virtual headless screens can be added and removed using Chrome DevTools Protocol (CDP) commands Emulation.addScreen and Emulation.removeScreen.

These new Headless Chrome capabilities are fully supported by Puppeteer, letting you automate complex, real-world display scenarios that were previously hard to test. Whether you need to verify a kiosk application running full-screen on a high-resolution 3K display, orchestrate multi-window workflows across a dual-monitor setup, or ensure your UI adapts gracefully when a user suddenly disconnects a secondary screen, Headless Chrome and Puppeteer now have you covered.

Test static screen configurations

Use static screen configuration through the --screen-info switch to evaluate your website within a static screen environment. The following are a list of common scenarios:

  • Test behavior with --start-maximized and --start-fullscreen switches, considering screen work area and scale factor (e.g., kiosk mode).
  • Evaluate element.requestFullscreen() and document.exitFullscreen() behavior across various screen sizes and in multiscreen configurations.
  • Observe split-screen behavior when a window spans multiple screens or is moved between them.
  • Verify the handling of diverse display settings, including scaling, resolutions, and high-DPI displays.
  • Assess the opening of windows or pop-ups on primary and secondary screens.

Dual screen configuration

The following Puppeteer script configures Chrome to run in a dual-screen configuration using the --screen-info switch. The primary 800x600 screen is configured in a landscape orientation and the secondary 600x800 screen, positioned directly to the right of the primary screen, is in a portrait orientation.

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  args: ['--screen-info={800x600 label=1st}{600x800 label=2nd}'],
});

const screens = await browser.screens();
const screenInfos = screens.map(
    s =>  `Screen [${s.id}]`

+   ` ${s.left},${s.top} ${s.width}x${s.height}`
+   ` label='${s.label}'`
+   ` isPrimary=${s.isPrimary}`
+   ` isExtended=${s.isExtended}`
+   ` isInternal=${s.isInternal}`
+   ` colorDepth=${s.colorDepth}`
+   ` devicePixelRatio=${s.devicePixelRatio}`
+   ` avail=${s.availLeft},${s.availTop} ${s.availWidth}x${s.availHeight}`
+   ` orientation.type=${s.orientation.type}`
+   ` orientation.angle=${s.orientation.angle}`
);

console.log(`Number of screens: ${screens.length}\n` + screenInfos.join('\n'));

await browser.close();

Output:

Number of screens: 2
Screen [1] 0,0 800x600 label='1st' isPrimary=true isExtended=true isInternal=false colorDepth=24 devicePixelRatio=1 avail=0,0 800x600 orientation.type=landscapePrimary orientation.angle=0
Screen [2] 800,0 600x800 label='2nd' isPrimary=false isExtended=true isInternal=false colorDepth=24 devicePixelRatio=1 avail=800,0 600x800 orientation.type=portraitPrimary orientation.angle=0

Test dynamic screen configurations

Dynamically configure your screen environment to test how your website reacts to unexpected monitor connections or disconnections, mirroring real-world user actions like connecting a notebook to a desktop monitor. These scenarios are emulated using CDP commands as Emulation.addScreen and Emulation.removeScreen. With these commands, you can do the following:

  • Verify that connecting a new monitor enables web pages to open new windows and pop-ups within the new monitor's work area.
  • Ensure that when a monitor is disconnected while a web page is active, its window size and position adapt gracefully to the remaining displays.

Open and maximize the window on a new screen

The following Puppeteer script opens a window at the default position on a 800x600 screen, then moves and maximizes the window to a newly created screen. It then restores the window to its normal state.

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  args: ['--screen-info={800x600}'],
});

async function logWindowBounds() {
  const bounds = await browser.getWindowBounds(windowId);
  console.log(`${bounds.left},${bounds.top}` +
     ` ${bounds.width}x${bounds.height}` +
     ` ${bounds.windowState}`);
}

const page = await browser.newPage({type: 'window'});
const windowId = await page.windowId();
await logWindowBounds();

const screenInfo = await browser.addScreen({
  left: 800,
  top: 0,
  width: 1600,
  height: 1200,
});

await browser.setWindowBounds(windowId, {
  left: screenInfo.left + 50,
  top: screenInfo.top + 50,
  width: screenInfo.width - 100,
  height: screenInfo.height - 100,
});
await logWindowBounds();

await browser.setWindowBounds(windowId, {windowState: 'maximized'});
await logWindowBounds();

await browser.setWindowBounds(windowId, {windowState: 'normal'});
await logWindowBounds();

await browser.close();

Output:

20,20 780x580 normal
850,50 1500x1100 normal
800,0 1600x1200 maximized
850,50 1500x1100 normal

More use cases, examples and availability

Find more code samples on pptr.dev. If you are encountering issues, let us know through Puppeteer's public bug tracker on GitHub.

Headless screen configuration functionality is available in stable Chrome releases starting from version 142.