npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

Readme

cdxdl 🎬

cdxdl by alfi dev
github.com/claidexdev | github.com/cloudkuimages
Telegram: @claidex

npm version downloads license

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 tersedia

ytdl.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'); // false

ytdl.validateURL(url: string): boolean

Validasi apakah string adalah YouTube URL yang valid.

ytdl.validateURL('https://youtu.be/dQw4w9WgXcQ'); // true

ytdl.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(), bukan getBasicInfo().

ytdl.Spodl(link: string, options?: Options): StreamCustom 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 dibatalkan
  • request - HTTP request dimulai
  • response - HTTP response diterima
  • redirect - Terjadi redirect
  • retry - Retry attempt
  • reconnect - 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:


⚠️ 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