October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk9 min

How to Automate Video Testing With Selenium

Use Selenium WebDriver to drive a real video player and verify playback, pause, seek, readiness, and failure states without relying on arbitrary sleeps.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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

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.

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

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 paused becomes true.
  • Seek test: seek to a valid target, wait for the operation to complete (commonly the seeked event), 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 ended state; 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.

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

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.

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

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.Support on Ko-Fi

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.

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

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 for waiting or stalled and 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 seeked and 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.

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

Does 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.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.