YouTube video downloader in pure JavaScript with streaming interface and comprehensive metadata extraction.
Core streaming download functionality for YouTube videos with extensive configuration options, progress tracking, and support for various video formats including live streams.
Downloads a YouTube video and returns a readable stream with comprehensive options for customization.
/**
* Downloads a YouTube video and returns a readable stream
* @param {string} url - YouTube video URL or video ID
* @param {downloadOptions} options - Download configuration options
* @returns {stream.Readable} - Readable stream of video data
*/
function ytdl(url, options);
interface downloadOptions {
// Range options
range?: {
start?: number; // Start byte position
end?: number; // End byte position
};
// Timing options
begin?: string | number | Date; // Start time (e.g., '1:30', '05:10.123', '10m30s')
liveBuffer?: number; // Live stream buffer in milliseconds (default: 20000)
// Stream options
highWaterMark?: number; // Buffer size in bytes (default: 512KB)
dlChunkSize?: number; // Chunk size for video-only/audio-only downloads (default: 10MB, 0 to disable)
// Network options
IPv6Block?: string; // IPv6 block for request rotation
requestOptions?: object; // Options passed to miniget
requestCallback?: function; // Callback for request streams
// Format selection (inherited from chooseFormatOptions)
quality?: string | number | string[] | number[];
filter?: string | function;
format?: object;
// Info options (inherited from getInfoOptions)
lang?: string; // Language code (default: 'en')
}Usage Examples:
const ytdl = require('ytdl-core');
const fs = require('fs');
// Basic download
ytdl('https://www.youtube.com/watch?v=aqz-KE-bpKQ')
.pipe(fs.createWriteStream('video.mp4'));
// Download with range (bytes 1000-5000)
ytdl(videoUrl, {
range: { start: 1000, end: 5000 }
}).pipe(outputStream);
// Download starting from specific time
ytdl(videoUrl, {
begin: '1:30' // Start at 1 minute 30 seconds
}).pipe(outputStream);
// Download with specific quality
ytdl(videoUrl, {
quality: 'highestaudio'
}).pipe(outputStream);
// Download with IPv6 rotation
ytdl(videoUrl, {
IPv6Block: '2001:2::/48'
}).pipe(outputStream);Downloads video using previously fetched video information, useful when you want to examine video details before downloading.
/**
* Downloads video using pre-fetched info object
* @param {videoInfo} info - Video info from getInfo() (must have full: true)
* @param {downloadOptions} options - Download options
* @returns {stream.Readable} - Readable stream of video data
* @throws {Error} - If info is from getBasicInfo() (full: false)
*/
function downloadFromInfo(info, options);Usage Examples:
// Get info first, then download
const info = await ytdl.getInfo(videoUrl);
console.log(`Downloading: ${info.videoDetails.title}`);
const stream = ytdl.downloadFromInfo(info, {
quality: 'highest'
});
stream.pipe(fs.createWriteStream('video.mp4'));The returned stream emits several events for monitoring download progress and handling responses.
Emitted when video information is fetched and format is chosen.
/**
* Emitted when video info is fetched and format is selected
* @param {videoInfo} info - Complete video information
* @param {videoFormat} format - Selected format for download
*/
stream.on('info', (info, format) => {
console.log(`Title: ${info.videoDetails.title}`);
console.log(`Format: ${format.qualityLabel} ${format.container}`);
});Emitted during download to track progress.
/**
* Emitted during download for progress tracking
* @param {number} chunkLength - Length of current chunk or segment number
* @param {number} downloaded - Total bytes downloaded or segments completed
* @param {number} total - Total bytes or total segments
*/
stream.on('progress', (chunkLength, downloaded, total) => {
const percent = downloaded / total * 100;
console.log(`Downloaded ${percent.toFixed(1)}%`);
});All miniget request events are forwarded and can be listened to:
// Network events forwarded from miniget
stream.on('request', (req) => { /* HTTP request started */ });
stream.on('response', (res) => { /* HTTP response received */ });
stream.on('redirect', (url) => { /* Request redirected */ });
stream.on('retry', (retryCount) => { /* Request retried */ });
stream.on('reconnect', (reconnectCount) => { /* Connection reconnected */ });
stream.on('abort', () => { /* Request aborted */ });
stream.on('error', (err) => { /* Error occurred */ });Aborts and stops downloading a video.
/**
* Aborts the download and destroys the stream
*/
stream.destroy();Usage Example:
const stream = ytdl(videoUrl);
stream.pipe(outputStream);
// Abort after 5 seconds
setTimeout(() => {
stream.destroy();
console.log('Download aborted');
}, 5000);Specify byte ranges for partial content downloads (not supported for segmented formats).
// Download first 1MB
ytdl(url, { range: { start: 0, end: 1024 * 1024 } })
// Download from 1MB onwards
ytdl(url, { range: { start: 1024 * 1024 } })Start downloading from specific timestamps.
// Various time formats supported
ytdl(url, { begin: '1:30' }) // 1 minute 30 seconds
ytdl(url, { begin: '05:10.123' }) // 5 minutes 10.123 seconds
ytdl(url, { begin: '10m30s' }) // 10 minutes 30 seconds
ytdl(url, { begin: 90000 }) // 90 seconds (milliseconds)
// For live videos, use Unix timestamp or Date
ytdl(liveUrl, { begin: Date.now() }) // Start from now
ytdl(liveUrl, { begin: new Date('2023-01-01T10:00:00Z') })Use IPv6 address rotation to avoid rate limiting.
ytdl(url, {
IPv6Block: '2001:2::/48' // Rotates through IPv6 addresses in this block
})Control download chunking for video-only or audio-only formats.
ytdl(url, {
dlChunkSize: 1024 * 1024 * 5 // 5MB chunks (default: 10MB)
})
ytdl(url, {
dlChunkSize: 0 // Disable chunking
})Common errors and how to handle them:
const stream = ytdl(url);
stream.on('error', (err) => {
if (err.message.includes('unavailable')) {
console.error('Video is unavailable');
} else if (err.message.includes('private')) {
console.error('Video is private');
} else if (err.statusCode === 429) {
console.error('Rate limited - try using proxies or IPv6 rotation');
} else {
console.error('Download error:', err.message);
}
});Install with Tessl CLI
npx tessl i tessl/npm-ytdl-core