Use Selenium WebDriver to operate the video player in a real browser, then assert observable media state—such as playback starting, time advancing, pausing, or seeking—rather than treating page load or a fixed delay as proof that the video works. The examples below use Python with Selenium 4 and a native HTML <video> element; adapt selectors and expected behavior to your player.
What a reliable Selenium video test should prove
A browser video test is most useful when it checks an actual user flow and its resulting media state. For example, click the player’s Play control and confirm the media enters playback and its time advances. A successful navigation or a visible player alone does not establish that playback works.
Selenium WebDriver drives a browser natively, so it can exercise page controls while JavaScript inspects the HTML media element. The browser’s media state is asynchronous: metadata, data for a frame, playback, buffering, seeking, and errors may occur at different times. Use waits for the condition your test needs, not a guessed sleep duration.
Prepare a deterministic test page
Prefer a controlled fixture
Use a test page with a known video asset and stable player markup when possible. Public video services and production streams introduce external variables such as changing content, network delivery, consent overlays, and provider-specific controls. A fixture makes it easier to distinguish a player regression from an unavailable third-party service.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →#1 Best Overall
The example assumes a native video element with id video and a button with id play. Replace these selectors with the real page’s accessible controls or stable test selectors. If the player is custom, its UI may wrap a native video element; inspect the page and identify both the user-facing control and the underlying media element, if one exists.
Install Selenium and start a browser
Install the Python binding with python -m pip install selenium. Selenium Manager handles browser and driver management by default in current Selenium documentation, although browser installation, permissions, and organization-specific setup can still affect your environment. See the Selenium documentation for language bindings and current setup guidance.
Runnable Python example: play, pause, seek, and inspect failures
Save this as test_video.py. Set VIDEO_TEST_URL to a test page you control. The test waits for media conditions with explicit waits, clicks the page’s Play control, verifies playback progresses, then checks pause and seek behavior. It gathers browser and media details when an assertion fails.
import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
VIDEO_URL = os.environ.get("VIDEO_TEST_URL", "http://localhost:8000/video-test.html")
def media_snapshot(driver):
return driver.execute_script("""
const v = document.querySelector('#video');
if (!v) return {present: false};
return {
present: true,
currentSrc: v.currentSrc,
currentTime: v.currentTime,
duration: v.duration,
paused: v.paused,
ended: v.ended,
readyState: v.readyState,
networkState: v.networkState,
error: v.error ? {code: v.error.code, message: v.error.message} : null
};
""")
def wait_for_media(driver, predicate, timeout=20):
return WebDriverWait(driver, timeout).until(
lambda d: predicate(media_snapshot(d))
)
def test_video_play_pause_seek():
options = webdriver.ChromeOptions()
# Headless mode is convenient in CI; omit this to watch the browser locally.
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
try:
driver.get(VIDEO_URL)
wait = WebDriverWait(driver, 20)
video = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#video")))
wait_for_media(driver, lambda m: m["present"] and m["readyState"] >= 1)
# Exercise the page UI as a user would. The click may be necessary to
# satisfy browser autoplay policy.
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#play"))).click()
# Wait for playback to start, then prove that the playback position advances.
wait_for_media(driver, lambda m: not m["paused"] and m["currentTime"] > 0)
start_time = media_snapshot(driver)["currentTime"]
WebDriverWait(driver, 10).until(
lambda d: media_snapshot(d)["currentTime"] > start_time
)
# Pause through the native video element for this state check.
# For a UI test of the pause button, click that page control instead.
driver.execute_script("document.querySelector('#video').pause()")
wait_for_media(driver, lambda m: m["paused"])
# Seek only when duration is finite and long enough for a meaningful target.
duration = media_snapshot(driver)["duration"]
if duration and duration != float("inf") and duration > 3:
target = min(2.0, duration - 0.5)
driver.execute_script(
"const v = document.querySelector('#video'); v.currentTime = arguments[0];",
target,
)
WebDriverWait(driver, 10).until(
lambda d: abs(media_snapshot(d)["currentTime"] - target) < 0.75
)
except Exception:
print("URL:", VIDEO_URL)
print("Browser:", driver.capabilities.get("browserName"),
driver.capabilities.get("browserVersion"))
print("Media:", media_snapshot(driver))
try:
print("Browser logs:", driver.get_log("browser"))
except Exception as log_error:
print("Browser log retrieval unavailable:", log_error)
raise
finally:
driver.quit()
if __name__ == "__main__":
test_video_play_pause_seek()
Run it with VIDEO_TEST_URL=http://localhost:8000/video-test.html python test_video.py (PowerShell: $env:VIDEO_TEST_URL="http://localhost:8000/video-test.html"; python test_video.py). The fixture must provide the selectors used above. For a test that focuses only on the UI, use the page’s pause and seek controls rather than calling the media element directly; the script-driven pause and seek here isolate state assertions from provider-specific button markup.
Rank #2
Choose assertions that match the scenario
Readiness is a starting condition, not a full-play guarantee
HTMLMediaElement.readyState ranges from HAVE_NOTHING (no media information) to HAVE_ENOUGH_DATA (the browser estimates enough data is available to play through without interruption). A readiness threshold can help establish a test precondition, but it cannot prove that a long video or live stream will play without buffering.
For a first-frame check, wait for loadeddata or a suitable readiness state. For an interaction test, verify the action’s outcome as well: a playing event or paused === false, followed by an advancing currentTime. An event listener can make event-specific assertions:
result = driver.execute_async_script("""
const done = arguments[arguments.length - 1];
const v = document.querySelector('#video');
const timer = setTimeout(() => done({ok: false, reason: 'timeout'}), 10000);
v.addEventListener('playing', () => {
clearTimeout(timer);
done({ok: true, currentTime: v.currentTime});
}, {once: true});
""")
assert result["ok"], result
Register the listener before clicking Play so the test cannot miss an event that fires quickly. Also handle a media error or rejected play request instead of waiting until a generic timeout.
Test the failure mode you intend to protect
- Playback smoke test: after a user-like Play action, wait for playback state and a time increase.
- Pause test: activate the page’s pause control and verify
pausedbecomes true. - Seek test: seek to a valid target, wait for the operation to complete (commonly the
seekedevent), and check that the final position is near the target. - Error-path test: provide an unsupported or deliberately unavailable source and assert the expected error UI or media error state.
- Completion test: for a short controlled clip, verify the
endedstate; do not make a long production video play to completion merely to test the Play button.
Useful media events include loadeddata, playing, pause, seeking, seeked, waiting, stalled, ended, and error. Choose the event and state that correspond to the behavior under test. A live stream may have no finite duration and may not produce an ended event; avoid finite-duration assertions for that case.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Rank #3
Handle autoplay policy and rejected play requests
HTMLMediaElement.play() returns a Promise. It can resolve after a delay or reject, including when browser autoplay policy blocks script-initiated playback or when media cannot be played. Do not treat calling play() as proof that playback began.
When validating the site’s Play control, click it through Selenium and then wait for the resulting playback state. For a test specifically targeting script playback, capture the Promise result in page JavaScript:
play_result = driver.execute_async_script("""
const done = arguments[arguments.length - 1];
const v = document.querySelector('#video');
v.play().then(
() => done({started: true}),
error => done({started: false, name: error.name, message: error.message})
);
""")
If the promise rejects, report the error and test setup rather than converting the rejection into a pass. A rejected play request caused by autoplay policy is different from a media source or decode error; the test should reflect which behavior it is designed to verify.
Capture diagnostics that make failures actionable
On failure, retain the browser name and version, driver/browser setup, page URL, media snapshot, and any available console or runtime errors. The example prints currentSrc, currentTime, duration, readyState, paused/ended flags, network state, and the media error object. Add relevant network request details if the failure might be caused by asset delivery.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #4
Selenium WebDriver BiDi can stream browser events such as network requests, console messages, and JavaScript errors. Selenium documents BiDi as an evolving implementation and a cross-browser replacement for CDP; check the current support status for your Selenium binding and target browser before making a test depend on it. See Selenium WebDriver BiDi documentation.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Run locally first, then scale the browser matrix
Local WebDriver
A local browser session is a straightforward place to build and debug the test. It has less infrastructure overhead, but covers only the browser and environment you run locally unless you add more sessions.
Selenium Grid
Use Selenium Grid when you need distributed execution across machines or a browser/operating-system matrix. Grid’s stated purpose includes distributing tests across several machines and environments. It adds setup and operational work, so use it when environment breadth or parallel execution matters. See Selenium Grid documentation.
Neither local WebDriver nor Grid alone establishes perceptual video or audio quality, codec behavior on every hardware configuration, or sustained streaming quality under realistic network conditions. Add specialized media, visual, or network testing when those are requirements.
Best Value
Troubleshooting common failures
- Element not found: the test may be targeting the wrong selector, the player may be inside an iframe, or the page may not have rendered it yet. Wait for the correct frame and stable element, then confirm the selector against the actual markup.
- Play click has no effect: check whether an overlay intercepts the click, whether the control is disabled, and whether the browser reports a rejected
play()Promise. Prefer a real user-like click when testing the UI. - Playback starts but time does not advance: inspect
paused,readyState,currentSrc, and the media error; also check forwaitingorstalledand relevant network failures. - Seek assertion times out: ensure the target is within a finite duration and seekable range. For streams or sparse media, a requested time may not be immediately available; wait for
seekedand validate a realistic tolerance. - Works locally, fails in CI: compare browser versions, headless versus headed behavior, media availability, permissions, and network access. Preserve browser logs and media state to separate setup failures from application regressions.
- Browser logs are unavailable: log retrieval depends on browser and driver support/configuration. Treat it as supplementary diagnostics, not a required assertion; retain Selenium exceptions and media state regardless.
- Embedded player behaves differently: switch into the relevant iframe before locating controls. Provider APIs, sandboxing, and cross-origin restrictions differ; there is no single Selenium interaction method for every third-party player.
Or skip the browser setup
If your immediate need is a screenshot of a video page rather than an interactive playback assertion, ScreenshotNeo offers a one-request screenshot API. It does not replace Selenium tests for playback, seeking, buffering, or media-state verification.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
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}`);
See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before the shot, along with known newsletter popups and chat widgets; those cleanup steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents use screenshot and PDF tools. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.
Sign up for 1,000 free screenshots a month, with no card required.
Frequently Asked Questions
Can Selenium test a video inside an iframe?
Yes, when the frame can be accessed by the browser session: switch into the relevant iframe before locating its controls. Provider APIs and cross-origin restrictions vary, so the appropriate interaction depends on that player.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesDoes Selenium prove video quality or uninterrupted streaming?
No. A browser automation test can check page behavior and media state, but perceptual audio/video quality, broad codec coverage, and sustained streaming under realistic network conditions need additional testing.
Quick Recap
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.




