Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Short answer: the official Selenium Docker recorder cannot capture a browser running in pure headless mode. Run Chrome or Chromium with the display-backed X server path (Xvfb) inside the container, then pair that browser container with one selenium/video FFmpeg container. Enable recording with se:recordVideo, persist /videos to the host, and collect the MP4 after the session closes. For Chrome/Chromium 127 and later, set SE_START_XVFB=true when using --headless=new; from Chrome 132, plain --headless selects that new mode too.

Why pure headless recording fails

There are two different meanings of “headless” in Docker discussions. A pure headless browser renders without a display server. A display-backed run starts an X server (normally Xvfb) in the container but still runs unattended, with no physical monitor. The SeleniumHQ Docker documentation states: “Video recording for headless browsers is not supported.” The official recorder captures the display-backed path, not the output of a pure headless browser process.

Therefore, adding an FFmpeg container does not make a pure headless session recordable. Keep the test unattended, but provide the virtual display that the recorder can read.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The recording architecture

The supported design has separate services:

  • Browser container: runs the Selenium session and its Xvfb display.
  • Video container: a matching selenium/video image running FFmpeg.
  • Shared network and session visibility: the recorder must reach the browser/Grid endpoints used by your topology.
  • Persistent storage: bind the recorder’s /videos directory (or the documented Grid assets directory) to the CI worker or an artifact volume.

Use one video container for each browser container. In parallel CI, do not point several recorders at an unplanned shared output path unless you also give every session a distinct file name.

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

Set up a browser and recorder pair

1. Prepare Docker and storage

Create a directory that will survive container removal and give the browser enough shared memory. The official examples use --shm-size='2g'; choose a value appropriate for your pages and concurrency.

mkdir -p videos
chmod 0775 videos
docker network create selenium-net

Pin a video image tag that you have validated instead of using latest. The official examples include selenium/video:ffmpeg-8.1-20260905.

2. Start the display-backed browser

Use the browser image and version that match your Selenium Grid deployment. The important settings are shared memory and an Xvfb display. For current Chrome images, set SE_START_XVFB=true whenever the browser is launched with --headless=new. Chrome/Chromium 132 and later use the new mode for plain --headless, so keep the variable enabled there as well.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
docker run -d 
  --name selenium-browser 
  --network selenium-net 
  --shm-size='2g' 
  -e SE_START_XVFB=true 
  selenium/standalone-chrome

Pin the browser image in real CI and keep its Chrome, Selenium and video-recorder versions under change control. If your deployment uses a Hub/Node or Dynamic Grid topology, start the browser node through that orchestration instead of this standalone example.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

3. Start the matching FFmpeg recorder

docker run -d 
  --name selenium-video 
  --network selenium-net 
  -v "$PWD/videos:/videos" 
  selenium/video:ffmpeg-8.1-20260905

The exact connection options differ between Standalone, Hub/Node and Dynamic Grid. In every topology, verify that the recorder can discover the browser session and that the pairing remains one-to-one. If your Grid example uses /opt/selenium/assets rather than /videos, bind-mount that documented assets directory and collect it as the CI artifact.

Request a recording from the WebDriver session

Add the Selenium vendor capabilities below when creating the session:

{
  "browserName": "chrome",
  "platformName": "linux",
  "se:recordVideo": true,
  "se:screenResolution": "1920x1080",
  "se:name": "checkout_regression"
}

What each capability controls

  • se:recordVideo: true asks the Grid/browser service to record the session.
  • se:screenResolution requests deterministic capture dimensions. Use it when pixel comparisons or stable review output matter.
  • se:name supplies a readable label. The Docker Selenium README describes sanitizing the value, replacing spaces with underscores, restricting characters, and enforcing a 255-character limit before the session identifier is appended.

Keep names short and unique for parallel jobs, for example checkout_chrome_linux_042. If your recorder writes a fixed filename, set SE_VIDEO_FILE_NAME distinctly or provide another per-session naming mechanism supported by your Grid deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Runnable Python example

The following test creates a recording-enabled Chrome session, performs a small workflow, and always quits the session so the recorder receives a close event.

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
# The container supplies Xvfb; do not add a pure-headless argument here.
options.set_capability('browserName', 'chrome')
options.set_capability('platformName', 'linux')
options.set_capability('se:recordVideo', True)
options.set_capability('se:screenResolution', '1920x1080')
options.set_capability('se:name', 'checkout_regression')

driver = webdriver.Remote(
    command_executor='http://localhost:4444/wd/hub',
    options=options,
)
try:
    driver.get('https://example.com')
    print(driver.title)
finally:
    driver.quit()

Point command_executor at the address exposed by your standalone server or Grid. If the browser is behind a Hub, use the Hub URL and ensure the video service is associated with the node that receives the session.

