Data converters · 5 min read
SRT to VTT: subtitles the browser will actually load
An HTML5 video element will happily ignore an SRT file: the browser’s `<track>` element loads WebVTT and nothing else. Converting SRT to VTT is therefore a routine step in publishing video on the web — and the differences between the two formats are smaller than you would expect, which is exactly why the conversion is worth understanding rather than treating as a black box.
Updated
What changes between SRT and VTT
- The header — WebVTT files begin with the line `WEBVTT`, optionally with a title after it.
- Timecodes — SRT writes `00:00:12,500` with a comma before milliseconds; VTT writes `00:00:12.500` with a dot.
- Cue identifiers — both allow an optional name above the cue; VTT keeps them more usefully for scripting.
- End timecodes — required in SRT; VTT can infer an end from the next cue, though explicit is safer.
- Extra features — VTT adds cue settings such as line position, alignment and text markup.
Styling and safe markup
WebVTT allows a limited set of tags inside a cue — `<b>`, `<i>`, `<u>` and `<c.classname>` for classes you style with CSS via `::cue`. Anything else is more likely to render as literal text. This is also why the conversion should preserve simple formatting when present and drop what the format cannot express, rather than escaping markup into visible angle brackets.
WEBVTT
00:00:12.500 --> 00:00:15.000 align:start
That was the point.
Why it matters beyond playback
Captions are an accessibility requirement on most platforms, and they are also indexed material: a text track gives search engines and assistants a machine-readable script that the audio alone does not provide. A correctly encoded `<track kind="captions">` is therefore doing double duty — meeting compliance and giving the video a text presence it can otherwise lack.
Encoding matters: serve VTT as UTF-8 with an appropriate charset. A file with accented characters saved in a legacy encoding will render as mojibake in the player, and it will look like a conversion bug rather than an encoding one.
The practical workflow
- Convert the SRT to VTT and check the first and last cue for correct timecodes.
- Save as UTF-8 with the .vtt extension and serve it with a text/vtt content type where you control the server.
- Reference it from the video element with `<track kind="captions" srclang="en" label="English" default>`.
- Upload the caption file alongside the video file so relative paths keep working after deployment.
Offline and instant
Subtitle files are large text documents and often unreleased work — a review cut’s script should not be uploaded anywhere. The SRT to VTT converter on this site runs in the browser, so a two-hour transcript converts in a fraction of a second without leaving your machine.
SRT to VTT — frequently asked questions
Why does my video player ignore my subtitle file?
Almost always because the file is SRT rather than WebVTT. HTML5 `<track>` accepts VTT only. Convert to VTT, confirm the file begins with the WEBVTT line, then check that the timecodes use dots, not commas.
Do YouTube and other platforms need VTT?
YouTube accepts both SRT and VTT uploads and converts them internally, but most self-hosted players and every HTML5 video element need WebVTT. Converting before upload keeps the captions rendering the same everywhere.
Can WebVTT be styled?
Yes — inside cue text you can use the bold, italic and underline tags plus class spans, and you style classes with CSS against the `::cue` pseudo-element. Positioning is controlled with cue settings such as line, position and align.
Tools mentioned in this post
Keep reading
5 min read
Markdown tables: generate them instead of counting pipes
Build GitHub-flavoured markdown tables from rows or spreadsheets — alignment, escaping pipes, and when a table is the wrong choice for your README.
6 min read
JSON formatter: pretty, minified, and actually valid
A JSON formatter that pretty-prints, minifies and validates with exact error locations — plus the five syntax mistakes behind almost every invalid JSON error.