netflix-to-srt: turning streaming subtitles into .srt files
Rip, extract and convert subtitles to .srt closed captions from .xml/dfxp/ttml and .vtt/WebVTT (e.g. Netflix, YouTube)
At a glance
- What is it?
- netflix-to-srt converts dfxp and ttml XML subtitles and WebVTT files into SubRip .srt, either in the browser or through a single Python script that can shift every timestamp in a batch. The extraction instructions for Netflix and YouTube rely on browser devtools and third-party userscripts, which is where the fragility sits.
- Who is it for?
- Adopt netflix-to-srt if you need SubRip files from subtitle formats that players and editors handle badly, because the conversion is a single script with no dependencies to install, it works on a whole directory at once, and the shift option solves the problem of a subtitle track that is consistently late or early.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A converter, a browser page and one Python script
The project is a converter for subtitle formats, and the README states the job in three steps. Get the subtitles, as .xml dfxp or .vtt files from Netflix, YouTube and other streaming media services. Convert them into .srt files, and optionally shift the timestamps. Then use them.
The third step in the README is to star the repository, and it appears twice, once at the top of the flow and once at the end of the Python section. It is the only promotional line in the document, and the rest of it is instructions.
Two routes are offered for the conversion itself, and the README explains the difference in one line. Using your web browser is described as easiest, and using Python as better for big batches and automation. The web version is hosted at netflix-to-srt.pages.dev, with an alternative at isaacbernat.github.io/netflix-to-srt-web, which is also the project's homepage.
The Python side is a single file, to_srt.py, and the README makes a point of that: you can clone the repository, download it as a ZIP, or download just the to_srt.py file. That last option matters, because a one-file tool that you can fetch and run has none of the dependency problems of a package.
The licence is MIT, the default branch is master, and the single published release is v2.0.0 on 2026-04-02, titled CI/CD, Automated Testing and Modernization. The last push to the repository was on 2026-04-22. The primary language of the repository is JavaScript, because of the web application in the web/ directory, while the command line tool is Python, which is why both appear in the project topics.
Three ways to get the file out of Netflix
The extraction instructions are the longest part of the README, and they are also the part most likely to break.
Method one is a browser extension. You need one of Google Chrome, Firefox, Safari, Microsoft Edge or Opera, and Tampermonkey installed in it, with the install links given for each browser. Then you install the Netflix subtitle downloader script for Tampermonkey. To get the file, you open the episode in Netflix and download the subtitles by clicking on the Download subs from this episode option, which the README illustrates with a screenshot.
Method two uses the browser's network inspector, and the README is specific that you need Google Chrome, not tested on other web browsers. You open devtools with Cmd plus Alt plus i, or with F12, go to the Network tab, load the movie or episode, select the subtitle you want, and then sort by name and look for a file with ?o= at the beginning of the name. The reasoning is that Netflix's subtitle request has a distinctive query parameter, so finding it in the network log is a matter of looking for a prefix.
Method three is the old way, and the README credits it to a post on the OpenSubtitles forum. You need Firefox and the AdblockPlus add-on, again not tested on other browsers. You start Netflix and the movie or episode, with the stream active, then start AdblockPlus and open its blockable items list. You search for dfxp, and the README gives the shape of what you are looking for, a nflximg URL with a .dfxp path and a query string, and you open it in a new window and save it.
The pattern across the three is worth noticing. The repository does not extract anything itself. It documents how to get a file out of a browser, and then converts that file. The fragility is in the browser side, because Netflix can change its URLs, its devtools output and its player interface, and the userscript and the add-on are maintained by other people.
YouTube is easier, because the downloaders already do it
The YouTube section is the calmer half of the README, and the reason is that two mature tools already extract subtitle tracks.
Method one uses youtube-dl, available for Windows, Mac and Linux. You download the subs from the URL you like:
youtube-dl --all-subs "https://www.youtube.com/watch?v=VHNfvFOBC0A"The subtitles are written to the folder the command ran in, with names that carry the language code, such as NameOfTheVideo VHNfvFOBC0A.ca.vtt and NameOfTheVideo VHNfvFOBC0A.tlh.vtt. If a language seems to be missing, the README says to check that it is actually available, with the listing command:
youtube-dl --list-subs "https://www.youtube.com/watch?v=VHNfvFOBC0A"Method two uses yt-dlp, which the README describes as a fork of youtube-dl by Snap, and it links the installation page rather than repeating it. The command downloads the subtitles in VTT format:
yt-dlp --skip-download --write-auto-subs --sub-lang "en" "https://youtu.be/cVsyJvxX48A"And the README notes the alternative, that yt-dlp has its own integrated converter and can produce srt directly with --convert-subs srt added. If you want the video with its audio and subtitles, you simply omit the --skip-download option.
That last remark is the honest summary of the whole project. The conversion problem is solved, and the interesting part is what happens after you have a file in a format that only one streaming service's player understands.
The browser page is the easy path, and it is a hosted page
The browser route takes two steps and no installation. Go to netflix-to-srt.pages.dev, or the alternative at isaacbernat.github.io/netflix-to-srt-web, upload the subtitles and click convert.
That simplicity is the reason the README calls it the easiest option, and it is genuinely the fastest way to convert one file. The web application is the web/ directory in the repository, and the rest of the tree is the Python script, the samples and the tests, so both implementations exist in the same place and can be compared.
One thing the README does not state is where the uploaded file is processed. It says to upload the subtitles and click convert, and it does not say whether the file is processed in the browser or sent to a server. For a subtitle file, that is usually a small concern. For a file that came out of a stream you have rights to, it is a small concern too. But the honest position for a reader is that the README does not say, and a reader who cares should check rather than assume.
The Python route has no such ambiguity, which is why the README recommends it for big batches and automation: the script runs on your machine, reads a directory, and writes a directory. Nothing leaves the machine at all.
The two routes also differ in what they can do. The Python script has the timestamp shift option and the explicit input and output paths, and it processes every eligible file in one pass, which is what makes it usable in a pipeline.
to_srt.py, and the -d flag that fixes a mistimed track
The Python instructions are short. Get Python, unless you are on Mac or Linux. Clone the repository, or download it as a ZIP, or download just the to_srt.py file. Then run it from the terminal in the folder where the script lives:
python to_srt.pyWith python3 on systems where that is the command. The script then expects the subtitle files to be in the same directory as to_srt.py, and it converts every .xml and .vtt file in the input directory into a converted .srt file in the output directory.
For custom locations there are two parameters, -i INPUT_PATH and -o OUTPUT_PATH, so you can keep your downloads and your results apart. The batch behaviour is a directory sweep rather than a file list, which is the right default for the use case, where you have downloaded twenty episodes and want twenty converted files.
The optional third parameter is the interesting one. -d DELAY_MS delays all the timestamps by the given number of milliseconds, and negative values shift them backwards. The README gives a worked example:
python to_srt.py -i samples/delays -o samples/delays -d -1500which takes all the eligible files in samples/delays and shifts the resulting .srt subtitles to be 1.5 seconds earlier than the original version. A shifted subtitle track is a common real problem, because the timings of a track extracted from a stream are often offset by a constant relative to the start of the video, and a player that offers no offset control makes that unwatchable. Being able to correct it in one pass over a directory is the feature that makes this script worth more than a web form.
The README notes the supported interpreter: tested on Python 3.10 and newer, with 3.10 being the oldest still supported version.
The samples directory is the real specification
The repository layout is small: to_srt.py, the web/ application, a samples/ directory, a tests/ directory, images/ for the screenshots the README embeds, and the usual project files.
The samples are the interesting part, and they read like a list of the things that break subtitle converters. There is a sample.srt and a sample.xml pair, then numbered pairs from sample2 through sample11, each with an xml and an srt, and a sample10.XML with the extension in capitals. That last one is a test in itself, because case-insensitive file matching is a routine thing to get wrong when you sweep a directory.
There is also sample_escaped_html_entities.xml with its matching .srt, which tells you that the converter handles XML entities in the source, and a delay/ directory that corresponds to the -d example in the README.
What the numbered samples are, the README does not say, and that is a small piece of missing documentation. Each pair is a conversion fixture, so a reader can run the script over the directory and diff the outputs to see exactly what the converter produces for that input, which is a much better way to learn its behaviour than reading the code.
The tests/ directory is what the v2.0.0 release title refers to, together with CI/CD and modernization. The release note is the only changelog in the repository, and it is a summary line rather than a list of changes.
Where this is fragile, and what to check first
The fragility is not in the converter. It is in the half of the workflow that this repository does not own.
Method one for Netflix depends on a userscript hosted on Greasy Fork and installed through Tampermonkey, and the userscript is maintained by someone else. Method two depends on the shape of Netflix's network requests, which change without notice. Method three depends on an add-on's blockable items list. YouTube is in better shape, because youtube-dl and yt-dlp are maintained projects with their own release cycles, but they are also third-party tools that adapt to a moving target.
What that means for an engineer is that the conversion step is dependable and the extraction step is a moving dependency. If you are building a repeatable pipeline, the parts you control are the downloader, the converter and the shift, and the part you should keep checking is the userscript and the devtools procedure.
The browser page is the other moving part, and it is a page hosted on a domain that is not the GitHub Pages one, with a second copy on GitHub Pages as an alternative. Two deployment locations is a reasonable hedge, and it also means the page you use is not necessarily the one in the repository.
On maintenance, the numbers are modest but not stale: the last push was on 2026-04-22, the repository is not archived, and the single release v2.0.0 came on 2026-04-02 with a title about CI, testing and modernisation. For a tool this small, one release and a test suite is a reasonable shape, and the samples directory is the part worth spending time with.
Editorial conclusion
Adopt netflix-to-srt if you need SubRip files from subtitle formats that players and editors handle badly, because the conversion is a single script with no dependencies to install, it works on a whole directory at once, and the shift option solves the problem of a subtitle track that is consistently late or early. Do not adopt it expecting a complete downloader, because the getting-the-subtitles part of the workflow depends on browser extensions, a userscript and a devtools search, all of which live outside this repository and can break when the streaming services change. Before you rely on it, check the samples directory for the edge case you care about, since the escaped HTML entities sample shows the converter was built against real-world files, and remember that the browser version does not document where the file is processed, so if that matters to you, the Python script runs entirely on your own machine.
Frequently asked questions
How do I convert Netflix dfxp subtitles to srt?
Get the .xml or .vtt file first, using one of the three extraction methods the README describes, then convert it. The web page at netflix-to-srt.pages.dev takes an upload and converts it, and the Python script to_srt.py converts every .xml and .vtt file in an input directory into .srt files in an output directory.
How do I download YouTube subtitles with yt-dlp?
Run yt-dlp --skip-download --write-auto-subs --sub-lang "en" with the video URL, which writes the subtitles in VTT format. Adding --convert-subs srt makes yt-dlp produce srt directly, and omitting --skip-download downloads the video with its audio and subtitles as well.
Can netflix-to-srt fix subtitles that are out of sync?
Yes. The Python script takes an optional -d DELAY_MS parameter that shifts every timestamp by the given number of milliseconds, with negative values shifting them backwards. The README's example is python to_srt.py -i samples/delays -o samples/delays -d -1500, which moves the whole batch 1.5 seconds earlier.
What Python version does netflix-to-srt need?
The README says it is tested on Python 3.10 and newer, and notes that 3.10 is the oldest still supported version. The script is a single file, to_srt.py, which you can download on its own without cloning the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/isaacbernat-netflix-to-srt)Was this useful?