Make the MP4 survive CI cleanup

  1. Wait for the test process to call quit() even when an assertion fails; a finally block or test-fixture teardown is essential.
  2. Allow the recorder to observe session closure. Grid 4.41.0’s documented event-driven recorder starts on session-created and stops on session-closed, avoiding timer-based cutoffs.
  3. Collect the host directory mapped to /videos (or the Grid assets directory) after the recorder has stopped.
  4. Upload the MP4 as a CI artifact before the worker is destroyed. For longer retention, the official README also documents rclone-based uploads to S3/GCS-compatible storage; credentials, encryption, bucket policy and retention are your deployment decisions.

Or skip the browser setup

If you need a clean visual snapshot of a page or test state rather than a time-based session video, ScreenshotNeo makes a single HTTP request. It is a screenshot API and MCP server, not a replacement for Selenium video: use it when a still image or PDF is the artifact you actually need.

Its practical difference is that consent banners are accepted and more than 60 known consent platforms, newsletter popups and chat widgets are removed before capture. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing result. An MCP server lets Claude, Cursor and other MCP clients call take_screenshot, get_page_info and capture_pdf.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for all options, including full-page capture, element selectors, device presets, custom CSS and JavaScript, waits, request blocking, cookies, headers, geolocation, transparent backgrounds, resizing, caching, signed links, asynchronous jobs, webhooks and bulk capture.

Python:

import requests
r = requests.get('https://api.screenshotneo.com/v1/shot', params={'access_key': 'YOUR_API_KEY', 'url': 'https://stripe.com'}, timeout=90)
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}`);

There is a free allowance of 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing provides two months free, and every feature is included on every plan. Create a free ScreenshotNeo account.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting missing or empty videos

The file is empty or no file appears

  • Confirm the browser is not running in pure headless mode. The official recorder documents that mode as unsupported.
  • Check that Xvfb is running and that SE_START_XVFB=true is set for Chrome/Chromium 127+ with --headless=new, and for Chrome/Chromium 132+ where plain --headless selects the new mode.
  • Verify that the recorder can reach the browser/Grid session endpoint and that exactly one recorder is assigned to the browser.

The recording starts or stops at the wrong time

Ensure the test closes the WebDriver session and that the recorder sees the close event. On Grid 4.41.0, prefer the event-driven lifecycle over timer heuristics. A force-killed test process may leave no clean session-closed signal.

The host directory is empty

Inspect the container mount with docker inspect selenium-video, confirm that the host path is writable, and collect artifacts only after the recorder exits. In Grid examples that use /opt/selenium/assets, mounting only /videos will not retrieve those files.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Several jobs overwrite one another

Use a unique se:name for every session and configure SE_VIDEO_FILE_NAME or an equivalent per-session filename. Give parallel recorder containers separate output directories when possible.

Chrome fails before the test starts

Increase shared memory; the official examples use --shm-size='2g'. Also check that the Chrome mode and Xvfb setting agree. A container that starts Chrome in a new headless mode without the required X server can fail before any recording begins.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Plan CPU, storage and retention

Video is not free operationally. SeleniumHQ recommends estimating about one CPU for each video container and one CPU for each browser container. Multiply that estimate by your maximum parallel sessions, then reserve additional storage for the expected recording duration and resolution.

  • Record selectively: enable video for failed tests, nightly diagnostics or suites where visual timing matters.
  • Retain intentionally: keep failure artifacts longer than passing-run videos, and enforce a storage lifecycle in your CI or object store.
  • Measure your workload: page complexity, resolution and test duration affect CPU and file size; the one-CPU guidance is a planning estimate, not a guarantee.

Standalone, Hub/Node or Dynamic Grid?

The browser-plus-recorder rule remains the same, but wiring changes by topology. Standalone deployments keep the services close together. Hub/Node deployments must route the recorder to the node hosting the session. Dynamic Grid provisions browsers and needs a recorder alongside each browser allocation, with shared access to the session events and asset location.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In Dynamic Grid, set se:recordVideo to true in the requested capabilities. Add se:screenResolution for stable dimensions and se:name for readable artifact labels. Test the full lifecycle—including provisioning, session closure and artifact collection—before increasing parallelism.

Frequently Asked Questions

Can I record a Selenium session with Chrome’s pure --headless flag?

Not with the official Docker Selenium recorder. Use the display-backed Xvfb path instead; current Chrome versions require SE_START_XVFB=true for the new headless mode used by recording setups.

How many video containers do I need for parallel tests?

Plan on one selenium/video container per browser container, with distinct output names or directories for concurrent sessions.

Where should recordings be stored in CI?

Bind-mount /videos, or the documented Grid assets directory when that topology uses it, to a host path and upload the files after the recorder has stopped.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.