WebVTT: The Complete Guide to Web Video Text Tracks
When you watch a video on YouTube, Netflix, or any modern website and enable captions, the text you see is almost certainly delivered in WebVTT format. WebVTT (Web Video Text Tracks) is the W3C standard for web subtitles and captions, designed from the ground up to integrate with the HTML5 <video> element and the <track> API. Unlike its predecessor SRT, WebVTT supports positioning, styling, chapter markers, and metadata — making it the most capable subtitle format for web delivery.
What Is WebVTT?
WebVTT (.vtt extension) is a plain text format for timed text tracks associated with HTML5 video. It handles:
- Subtitles: transcribed dialogue for viewers who can hear the audio
- Captions: subtitles plus sound effects and speaker identification for deaf/hard-of-hearing viewers
- Chapters: navigation markers displayed as a chapter menu (YouTube-style)
- Descriptions: text descriptions of video content for screen readers
- Metadata: arbitrary key-value data that JavaScript can read at specific timestamps
A minimal WebVTT file:
WEBVTT
00:00:00.000 --> 00:00:04.000
Hello, welcome to this video.
00:00:04.500 --> 00:00:09.000
Today we're going to learn about subtitle formats.
00:00:09.500 --> 00:00:14.000
WebVTT is the modern standard for web captions.
WebVTT File Structure
Every WebVTT file starts with the required header:
WEBVTT
Optionally followed by a header block:
WEBVTT
Kind: captions
Language: en-US
Then comes a series of cue blocks, each separated by a blank line:
[optional cue identifier]
[start time] --> [end time] [optional positioning settings]
[cue payload text]
Timestamps
WebVTT uses HH:MM:SS.mmm format (hours optional):
00:01:23.456— 1 minute, 23 seconds, 456 milliseconds01:23.456— 1 minute, 23 seconds (hours omitted when zero)
Hours are required if the video is over 59 minutes to avoid ambiguity.
Cue Identifiers (Optional)
chapter-1
00:00:00.000 --> 00:01:30.000
Introduction
Cue IDs can be used for:
- Anchor links to specific cue positions
- CSS targeting with
::cue(#chapter-1)pseudo-element - JavaScript referencing via the TextTrackCue API
Cue Positioning and Styling
This is where WebVTT significantly exceeds SRT:
Position Settings (on the --> line)
00:00:01.000 --> 00:00:04.000 position:10% align:left
This text appears at the left side of the screen.
00:00:05.000 --> 00:00:08.000 position:50% align:center line:90%
This text appears near the bottom center.
00:00:09.000 --> 00:00:12.000 position:90% align:right line:10%
This appears at the top right.
Available settings:
position:X%— horizontal position (0% = left, 100% = right)align:left|center|right|start|end— text alignment within cue boxline:X%orline:N— vertical position (% or line number from top)size:X%— width of the cue boxvertical:lr|rl— vertical text (for CJK languages)
Inline Styling with VTT Tags
WebVTT supports HTML-like tags within cue text:
00:00:01.000 --> 00:00:04.000
<b>Bold text</b> and <i>italic text</i> and <u>underlined</u>
<c.yellow>Yellow colored text</c>
<c.loud>Text with CSS class "loud"</c>
<ruby>漢字<rt>かんじ</rt></ruby>
CSS Styling via ::cue()
In CSS, you can style WebVTT cues:
::cue {
color: white;
background-color: rgba(0, 0, 0, 0.8);
font-size: 1.2em;
font-family: 'Arial', sans-serif;
}
::cue(b) {
color: yellow;
font-weight: bold;
}
::cue(.loud) {
font-size: 1.5em;
color: red;
}
Speaker Voice Tags
WEBVTT
00:00:01.000 --> 00:00:04.000
<v Alice>Hello, I'm Alice.
00:00:04.500 --> 00:00:07.000
<v Bob>And I'm Bob. We're co-hosting today.
Voice tags are used by CSS: ::cue(v[voice="Alice"]) to style different speakers.
WebVTT Chapters
When a WebVTT file is used as a chapters track (kind="chapters"), video players display a chapter menu:
WEBVTT
chapter-intro
00:00:00.000 --> 00:01:30.000
Introduction
chapter-basics
00:01:30.000 --> 00:08:45.000
Basic Concepts
chapter-advanced
00:08:45.000 --> 00:15:00.000
Advanced Topics
chapter-conclusion
00:15:00.000 --> 00:18:30.000
Conclusion
YouTube's chapter system uses a simplified text description in the video description box rather than VTT files, but the HTML5 <track kind="chapters"> API uses WebVTT.
Using WebVTT in HTML5
<video controls>
<source src="video.mp4" type="video/mp4">
<!-- English captions -->
<track kind="captions" src="captions-en.vtt" srclang="en" label="English" default>
<!-- Spanish subtitles -->
<track kind="subtitles" src="subtitles-es.vtt" srclang="es" label="Español">
<!-- Chapter navigation -->
<track kind="chapters" src="chapters.vtt" srclang="en">
<!-- Screen reader descriptions -->
<track kind="descriptions" src="descriptions.vtt" srclang="en">
</video>
Track kind values:
subtitles: transcribed dialoguecaptions: subtitles + audio descriptions (recommended for accessibility)chapters: navigation markersdescriptions: extended descriptions for screen readersmetadata: data for JavaScript consumption only (not displayed)
WebVTT vs SRT
| Feature | SRT | WebVTT |
|---|---|---|
| Standard body | Informal | W3C |
| Year | 1990s | 2010 |
| File extension | .srt | .vtt |
HTML5 <track> |
No | Yes |
| Cue positioning | No | Yes |
| Inline styling | No | Yes |
| CSS integration | No | Yes |
| Chapter markers | No | Yes |
| Metadata cues | No | Yes |
| Multiple speakers | No (workaround: - Speaker:) |
Yes (voice tags) |
| Editor support | Universal | Good |
| Encoding | UTF-8 (common) | UTF-8 required |
For web delivery: always use WebVTT. For compatibility with video editors and subtitle software: SRT is often simpler.
Converting Between VTT and SRT
VTT → SRT
# Using ffmpeg
ffmpeg -i input.vtt output.srt
# Using Python
# The srt library handles both formats
pip install srt
Manual conversion rules:
- Remove
WEBVTTheader line - Change timestamp format:
00:00:01.000→00:00:01,000(period → comma for milliseconds) - Add sequential numbers before each cue:
1,2,3... - Remove any VTT positioning and styling tags
- Remove voice tags (
<v Name>) — or convert toName: textformat
SRT → VTT
ffmpeg -i input.srt output.vtt
Manual conversion:
- Add
WEBVTTon the first line - Change timestamp separator:
,→.(comma → period for milliseconds) - Optionally remove cue numbers (they're optional in VTT)
Creating VTT from Transcript with Whisper (AI)
OpenAI's Whisper model generates WebVTT output directly:
pip install openai-whisper
whisper audio.mp3 --output_format vtt --language en
Accessibility and WCAG Compliance
WebVTT is the format required for WCAG 2.1 Level AA accessibility compliance for web video:
- 1.2.2 Captions (Prerecorded): Level A — captions required for all prerecorded audio in video
- 1.2.3 Audio Description: Level A — audio description or text alternative for all video content
The <track kind="captions"> element with a properly formatted VTT file satisfies these requirements. For government and educational websites subject to accessibility law (ADA in the US, EN 301 549 in the EU), WebVTT captions are effectively mandatory.
WebVTT is the subtitle format of the modern web. Its combination of W3C standardization, CSS integration, rich positioning, and native HTML5 support makes it the right choice for any video content delivered via a browser.
Related conversions
Common video conversions that pair well with this guide: