A free, open-source, and powerful m3u8 video batch downloader with multi-threaded downloading, play-while-downloading, WebUI management, video parsing, and more. Supports multiple usage methods including CLI command line, browser, PC client, Docker deployment, and Node.js API calls.


This is a Violentmonkey/Tampermonkey/Greasemonkey userscript that can automatically capture video links in browsers, working with M3U8-DL WebUI to provide a seamless download experience.

No need to rely on third-party players, you can directly watch downloaded content in the browser or client, improving convenience.

Method 1: Global Installation with Node.js
Use as a CLI command-line tool.
npm i -g @lzwme/m3u8-dl
m3u8dl -h
Or use npx to run directly:
npx @lzwme/m3u8-dl -h
Method 2: Desktop Application Download
Install as a PC client. Easy to use, suitable for most regular users, with built-in browser functionality to automatically extract video addresses. Download the latest version from one of the following addresses:
Tip: If you need to download and convert to
mp4video format, you need to globally install ffmpeg. Or use the--ffmpeg-pathparameter to specify the path to ffmpeg.
View all available commands and options:
m3u8dl --help
# Download a single m3u8 file
m3u8dl https://example.com/video.m3u8
# Specify filename and save directory
m3u8dl https://example.com/video.m3u8 --filename "My Video" --save-dir "./downloads"
# Enable play-while-downloading mode
m3u8dl https://example.com/video.m3u8 --play
# Set thread count (default 4)
m3u8dl https://example.com/video.m3u8 --thread-num 8
# Don't convert to mp4 (only download ts segments)
m3u8dl https://example.com/video.m3u8 --no-convert
# Ignore specified time segments (e.g., skip first 30 seconds and last 60 seconds)
m3u8dl https://example.com/video.m3u8 --ignore-segments "0-30,END-60"
Method 1: Command Line Parameters
# Download multiple files, use | to separate filename and URL
m3u8dl "Episode 1|https://example.com/ep1.m3u8" "Episode 2|https://example.com/ep2.m3u8" --filename "Series Name"
Method 2: Batch Import from Text File
Create a series-list.txt file with the following format (use $ to separate filename and URL):
Episode 1$https://example.com/ep1.m3u8
Episode 2$https://example.com/ep2.m3u8
Episode 3$https://example.com/ep3.m3u8
Then execute:
m3u8dl series-list.txt --filename "Series Name"
Supports sharing links from platforms like Douyin, Weibo, etc.:
# Douyin video sharing link
m3u8dl "https://v.douyin.com/xxxxx/" --type parser
# Weibo video sharing link
m3u8dl "https://weibo.com/xxxxx" --type parser
# Automatically extract m3u8 address from video playback page and download
m3u8dl "https://example.com/play/12345" --type web
# View search command help
m3u8dl search --help
# Specify collection site API and search download (will cache API address)
m3u8dl search -u https://api.example.com/provide/vod/
# Search keyword directly
m3u8dl search "keyword" -u https://api.example.com/provide/vod/
Disclaimer: The above are examples only. Please search for available collection site APIs yourself. This tool is only for technical research and learning purposes and does not provide any specific resource information.
| Option | Description |
|---|---|
-f, --filename <name> |
Specify filename |
-n, --thread-num <number> |
Set download thread count (default 4) |
-p, --play |
Enable play-while-downloading mode |
-C, --cache-dir <dirpath> |
Specify cache directory |
-S, --save-dir <dirpath> |
Specify save directory |
--no-convert |
Don't convert to mp4 |
--no-del-cache |
Don't delete cache after download completes |
--ffmpeg-path <path> |
Specify ffmpeg path |
-H, --headers <headers> |
Set request headers (JSON format) |
-I, --ignore-segments <time> |
Ignore specified time segments |
--debug |
Enable debug mode |
--lang <lang> |
Set language (zh-CN/en) |
Start web service to manage download tasks through browser:
# Start service (default port 6600)
m3u8dl server
# Specify port and access password
m3u8dl server -p 8080 -t "your-secret-token"
After starting, visit http://localhost:6600 in your browser to use WebUI.
WebUI Main Features:
Environment Variable Configuration:
# Set port
export DS_PORT=6600
# Set access password
export DS_SECRET=your-secret-token
# Set save directory
export DS_SAVE_DIR=./downloads
# Set cache directory
export DS_CACHE_DIR=./cache
# Set ffmpeg path
export DS_FFMPEG_PATH=/usr/local/bin/ffmpeg
# Enable debug mode
export DS_DEBUG=1
# Limit file access (only allow access to download and cache directories)
export DS_LIMTE_FILE_ACCESS=1
Call related APIs in your project. Code examples:
import { m3u8Download, m3u8BatchDownload, VideoParser, getM3u8Urls } from '@lzwme/m3u8-dl';
// Example 1: Single file download
const result = await m3u8Download('https://example.com/video.m3u8', {
filename: 'My Video',
saveDir: './downloads',
threadNum: 8,
debug: true,
});
if (result.errmsg) {
console.error('Download failed:', result.errmsg);
} else {
console.log('Download successful:', result.filepath);
}
// Example 2: Batch download
const fileList = [
'Episode 1$https://example.com/ep1.m3u8',
'Episode 2$https://example.com/ep2.m3u8',
];
await m3u8BatchDownload(fileList, {
filename: 'Series Name',
threadNum: 4,
});
// Example 3: Video parsing download (Douyin, Weibo, etc.)
const parser = new VideoParser();
const parseResult = await parser.parse('https://v.douyin.com/xxxxx/');
if (parseResult.data) {
console.log('Video title:', parseResult.data.title);
console.log('Video URL:', parseResult.data.url);
// Download video
await parser.download('https://v.douyin.com/xxxxx/', {
filename: parseResult.data.title,
});
}
// Example 4: Extract m3u8 addresses from web page
const urls = await getM3u8Urls({
url: 'https://example.com/play/12345',
headers: {
'User-Agent': 'Mozilla/5.0...',
},
deep: 2, // Search depth
});
console.log('Extracted addresses:', Array.from(urls.keys()));
// Example 5: Specify ffmpeg path
import ffmpegStatic from 'ffmpeg-static';
m3u8Download('https://example.com/video.m3u8', {
filename: 'Test Video',
ffmpegPath: ffmpegStatic, // Use ffmpeg-static package. Suitable for scenarios where ffmpeg is not globally installed
// Or specify the absolute path of installed ffmpeg (if already in PATH environment variable, no need to specify)
// ffmpegPath: '/usr/local/bin/ffmpeg',
});
# Pull image
docker pull renxia/m3u8dl-dl:latest
# Run container
docker run --rm -it \
-v ./cache:/app/cache \
-v ./downloads:/app/downloads \
-p 6600:6600 \
-e DS_PORT=6600 \
-e DS_SECRET=your-secret-token \
renxia/m3u8dl-dl:latest
Create docker-compose.yml file:
services:
m3u8-dl:
image: renxia/m3u8dl-dl:latest
container_name: m3u8-dl
volumes:
- ./downloads:/app/downloads
- ./cache:/app/cache
ports:
- '6600:6600'
environment:
DS_PORT: '6600'
DS_SAVE_DIR: '/app/downloads'
DS_CACHE_DIR: '/app/cache'
DS_SECRET: '' # Set access password
DS_DEBUG: ''
DS_FFMPEG_PATH: '' # Leave empty to use ffmpeg from system PATH
DS_LIMTE_FILE_ACCESS: '1' # Limit file access
restart: unless-stopped
Start service:
docker-compose up -d
After successful deployment, visit http://your-server-ip:6600 in your browser to use.
Tip: The Docker image already includes ffmpeg, no need for additional installation. The image also includes AriaNg static resources.
The project supports packaging as an Electron desktop application with richer features:
Download the built application:
Installation Steps:
Install browser extension (choose one):
Install script:
client/m3u8-capture.user.js fileConfigure WebUI address:
http://localhost:6600)Feature Description:
h1, h2, or document.titleurl|name)/, e.g., /example\.com/)Usage Example:
Exclusion Rule Configuration Example:
localhost:6600
127.0.0.1
/example\.com/
admin
Tip: The script automatically excludes WebUI address pages to avoid capturing in WebUI pages. You can also manually add more exclusion rules.
# Clone project
git clone https://github.com/lzwme/m3u8-dl.git
cd m3u8-dl
# Install dependencies
pnpm install
# Development mode (watch file changes and auto-compile)
pnpm dev
# Build project
pnpm build
# Code check
pnpm lint
# Code format
pnpm format
# Fix code issues
pnpm fix
Build desktop application:
# Enter application directory
cd packages/m3u8dl-app
# Install dependencies
pnpm install
# Run in development mode
pnpm dev
# Build application
pnpm build
m3u8-dl/
├── src/ # Source code (TypeScript)
│ ├── cli.ts # Command line entry
│ ├── lib/ # Core library
│ ├── server/ # Web service
│ ├── video-parser/ # Video parser
│ └── types/ # Type definitions
├── packages/
│ ├── frontend/ # Vue 3 frontend project
│ ├── m3u8dl-app/ # Electron desktop application
│ └── m3u8-capture/ # Browser userscript (TypeScript + Vite)
├── cjs/ # Compiled CommonJS code
└── client/ # Frontend build output
└── m3u8-capture.user.js # Browser video address capture userscript (built from packages/m3u8-capture)
Welcome to submit Issues and Pull Requests!
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Welcome to contribute ideas and code! 🎉
Thanks to the following projects for inspiration and reference:
@lzwme/m3u8-dl is released under the MIT license.
This plugin is developed and maintained by Zhiwen Studio.