## TL;DR
Wrap your headed test command in xvfb-run so the browser gets a virtual display, and size that display explicitly. In containers, also disable the GPU and the sandbox, and give the container enough shared memory. If the browser still cannot start, the error is usually the display variable or missing system libraries, not your test.

## The query
```text
how to run headed browsers in CI with xvfb
```

## Use this when
- Tests must run headed: browser extensions, file download dialogs, or headed-only behavior
- The CI runner is Linux with no physical display
- The browser fails at startup with display or GPU errors

## Not for
- Headless test runs (you do not need xvfb at all)
- macOS or Windows CI runners (they have displays)
- Debugging a test failure that also happens headless

## Steps
1. Install xvfb in the CI image if it is missing. Most Linux images need an explicit install step for the xvfb package.
   Expected output: the package installed in CI setup logs.
2. Wrap the test command with xvfb-run. Use the auto server number flag so parallel jobs do not collide on the display number.
   Expected output: the test command prefixed with xvfb-run, and the browser launching without display errors.
3. Set the screen size explicitly. Pass a screen geometry like 1920x1080x24 so screenshots and layouts are deterministic.
   Expected output: a fixed screen size in the xvfb flags, with screenshots at the expected resolution.
4. Add container flags to the browser launch. Disable the GPU and the sandbox when running inside Docker, where neither is available.
   Expected output: browser launch flags including no-sandbox and disabled GPU, with clean startup logs.
5. Verify with a headed-only check. Run one test that requires headed mode, like an extension load or a download dialog, and confirm it passes.
   Expected output: a green run of a test that fails or skips in headless mode.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_NlXyvML1U5SnA87j457ZZQ
