Missing captions for videos
video-caption
- WCAG success criterion
- 1.2.2 (level A)
- Outcome class
- Hint only. An automated check that by design reports review hints only: its findings are marked for manual review, never as confirmed violations.
- Area
- Accessibility, Content & Alternatives
- Default severity
- high
- axe-core rule
video-caption
Why we flag this
Deaf or hard-of-hearing users cannot perceive spoken content.
Missing track element for captions.
What the rule checks
Scope. Pages with a rendered native <video> or a known video-platform embed iframe.
Expectation. Pass (positive signal, no finding) only when every rendered <video> has a <track kind="captions"|"subtitles"> whose src resolves same-origin as a caption file (.vtt/.srt or a vtt content type). Anything less — no caption track, a track that does not resolve or is cross-origin, only description/chapter tracks, more caption tracks than the probe budget of 10 checks, or third-party embeds — is one page-level UNTESTED note: captions may exist in ways the tool cannot see (open captions, platform players), so never a violation. A page without rendered video is not applicable; a video in a hidden panel is not presented in this state.
Source. WCAG 2.2 SC 1.2.2 Captions (Prerecorded) (H95, G87, F8); HTML §4.8.11.11 track
Detection: page; needs dom, network.
Failing example
The check flags this for review. Corpus case content_video_dynamic. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Video added after load</title>
<style>
nav a, .skip-link { display: inline-block; min-width: 44px; min-height: 44px; }
</style>
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>
<header>
<p>City Library</p>
<nav aria-label="Main"><a href="/" aria-current="page">Home</a> <a href="/catalogue">Catalogue</a> <a href="/visit">Visit</a></nav>
</header>
<main id="main">
<h1>Featured video</h1>
<div id="player-slot"></div>
<script>
document.getElementById('player-slot').innerHTML =
'<video id="featured" controls width="320" height="180" src="/featured.mp4"></video>';
</script>
</main>
<footer><p>City Library, 1 Market Square</p></footer>
</body>
</html>Passing example
The check passes here and reports nothing. Corpus case content_video_captioned. The page may contain further findings for other rules.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Library tour video</title>
<style>
nav a, .skip-link { display: inline-block; min-width: 44px; min-height: 44px; }
</style>
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>
<header>
<p>City Library</p>
<nav aria-label="Main"><a href="/" aria-current="page">Home</a> <a href="/catalogue">Catalogue</a> <a href="/visit">Visit</a></nav>
</header>
<main id="main">
<h1>Library tour</h1>
<video id="tour" controls width="320" height="180" src="/tour.mp4">
<track kind="captions" src="/tour.en.vtt" srclang="en" label="English">
</video>
<video id="workshop" controls width="320" height="180" src="/workshop.mp4">
<track kind="subtitles" src="/workshop.de.srt" srclang="de" label="Deutsch">
<track kind="chapters" src="/workshop.chapters.html" srclang="en">
</video>
</main>
<footer><p>City Library, 1 Market Square</p></footer>
</body>
</html>This page is generated from the rule catalogue and the rule contracts; see therule overview for how the outcome classes are derived.