Online Tool Store Online Tool Store

SRT to VTT Converter

Convert an .srt file to WebVTT in your browser: adds the required header, normalises timestamps including one-digit fractions, escapes bare angle brackets that would break a cue, and translates ASS-style positioning overrides. Timing problems are reported rather than silently repaired.

🔒 This tool runs entirely in your browser. Your files are never uploaded to a server.

Options

Converted in this page — the file is never uploaded, which matters for unreleased footage. Serve the result as UTF-8 with a text/vtt content type; a wrong content type is the most common reason a valid file still fails to load.

How to use it

  1. Paste your SubRip text or open an .srt file — the sample shows the awkward cases.
  2. Read the notes: they say what was changed and why, not just that something was.
  3. Fix any timing problems at the source, or tick the box to omit those cues.
  4. Download the .vtt and serve it as UTF-8 with a text/vtt content type.

The four differences that actually matter

SubRip and WebVTT look nearly identical, which is why conversion is usually treated as a search and replace. These are the places that catches you out:

WEBVTT header     required        track is rejected without it
00:00:01,000      → 00:00:01.000   comma becomes a period
00:00:09,9        → 00:00:09.900   one digit means 900ms, not 9ms
5 < 10             → 5 &lt; 10       a bare < would start a tag

The fractional-digits case is the one worth dwelling on. A file written as 00:00:09,9 means nine and nine-tenths of a second. Read the fraction as an integer and you get nine seconds and nine milliseconds — a tenth of a second early, repeated across every loose timestamp in the file. It is a small enough error to survive review and large enough to make captions feel subtly off.

Why tags cannot simply be passed through

WebVTT defines a small set of inline tags: italic, bold, underline, voice, class and language. It does not include <font color>, which appears in plenty of SubRip files, and it has no concept of the ASS-style overrides like {\an8} that some tools leave behind. Left in place, those either do nothing or display as literal text over the video.

So the recognised tags are kept, <font> is unwrapped rather than deleted with its contents, and the positioning override is translated into the nearest real equivalent — a line:0 align:center cue setting, which puts the cue at the top of the frame where an8 intended it. Anything else that starts with a chevron is escaped, so it shows up as text rather than breaking the cue.

Problems are reported, not repaired

A cue that ends before it begins, or lasts zero seconds, is passed straight through with a note saying so. That is deliberate. Any automatic repair is a guess about intent, and a silently corrected timing is much harder to notice than an obviously broken one. Overlapping cues are reported too but flagged as normal, because overlap is how simultaneous dialogue is captioned and is perfectly legal.

When a valid file still will not play

This is worth knowing before you start debugging the file. WebVTT must be served as text/vtt and encoded as UTF-8; the wrong content type is refused regardless of how correct the contents are. A track loaded from another origin needs CORS headers and the crossorigin attribute on the video element. And a byte-order mark before the header will invalidate the file, which is why one is stripped here if present.

FAQ

Is it not just swapping commas for periods?

That is the visible difference, and on a simple file it is enough. It is the awkward files that need more: a missing WEBVTT header makes the browser reject the track outright, a payload containing a bare "<" is invalid because WebVTT reads it as a tag, one-digit fractions like ",5" mean 500 milliseconds rather than 5, and ASS-style overrides such as {\an8} render as literal text. This handles all four.

Why did my "5 < 10" line change?

Because a bare "<" begins a tag as far as WebVTT is concerned, so the rest of the cue would be swallowed or the file rejected. It is escaped to "&lt;", which displays as the character you wanted. Genuine tags — <i>, <b>, <u>, <v>, <c> and <lang> — are recognised and left alone; anything else beginning with "<" is escaped rather than passed through as markup no player understands.

Why does it not fix a cue that ends before it starts?

Because there is no way to know what was meant. Swapping the two timestamps, extending the end, or dropping the cue are all plausible and all change the caption timing. It is reported with the exact figures so you can correct it at the source, and there is a checkbox to omit those cues if you would rather ship the file without them.

Should I keep the cue numbers?

They are optional in WebVTT, and harmless. Keeping them makes it much easier to match the output against the original when something looks wrong, which is why it is the default. The one reason to drop them is if you plan to edit or merge cues afterwards, since stale numbering is more confusing than none.

My file converted cleanly but the track still will not load.

Almost always the server, not the file. WebVTT has to be served as text/vtt and UTF-8; served as text/plain or application/octet-stream, a browser will refuse it. Cross-origin tracks additionally need CORS headers and a crossorigin attribute on the video element. None of that is visible in the file itself, which is why a valid file can still fail.

Is my subtitle file uploaded?

No, it is parsed and rewritten in the page. That matters more than it sounds for subtitles, which routinely belong to footage that has not been released.

How we compare

Feature Online Tool Store Find-and-replace by hand Online converters
File never leaves your device
Escapes bare < and & in the payload Rarely
Handles one and two digit fractions correctly Varies
Reports timing problems with figures
Translates {\an8} to a cue setting
Batch conversion of many files Scriptable
Re-times or translates the captions Some do

The right choice for one file you want converted correctly, especially an unreleased one you would rather not upload. For a whole season of episodes, script it — ffmpeg will do the conversion, though it is less careful about payload escaping than this is.

Explore related tools

Embed this tool

Paste this on your own site — it stays free, and every file still stays in your visitor's browser, not yours or ours.