cdxdl
v1.0.0
Published
High-performance YouTube downloader powered by InnerTube clients with automatic signature deciphering. Supports audio/video streaming, adaptive formats, restricted content (cookies), and multi-client fallback (WEB, ANDROID, IOS, VR). Built for speed, reli
Downloads
9
Maintainers
Readme
cdxdl 🎬
cdxdl by alfi dev
github.com/claidexdev | github.com/cloudkuimages
Telegram: @claidex
Library Node.js untuk mendownload video/audio dari YouTube dengan performa tinggi dan kompatibel 100% dengan ytdl-core.
✨ Features
✅ Android InnerTube Client - Reliable format extraction menggunakan YouTube's official Android API
✅ Automatic Signature Decoding - Menangani encrypted format URLs secara transparan
✅ Restricted Videos - Download video age-restricted dan region-locked dengan cookies
✅ Multi-threading - Download paralel cepat dengan multiple connections
✅ 100% API Compatible - Drop-in replacement untuk ytdl-core
✅ Production Ready - Stabil dan teruji dengan YouTube 2025
📦 Installation
npm install cdxdl
# atau
yarn add cdxdl
# atau
pnpm add cdxdl🚀 Usage
CommonJS
const ytdl = require('cdxdl');
// Download video
const stream = ytdl('https://www.youtube.com/watch?v=VIDEO_ID', {
quality: 'highest',
filter: 'audioonly'
});
stream.pipe(require('fs').createWriteStream('output.mp4'));ESM (ECMAScript Modules)
import * as ytdl from 'cdxdl';
// Download audio only dengan method Spodl
const stream = await ytdl.Spodl('https://www.youtube.com/watch?v=VIDEO_ID');
stream.pipe(require('fs').createWriteStream('audio.mp3'));Async/Await Example
import * as ytdl from 'cdxdl';
import { createWriteStream } from 'fs';
async function downloadVideo(url, path) {
try {
const info = await ytdl.getInfo(url);
const format = ytdl.chooseFormat(info.formats, { quality: 'highest' });
const stream = ytdl(url, { format });
stream.on('progress', (chunk, downloaded, total) => {
const percent = ((downloaded / total) * 100).toFixed(2);
console.log(`Progress: ${percent}%`);
});
stream.pipe(createWriteStream(path));
return new Promise((resolve, reject) => {
stream.on('end', resolve);
stream.on('error', reject);
});
} catch (err) {
console.error('Download failed:', err);
throw err;
}
}📚 API Reference
Main Function
ytdl(link: string, options?: Options): Stream
Fungsi utama untuk mendownload video/audio dari YouTube.
const stream = ytdl('https://youtu.be/dQw4w9WgXcQ', {
quality: '18', // atau 'highest', 'lowest', itag number
filter: 'audioonly', // 'videoandaudio', 'videoonly', 'audioonly'
dlChunkSize: 1024 * 512, // ukuran chunk download
range: { start: 0, end: 1000000 }, // download partial
begin: '1:30', // mulai dari timestamp
requestOptions: { headers: { 'User-Agent': '...' } },
IPv6Block: '2001:db8::/64', // rotasi IPv6
agent: customAgent, // custom HTTP agent
highWaterMark: 1024 * 512 // buffer size
});Info Methods
ytdl.getInfo(link: string, options?: Options): Promise<VideoInfo>
Mengambil informasi lengkap video termasuk semua format yang tersedia.
const info = await ytdl.getInfo('https://youtu.be/VIDEO_ID');
console.log(info.videoDetails.title);
console.log(info.formats); // array format tersediaytdl.getBasicInfo(link: string, options?: Options): Promise<BasicVideoInfo>
Mengambil informasi dasar video (lebih cepat, tapi format terbatas).
const basicInfo = await ytdl.getBasicInfo('https://youtu.be/VIDEO_ID');
console.log(basicInfo.videoDetails.title);Format Utilities
ytdl.chooseFormat(formats: Format[], options: FormatOptions): Format
Memilih format terbaik berdasarkan opsi yang diberikan.
const format = ytdl.chooseFormat(info.formats, {
quality: 'highest',
filter: 'audioonly'
});ytdl.filterFormats(formats: Format[], filter: FilterType): Format[]
Memfilter array format berdasarkan tipe.
// Filter: 'video', 'videoandaudio', 'audio', 'videoonly', 'audioonly', 'm3u8', 'dash-mpd'
const audioOnly = ytdl.filterFormats(info.formats, 'audioonly');URL Utilities
ytdl.validateID(id: string): boolean
Validasi apakah string adalah YouTube Video ID yang valid.
ytdl.validateID('dQw4w9WgXcQ'); // true
ytdl.validateID('invalid-id'); // falseytdl.validateURL(url: string): boolean
Validasi apakah string adalah YouTube URL yang valid.
ytdl.validateURL('https://youtu.be/dQw4w9WgXcQ'); // trueytdl.getURLVideoID(url: string): string
Ekstrak Video ID dari YouTube URL.
ytdl.getURLVideoID('https://youtu.be/dQw4w9WgXcQ?t=30'); // 'dQw4w9WgXcQ'ytdl.getVideoID(str: string): string
Ekstrak Video ID dari URL atau ID langsung.
ytdl.getVideoID('dQw4w9WgXcQ'); // 'dQw4w9WgXcQ'
ytdl.getVideoID('https://youtube.com/watch?v=dQw4w9WgXcQ'); // 'dQw4w9WgXcQ'Agent & Proxy
ytdl.createAgent(options?: AgentOptions): Agent
Membuat custom HTTP agent dengan cookie support.
const agent = ytdl.createAgent({
cookies: 'sessionid=xxx; pref=yyy'
});
const stream = ytdl('https://youtu.be/PRIVATE_VIDEO', { agent });ytdl.createProxyAgent(proxyUrl: string): Agent
Membuat agent dengan proxy support.
const proxyAgent = ytdl.createProxyAgent('http://localhost:8080');
const stream = ytdl(url, { agent: proxyAgent });Special Methods
ytdl.downloadFromInfo(info: VideoInfo, options?: Options): Stream
Download langsung dari objek info yang sudah diambil sebelumnya.
const info = await ytdl.getInfo(url);
const stream = ytdl.downloadFromInfo(info, { quality: 'highest' });⚠️ Note: Hanya bekerja dengan info dari
getInfo(), bukangetBasicInfo().
ytdl.Spodl(link: string, options?: Options): Stream ⭐ Custom Method
Method khusus untuk download audio-only dengan kualitas terbaik menggunakan Android InnerTube client.
// ESM
import * as ytdl from 'cdxdl';
const stream = ytdl.Spodl('https://youtu.be/VIDEO_ID', {
// options tambahan (opsional)
liveBuffer: 20000,
highWaterMark: 1024 * 512
});
stream.on('info', (info, format) => {
console.log(`Downloading: ${info.videoDetails.title}`);
console.log(`Format: ${format.audioBitrate}kbps`);
});
stream.on('progress', (chunk, downloaded, total) => {
const percent = ((downloaded / total) * 100).toFixed(1);
console.log(`📥 ${percent}%`);
});
stream.pipe(require('fs').createWriteStream('audio.m4a'));Properties
ytdl.cache
Akses ke cache internal library.
// Clear cache info
ytdl.cache.info.clear();
// Clear watch page cache
ytdl.cache.watch.clear();ytdl.version
Versi library yang terinstall.
console.log(ytdl.version); // '1.0.0'🎯 Options Reference
Download Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| quality | string \| number | 'highest' | Kualitas video: 'lowest', 'highest', 'audioonly', atau itag number |
| filter | string | null | Filter format: 'video', 'audio', 'videoonly', 'audioonly', 'm3u8', 'dash-mpd' |
| format | Format | null | Format spesifik yang ingin didownload |
| range | object | null | Download partial: { start: number, end: number } |
| begin | string \| number | null | Mulai download dari timestamp: '1:30' atau 90 (detik) |
| dlChunkSize | number | 524288 | Ukuran chunk download (0 = disable chunking) |
| highWaterMark | number | 524288 | Buffer size untuk stream |
| IPv6Block | string | null | IPv6 block untuk rotasi IP |
| liveBuffer | number | 40000 | Buffer size untuk live stream |
| requestOptions | object | {} | Custom options untuk HTTP request |
| agent | Agent | null | Custom HTTP agent dengan cookie/proxy |
Format Options (untuk chooseFormat)
| Option | Type | Description |
|--------|------|-------------|
| quality | string \| number | Target kualitas: 'lowest', 'highest', 'audioonly', atau itag |
| filter | string | Filter format yang diinginkan |
| format | object | Format object spesifik |
📡 Events
Stream yang dikembalikan oleh ytdl() dan ytdl.Spodl() mendukung events berikut:
info
Dipancarkan ketika informasi video dan format tersedia.
stream.on('info', (info, format) => {
console.log('Title:', info.videoDetails.title);
console.log('Format:', format.itag, format.qualityLabel);
});progress
Dipancarkan secara berkala selama download.
stream.on('progress', (chunk, downloaded, total) => {
const percent = ((downloaded / total) * 100).toFixed(2);
console.log(`📥 ${percent}% - ${downloaded}/${total} bytes`);
});error
Dipancarkan ketika terjadi error.
stream.on('error', (err) => {
console.error('Download error:', err.message);
});end
Dipancarkan ketika download selesai.
stream.on('end', () => {
console.log('✅ Download completed!');
});Network Events
Events dari underlying HTTP request:
abort- Request dibatalkanrequest- HTTP request dimulairesponse- HTTP response diterimaredirect- Terjadi redirectretry- Retry attemptreconnect- Reconnect attempt
stream.on('response', (res) => {
console.log('Status:', res.statusCode);
});🔧 Advanced Examples
Download dengan Cookies (untuk video restricted)
import * as ytdl from 'cdxdl';
import { createWriteStream } from 'fs';
const agent = ytdl.createAgent({
cookies: 'SID=xxx; HSID=yyy; APISID=zzz' // cookie dari browser
});
const stream = ytdl('https://youtu.be/AGE_RESTRICTED', {
quality: 'highest',
agent
});
stream.pipe(createWriteStream('video.mp4'));Download dengan Proxy
const proxyAgent = ytdl.createProxyAgent('http://user:pass@proxy:8080');
const stream = ytdl(url, {
quality: '18',
agent: proxyAgent
});Download dengan IPv6 Rotation
const stream = ytdl(url, {
quality: 'highest',
IPv6Block: '2001:db8::/64' // akan rotasi IP dari block ini
});Download Live Stream
const stream = ytdl('https://youtu.be/LIVE_VIDEO', {
filter: 'audioonly',
liveBuffer: 60000 // buffer lebih besar untuk live
});
stream.pipe(require('fs').createWriteStream('live.aac'));Download dengan Timestamp Begin
// Mulai dari 2 menit 30 detik
const stream = ytdl(url, {
begin: '2:30', // atau begin: 150 (dalam detik)
quality: 'highest'
});🧪 Error Handling
import * as ytdl from 'cdxdl';
async function safeDownload(url, path) {
try {
// Validasi URL dulu
if (!ytdl.validateURL(url)) {
throw new Error('Invalid YouTube URL');
}
const stream = ytdl(url, { quality: 'highest' });
return new Promise((resolve, reject) => {
stream.on('error', (err) => {
// Handle error spesifik
if (err.message.includes('unavailable')) {
reject(new Error('Video tidak tersedia di region Anda'));
} else if (err.message.includes('age-restricted')) {
reject(new Error('Video age-restricted, gunakan cookies'));
} else {
reject(err);
}
});
stream.on('end', resolve);
stream.pipe(createWriteStream(path));
});
} catch (err) {
console.error('❌ Download failed:', err.message);
throw err;
}
}🗂️ Format Object Properties
Format object yang dikembalikan memiliki properti berikut:
{
itag: number, // YouTube format identifier
mimeType: string, // 'video/mp4; codecs="avc1.64001F, mp4a.40.2"'
bitrate: number, // Bitrate dalam bps
width: number, // Lebar video (jika ada)
height: number, // Tinggi video (jika ada)
contentLength: string, // Ukuran file dalam bytes
quality: string, // 'medium', 'small', 'hd720', dll
qualityLabel: string, // '720p', '1080p', dll
audioBitrate: number, // Audio bitrate (jika ada)
hasAudio: boolean, // Apakah format memiliki audio
hasVideo: boolean, // Apakah format memiliki video
isLive: boolean, // Apakah ini live stream
isHLS: boolean, // Apakah format HLS/m3u8
isDashMPD: boolean, // Apakah format DASH/MPD
url: string // URL download (signed)
}📄 License
Distributed under the MIT License. See LICENSE for more information.
☕ Support Developer
Jika library ini membantu project Anda, Anda bisa support developer:
- Telegram: @claidex
- GitHub: claidexdev | cloudkuimages
⚠️ Disclaimer: Library ini dibuat untuk tujuan edukasi. Pastikan Anda mematuhi YouTube Terms of Service dan menghormati hak cipta konten creator.
cdxdl by alfi dev - Made with ❤️ for the community