What Is a Headless Browser Test?
A headless browser test runs a real browser without a visible window, driving a web app programmatically to verify it behaves correctly.
Testing a web app properly means running it in a real browser, with real rendering, real JavaScript, real layout. But CI servers have no screen. A headless browser solves this: it is a full browser engine running without a visible UI, controlled by code. It is how end-to-end and component tests run on servers.
What headless means
A headless browser is a normal browser, Chromium, Firefox, WebKit, running without rendering to a screen. Everything else is real: the DOM, the JavaScript engine, the network stack. Your test code drives it, clicking, typing, navigating, and reads back the result, all without a display.
Why CI uses headless mode
CI runners are headless machines with no graphical display. Running a browser headlessly lets full browser tests execute on those servers. Headless mode is also faster than rendering to a screen, which matters when a suite launches a browser many times.
A quick example
Test frameworks launch the browser in headless mode by default in CI, then drive it through the page.
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto("https://example.com");Common gotchas
- Missing system libraries the browser needs in a container.
- Differences between headless and headed rendering.
- Fonts and locales that differ from a developer machine.
- Timing flakiness from waiting on async UI.
Headless browser tests in CI
These tests are the backbone of E2E and visual testing in the pipeline, but they are also the most prone to transient timing flakes and need a consistent environment with the right browser dependencies. Running them in parallel on fast, isolated runners and auto-retrying transient failures keeps them dependable. Latchkey provides isolated runners and transient-flake retries that fit this well.
Key takeaways
- A headless browser is a real browser running with no visible UI.
- CI uses headless mode because runners have no display.
- These tests are powerful but prone to timing flakiness.