How to convert SRT to VTT (and why HTML5 video needs it)
A browser will not play an SRT file, but converting one to the VTT it does accept is almost trivial. Here are the two changes involved, and the exact markup to load the result.
If you have tried to add captions to an HTML5 video and nothing appeared, an SRT file is almost always the reason. Browsers do not read SubRip. The <track> element only understands WebVTT, so an SRT that plays flawlessly in VLC is invisible on a web page. The good news is that the two formats are so similar that converting between them is mostly a find-and-replace.
This guide covers the two mechanical changes, shows the video markup that loads the result, and flags the MIME-type detail that catches people out on their own server.
Why does HTML5 video need VTT at all?
When the web platform standardised captions, it picked one format — WebVTT — and built the <track> element around it. That decision keeps browsers simple: they only ever have to parse a single, well-specified format. SRT, for all its popularity, is a loose de-facto convention that was never written into any web standard, so browsers deliberately do not support it.
That is why the fix is a conversion and not a setting. There is no flag that makes a browser read SRT; you have to hand it VTT. The two formats descend from the same idea, though, which is why the change is so small.
What are the two changes?
A valid VTT differs from an SRT in exactly two ways. Make both and you have a working caption file.
1. Add the WEBVTT header
The first line of the file must be the word WEBVTT, on its own, before anything else — no blank line above it, no byte-order mark in front of it. This header is how the browser recognises the file as a caption track. Without it, parsing fails immediately and no cues show, even if everything below is perfect.
2. Change commas to periods in timestamps
SRT separates the seconds from the milliseconds with a comma: 00:00:04,500. VTT uses a period: 00:00:04.500. Every timestamp in the file needs this swap. The hours-minutes-seconds colons stay exactly as they are — only the millisecond separator changes.
Here is the same cue before and after. The counter and the text are untouched; only the header and the two decimal points are new.
SRT (before)
1
00:00:04,500 --> 00:00:07,200
Today we are talking about subtitles.VTT (after)
WEBVTT
1
00:00:04.500 --> 00:00:07.200
Today we are talking about subtitles.| Element | SRT | VTT |
|---|---|---|
| First line | (cue number) | WEBVTT |
| Millisecond separator | Comma 00:00:04,500 | Period 00:00:04.500 |
| Cue text & timing | Unchanged | Unchanged |
| File extension | .srt | .vtt |
| Served as | application/x-subrip | text/vtt |
You can make both changes by hand in a text editor for a short file, but for anything real the SRT to VTT converter does it instantly and correctly — header added, commas swapped, saved as clean UTF-8 — without the file ever leaving your browser. If you need the reverse later, VTT to SRT undoes it just as cleanly.
Convert your SRT to VTT nowHow do I load the VTT into a video?
Once you have the VTT, you attach it to an HTML5 <video> with a <track> element nested inside. The src points at the VTT, kind="subtitles" tells the browser what it is, srclang sets the language, and default makes it show without the viewer turning it on.
<video controls width="720">
<source src="lecture.mp4" type="video/mp4" />
<track
src="lecture.vtt"
kind="subtitles"
srclang="en"
label="English"
default
/>
</video>That is all the markup needs. You can also stack several <track> elements inside the same <video> to offer more than one language — one VTT per language, each with its own srclang and label, and default on only the one you want shown first. The browser then builds the subtitle menu automatically, so a viewer can switch between English, Spanish and French from the player controls.
If the captions still do not appear after all that, the problem is almost always the server, not the HTML — which brings us to the MIME type.
Why does the MIME type matter?
Browsers are strict about how a VTT is delivered. The server must send it with the Content-Type: text/vtt header. If your host serves it as text/plain, or with a generic application/octet-stream, some browsers will refuse to parse it and the track silently fails — no error, just no captions.
Most modern servers already map the .vtt extension to text/vtt, but older or minimal setups do not. If you control the server, add the mapping. On Apache, one line does it:
# .htaccess
AddType text/vtt .vttOnce the file converts cleanly and serves with the right type, the captions appear on first play. If you want to sanity-check the cues before wiring up the page, the subtitle preview tool renders them so you can catch timing or wrapping issues early, and the full subtitle editor lets you nudge anything that looks off. For the bigger picture of getting captions onto a clip, see add subtitles to a video.
Frequently asked questions
Can I convert SRT to VTT without any software?
Yes. The two changes — adding the header and swapping commas for periods — can be done in any plain text editor. For more than a couple of cues, a browser-based converter is faster and avoids mistakes, and it still keeps the file on your own device.
My VTT loads but shows no text. What is wrong?
Check three things in order: the first line is exactly WEBVTT, the file is UTF-8 with no BOM in front of that header, and the server sends it as text/vtt. One of those three is nearly always the cause.
Do I need the cue numbers in a VTT?
No. VTT cue identifiers are optional, so a valid file can go straight from the header to the first timestamp. Keeping the numbers does no harm and makes the file easier to compare against the original SRT.
Is the conversion reversible?
Completely, as long as your VTT is plain. Converting back to SRT removes the header and turns the periods into commas. Only VTT-specific features like cue positioning or styling would be lost, and a converted-from-SRT file has none of those.
Can one VTT file hold several languages?
No — keep one VTT per language and add a separate <track> element for each. The srclang and label on each track tell the browser which language it is, and the player builds the caption menu from them. A single file should contain a single language.
Does the file size change much after converting?
Barely. You are adding one short header line and changing punctuation, so a VTT is within a few bytes of the SRT it came from. Subtitle files are tiny to begin with, so size is never a concern here.