Home β€Ί Guides β€Ί How to Add Subtitles to HTML5 Video

How to Add Subtitles to HTML5 Video

The native track element handles captions without any JavaScript library. Here is the working setup, and the four reasons it silently does nothing.

The short version

Use a <track> element pointing at a WebVTT file. If your file is .srt, convert it first β€” browsers do not read SubRip at all. The three things that break most often are the file format, the server's content type, and cross-origin access.

A minimal working example

<video controls width="640">
  <source src="video.mp4" type="video/mp4">
  <track src="captions.vtt" kind="subtitles" srclang="en" label="English" default>
</video>

Save the captions as captions.vtt beside the video. That is a complete, working setup β€” no library, no configuration.

The four attributes that matter

  • src β€” path to the WebVTT file.
  • kind β€” use subtitles when you are translating dialogue, captions when you are also conveying sound effects and speaker identity. The distinction is about accessibility, not about file format.
  • srclang β€” a BCP 47 language tag such as en, zh-Hans or pt-BR. Required for the track to be offered as a subtitle option.
  • label β€” the text shown in the player's caption menu. Omit it and the menu entry can appear blank.

Add default to the track you want enabled automatically. Supply several tracks without marking any default and captions start switched off, leaving the viewer to find the menu.

Why your captions silently do nothing

Browsers fail quietly here. A broken track usually produces no console error and no visible message β€” the captions simply never appear.

1. The file is SubRip

An .srt file is ignored even when you point src straight at it. Convert it with the SRT to VTT converter. If you can see a comma inside the timestamp, that is your problem.

2. The server sends the wrong content type

WebVTT files must be served as text/vtt. Plenty of servers and default static-host configurations serve an unfamiliar extension as application/octet-stream or text/plain, and browsers then refuse the track. Check the response headers in your browser's network panel. On a static host, add a rule mapping .vtt to text/vtt.

3. The file is on a different origin

Track files follow cross-origin rules. If the video and the captions live on different domains, the caption request needs CORS headers and the <track> element needs crossorigin="anonymous". Without both, the track is blocked.

4. The WebVTT file is malformed

WebVTT requires the WEBVTT header, a blank line before the first cue, and a blank line between cues. A file missing any of those parses as empty. Re-convert from the original source, or run it through Clean subtitles.

Styling the captions

WebVTT cues can be styled from your own CSS using the ::cue pseudo-element β€” a genuine advantage over SubRip.

video::cue {
  background: rgba(0,0,0,.75);
  color: #fff;
  font-size: 1.1rem;
}
video::cue(.speaker) { color: #ffd479; }

To use a class, write it into the cue as <c.speaker> in the WebVTT text. Class-based cue styling is supported unevenly across browsers, so treat it as an enhancement rather than a requirement.

Serving captions in more than one language

Add one <track> per language. The player builds its caption menu from label and srclang.

<track src="captions.en.vtt" kind="subtitles" srclang="en" label="English" default>
<track src="captions.es.vtt" kind="subtitles" srclang="es" label="EspaΓ±ol">
<track src="captions.de.vtt" kind="subtitles" srclang="de" label="Deutsch">

Do you need a player library?

Not for basic captions. Native <track> support in modern browsers handles loading, the caption menu, timing and styling on its own. Reach for a JavaScript player library when you need adaptive bitrate streaming, DRM, or caption rendering that must look identical on every platform β€” not simply to display subtitles.

Tools mentioned in this guide

SRT to VTT Converter

Convert .srt subtitle files to WebVTT (.vtt) for HTML5 video, right in your browser.

Open tool β†’

VTT to SRT Converter

Turn WebVTT files back into SubRip (.srt) for editors, players and upload platforms.

Open tool β†’

Remove Timestamps from Subtitles

Strip timestamps and cue numbers to get a clean, readable transcript.

Open tool β†’

Clean Up AI-Generated Subtitles

Remove sound cues, HTML tags, speaker labels and duplicate cues from auto-generated captions.

Open tool β†’

Shift Subtitle Timing

Move every subtitle cue earlier or later to fix out-of-sync captions.

Open tool β†’

Resync Subtitles by Frame Rate or Speed

Fix subtitles that drift progressively out of sync by resampling them to your video's frame rate or playback speed.

Open tool β†’

SBV to SRT Converter

Convert YouTube .sbv caption files to SubRip (.srt), right in your browser.

Open tool β†’

Merge Subtitle Files

Combine two SRT or VTT files into one track, with the second file appended after the first.

Open tool β†’

Subtitles to CSV Converter

Export SRT or VTT cues to a CSV spreadsheet with start time, end time, duration and text.

Open tool β†’

Split Subtitle Files

Cut one SRT or VTT track into two files at any timestamp, right in your browser.

Open tool β†’

Fix Garbled Subtitles (Encoding Repair)

Repair mojibake β€” subtitles showing é, Ò€ℒ or ΓΒΏΓ‘β‚¬ΓΒΈΓΒ²ΓΒ΅Γ‘β€š instead of real characters.

Open tool β†’

Subtitle Timing Checker

Audit an SRT or VTT file for cues that are too fast, too short, too long or overlapping.

Open tool β†’

ASS / SSA to SRT Converter

Turn SubStation Alpha (.ass, .ssa) subtitles into clean SubRip (.srt) β€” in your browser, with nothing uploaded.

Open tool β†’

SRT to ASS Converter

Turn SubRip (.srt) subtitles into a complete ASS v4+ script with a default style, ready for styled players.

Open tool β†’

TTML / DFXP to SRT Converter

Turn TTML and DFXP captions (.ttml, .dfxp, .xml) into SubRip (.srt) in your browser β€” including offset times such as 10s, 100ms and 30f.

Open tool β†’

Plain Text to SRT Converter

Turn a transcript β€” one line per caption β€” into a valid .srt file with evenly spaced timing you can retime later.

Open tool β†’

Last updated 2026-09-21. All tools run locally in your browser.