Xvfb: practical guide, and how to get real GPU rendering
Xvfb (X virtual framebuffer) is an X server that draws into memory instead of onto a screen. It is the classic way to run a browser, a graphical application or an E2E test suite on a Linux server with no display. This guide covers the essentials, then the limitation most tutorials leave out: Xvfb does not use the GPU.
Get started in one line
sudo apt install xvfb # Debian / Ubuntu
xvfb-run -a -s "-screen 0 1920x1080x24" npx playwright test
-aautomatically picks a free display number (handy for parallel CI);-screen 0 1920x1080x24sets the resolution and color depth, so screenshots are identical from one run to the next.
To keep a display running in the background:
Xvfb :99 -screen 0 1920x1080x24 &
export DISPLAY=:99
The catch: Xvfb renders on the CPU
Xvfb has no access to the GPU. Any OpenGL application running on it is
rendered by the CPU, using Mesa’s llvmpipe software driver:
$ xvfb-run -a glxinfo -B | grep renderer
OpenGL renderer string: llvmpipe (LLVM 19.1.7, 256 bits)
With Chrome and Chromium it is even more obvious. Under Xvfb with default
settings, WebGL is simply disabled; in --headless mode with default
settings, Chrome uses SwiftShader, a GPU emulated on the CPU. On a 1080p WebGL
test, that gives roughly 13 frames/s.
Make Chrome use the GPU, with or without Xvfb
Chrome can render directly on the GPU through ANGLE, bypassing the X server. You just have to ask:
chromium --headless=new --use-angle=vulkan --ignore-gpu-blocklist ...
Measured on 2026-10-29 on a Linux GPU server (Intel UHD 770, 4 vCPU, Chromium 156, same 1080p WebGL shader):
| Configuration | WebGL renderer | Frames/s |
|---|---|---|
--headless=new alone | SwiftShader (CPU) | 13 |
| Xvfb alone | WebGL disabled | — |
--headless=new --use-angle=vulkan | UHD 770 (Vulkan) | ~260 |
--headless=new --use-angle=gl-egl | UHD 770 (OpenGL ES 3.2) | ~230 |
Xvfb + --use-angle=vulkan | UHD 770 (Vulkan) | GPU, same as above |
About 20 times faster, and the CPU stays free for your tests. The same flags work under Xvfb, which is useful if you keep Xvfb for an extension or an application that needs a real X display.
The details (Playwright, Puppeteer, Selenium, Docker, verification) are in our guide Running Chrome with the GPU on a Linux server.
Do I still need Xvfb?
| Use case | Is Xvfb useful? |
|---|---|
| Recent Playwright / Puppeteer / Selenium | No: --headless=new is enough |
| Chrome extensions, headed-mode tests | Yes |
| X11 applications (Electron, Java Swing, legacy tools) | Yes |
| Accelerated OpenGL for a non-browser app | No: use display-less EGL, or VirtualGL |
FAQ
Why are my WebGL screenshots black or very slow under Xvfb?
Because Chrome disables WebGL (or falls back to SwiftShader) when it can’t find
a GPU. Add --use-angle=vulkan --ignore-gpu-blocklist.
Can I get hardware OpenGL under Xvfb?
Not directly: Xvfb can’t use the GPU. Applications that can render through EGL
(eglinfo -B -p surfaceless shows the card) or VirtualGL work around the
problem.
Is it reproducible in CI? Yes: resolution and depth are fixed by the command, and the GPU produces the same output on every run.
Try it on a Linux GPU server
Our servers have an Intel UHD 770 GPU available inside the VM, with Mesa,
Vulkan and VAAPI already installed: install Chromium (apt install chromium)
and the commands above work right away. From €14.99 excl. VAT/month, root
access, dedicated IPv6, optional k3s cluster.