
Security News
Socket Security Analysis Is Now One Click Away on npm
npm now links to Socket's security analysis on every package page. Here's what you'll find when you click through.
ytdlp-nodejs
Advanced tools
⚠️ Notice: Version 3.4.0 is currently in beta. While we've thoroughly tested the new features, please report any issues you encounter on our GitHub Issues page. Your feedback helps make this library better!
A powerful Node.js wrapper for yt-dlp that provides a simple, type-safe interface for downloading, streaming, and fetching metadata from videos across thousands of websites.
npm install ytdlp-nodejs
Note: FFmpeg is recommended for full functionality. Install it manually or use the built-in
downloadFFmpeg()method.
import { YtDlp } from 'ytdlp-nodejs';
const ytdlp = new YtDlp();
// Download a video with fluent API
const result = await ytdlp
.download('https://youtube.com/watch?v=dQw4w9WgXcQ')
.filter('mergevideo')
.quality('1080p')
.type('mp4')
.on('progress', (p) => console.log(`${p.percentage_str}`))
.run();
console.log('Downloaded:', result.filePaths);
// Get video info
const info = await ytdlp.getInfoAsync(
'https://youtube.com/watch?v=dQw4w9WgXcQ',
);
console.log(info.title);
// Stream to file
import { createWriteStream } from 'fs';
const stream = ytdlp.stream('https://youtube.com/watch?v=dQw4w9WgXcQ');
await stream.pipeAsync(createWriteStream('video.mp4'));
Launch the interactive menu to access all features with guided prompts:
ytdlp
These commands run without prompts:
# List available formats
ytdlp formats <url>
# Download with specific quality (non-interactive)
ytdlp video <url> --quality 1080p
# Download FFmpeg binaries
ytdlp ffmpeg
# Update yt-dlp binary
ytdlp update
const ytdlp = new YtDlp({
binaryPath?: string, // Path to yt-dlp binary
ffmpegPath?: string, // Path to ffmpeg binary
});
download(url, options?)Returns a fluent builder for downloading with chainable methods.
// Fluent builder API (recommended)
const result = await ytdlp
.download('https://youtube.com/watch?v=...')
.format({ filter: 'mergevideo', quality: '1080p', type: 'mp4' })
.output('./downloads')
.embedThumbnail()
.on('progress', (p) => console.log(`${p.percentage_str}`))
.run();
console.log('Files:', result.filePaths);
// With initial options
const result = await ytdlp
.download(url, {
format: { filter: 'mergevideo', quality: '1080p', type: 'mp4' },
})
.embedThumbnail()
.on('progress', (p) => console.log(p))
.run();
| Category | Methods |
|---|---|
| Format | .filter(), .quality(), .type(), .format() |
| Output | .output('./downloads'), .setOutputTemplate('%(title)s.%(ext)s') |
| Audio | .extractAudio(), .audioFormat('mp3'), .audioQuality('0') |
| Embed | .embedThumbnail(), .embedSubs(), .embedMetadata() |
| Subtitles | .writeSubs(), .writeAutoSubs(), .subLangs(['en', 'es']) |
| Thumbnail | .writeThumbnail() |
| Auth | .cookies(str), .cookiesFromBrowser('chrome'), .username(user), .password(pass) |
| Network | .proxy(url), .rateLimit('1M') |
| Playlist | .playlistStart(1), .playlistEnd(10), .playlistItems('1,3,5') |
| Advanced | .options(argsOptions), .addOption(key, value), .addArgs(...args), .skipDownload() |
| Events | .on('start' | 'progress' | 'beforeDownload' | 'stdout' | 'stderr' | 'error' | 'finish', fn) |
| Execute | .run() - returns Promise<DownloadFinishResult> - Also directly awaitable |
downloadAsync(url, options?)Downloads a video asynchronously with callback-style progress.
const result = await ytdlp.downloadAsync(url, {
format: { filter: 'mergevideo', type: 'mp4', quality: '1080p' },
output: './downloads/%(title)s.%(ext)s',
onProgress: (progress) => console.log(progress),
});
downloadAudio(url, format?, options?)Downloads audio only.
await ytdlp.downloadAudio(url, 'mp3'); // 'aac', 'flac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav', 'alac'
downloadVideo(url, quality?, options?)Downloads video with specific quality.
await ytdlp.downloadVideo(url, '1080p'); // 'best', '2160p', '1440p', '1080p', '720p', etc.
stream(url, options?)Returns a fluent builder for streaming with chainable methods.
import { createWriteStream } from 'fs';
// Fluent builder API
const result = await ytdlp
.stream('https://youtube.com/watch?v=...')
.filter('audioandvideo')
.quality('highest')
.type('mp4')
.on('progress', (p) => console.log(p.percentage_str))
.pipeAsync(createWriteStream('video.mp4'));
console.log(`Bytes: ${result.bytes}`);
// Sync pipe
ytdlp.stream(url).filter('audioandvideo').pipe(writableStream);
// Stream to buffer
const buffer = await ytdlp.stream(url).filter('audioonly').toBuffer();
| Method | Description |
|---|---|
.filter(), .quality(), .type() | Set format options (same as Download) |
.pipe(dest, options?) | Pipe to writable stream, returns Promise |
.pipeAsync(dest, options?) | Alias for .pipe() |
.toBuffer() | Collect stream into Buffer |
.getStream() | Get underlying PassThrough stream |
.on('start' | 'progress' | 'beforeDownload' | 'data' | 'error' | 'end', fn) | Event listeners |
getFileAsync(url, options?)Returns a File object without saving to disk.
const file = await ytdlp.getFileAsync(url, {
format: { filter: 'audioonly', type: 'mp3' },
onProgress: (p) => console.log(p),
});
console.log(file.name, file.size);
getInfoAsync(url, options?)Fetches video/playlist metadata.
const info = await ytdlp.getInfoAsync(url);
console.log(info.title, info.duration, info.formats);
getFormatsAsync(url, options?)Gets available formats using JSON output.
const result = await ytdlp.getFormatsAsync(url);
console.log(`Found ${result.formats.length} formats`);
getDirectUrlsAsync(url, options?)Returns direct media URLs.
const urls = await ytdlp.getDirectUrlsAsync(url);
getTitleAsync(url)const title = await ytdlp.getTitleAsync(url);
getThumbnailsAsync(url)const thumbnails = await ytdlp.getThumbnailsAsync(url);
getVersionAsync()const version = await ytdlp.getVersionAsync();
checkInstallationAsync(options?)const installed = await ytdlp.checkInstallationAsync({ ffmpeg: true });
downloadFFmpeg()await ytdlp.downloadFFmpeg();
updateYtDlpAsync(options?)const result = await ytdlp.updateYtDlpAsync();
console.log(`Updated to ${result.version}`);
Use structured format options for type-safe configuration:
// Video only
{ filter: 'videoonly', type: 'mp4', quality: '1080p' }
// Audio only
{ filter: 'audioonly', type: 'mp3', quality: 5 }
// Audio and video (single file)
{ filter: 'audioandvideo', type: 'mp4', quality: 'highest' }
// Merge video and audio
{ filter: 'mergevideo', type: 'mp4', quality: '1080p' }
| Filter | Quality Values |
|---|---|
videoonly, mergevideo | '2160p', '1440p', '1080p', '720p', '480p', '360p', '240p', '144p', 'highest', 'lowest' |
audioandvideo | 'highest', 'lowest' |
audioonly | 0 to 10 (VBR quality) |
| Filter | Type Values |
|---|---|
videoonly, audioandvideo | 'mp4', 'webm' |
audioonly | 'aac', 'flac', 'mp3', 'm4a', 'opus', 'vorbis', 'wav', 'alac' |
mergevideo | 'mkv', 'mp4', 'ogg', 'webm', 'flv' |
Node.js is used as the default JavaScript runtime for yt-dlp extractors:
await ytdlp.execAsync(url, {
jsRuntime: 'node', // default, or 'deno', 'phantomjs'
});
Pass any yt-dlp argument directly:
await ytdlp.downloadAsync(url, {
rawArgs: ['--match-filter', 'duration > 60', '--geo-bypass'],
});
await ytdlp.execAsync(url, {
debugPrintCommandLine: true,
verbose: true,
});
import { helpers } from 'ytdlp-nodejs';
await helpers.downloadYtDlp();
await helpers.downloadFFmpeg();
Or provide custom paths:
const ytdlp = new YtDlp({
binaryPath: '/path/to/yt-dlp',
ffmpegPath: '/path/to/ffmpeg',
});
🚀 NextDownloader.com - A video downloader I built using this library. Check it out and let me know what you think! Your feedback is greatly appreciated.
Contributions are welcome! Please feel free to submit a Pull Request or open an issue on GitHub.
FAQs
A TypeScript wrapper for the yt-dlp executable
The npm package ytdlp-nodejs receives a total of 1,637 weekly downloads. As such, ytdlp-nodejs popularity was classified as popular.
We found that ytdlp-nodejs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
npm now links to Socket's security analysis on every package page. Here's what you'll find when you click through.

Security News
A compromised npm publish token was used to push a malicious postinstall script in cline@2.3.0, affecting the popular AI coding agent CLI with 90k weekly downloads.

Product
Socket is now scanning AI agent skills across multiple languages and ecosystems, detecting malicious behavior before developers install, starting with skills.sh's 60,000+ skills.