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

ytmusic-advanced

v1.1.0

Published

Advanced YouTube Music API client for searching and retrieving music data including songs, albums, artists, and playlists

Downloads

15

Readme

ytmusic-advanced: Complete Integration Guide

🎯 Overview

ytmusic-advanced is now a fully self-contained YouTube Music/YouTube API client that eliminates the need for:

  • ❌ @distube/ytdl-core
  • ❌ YouTube.js
  • ❌ ytmusicapi

Everything you need is built-in with superior reliability and performance.


🚀 Quick Start

Installation

npm install ytmusic-advanced

Basic Usage

import YTMusicAdvanced from "ytmusic-advanced";

// Initialize client
const client = await YTMusicAdvanced.initialize({
  cacheEnabled: true,
  timeout: 20000,
});

// Search with intelligent ranking
const results = await client.searchMusic("Shape of You Ed Sheeran");

// Get direct audio URLs
const audioData = await client.getAudioURLs(results.items[0].videoId);

console.log("Direct Audio URL:", audioData.bestAudio.url);
console.log("Bitrate:", audioData.bestAudio.bitrate);
console.log("Expires At:", audioData.expiresAt);

🎵 Complete Feature Guide

1. Intelligent Search

Search with automatic quality filtering and relevance scoring:

// High-quality music search
const results = await client.searchMusic("Imagine Dragons Bones", {
  limit: 10,
  preferOfficial: true,
  minRelevanceScore: 0.6,
});

// Each result includes:
// - Relevance score (0-1)
// - Quality score (0-1)
// - Authenticity score (0-1)
// - Technical quality score (0-1)

results.items.forEach((item) => {
  console.log(`${item.rank}. ${item.title}`);
  console.log(`   Score: ${item.totalScore.toFixed(2)}`);
  console.log(`   Quality: ${item.scores.quality.toFixed(2)}`);
});

2. Direct Audio URL Extraction

Get playable audio URLs with multiple quality options:

const audioData = await client.getAudioURLs("dQw4w9WgXcQ");

if (audioData.success) {
  // Best quality audio
  console.log("Best Audio:", audioData.bestAudio.url);

  // All available formats
  console.log(`Found ${audioData.formats.length} formats`);

  // Filtered by quality
  console.log("High Quality:", audioData.audioByQuality.high);
  console.log("Medium Quality:", audioData.audioByQuality.medium);
  console.log("Low Quality:", audioData.audioByQuality.low);

  // Metadata
  console.log("Title:", audioData.title);
  console.log("Duration:", audioData.duration, "seconds");
  console.log("URL expires:", audioData.expiresAt);
}

3. Search + Audio URLs (One Call)

Get search results with direct playback URLs:

const results = await client.searchWithAudio("Coldplay Yellow", {
  limit: 5,
  maxAudioFetches: 3, // Fetch URLs for top 3 results
});

results.items.forEach((item) => {
  if (item.audioData) {
    console.log(`✅ ${item.title}`);
    console.log(`   Play: ${item.audioData.directURL}`);
  } else {
    console.log(`⏳ ${item.title} (audio not fetched)`);
  }
});

4. Advanced Search with Filters

const results = await client.advancedSearch("The Weeknd", {
  contentType: "official", // 'official', 'lyrics', 'audio', 'video'
  minDuration: 120, // At least 2 minutes
  maxDuration: 360, // At most 6 minutes
  quality: "high", // 'high', 'medium', 'low'
  sortBy: "quality", // 'relevance', 'quality', 'popularity'
});

5. Quick Search (Fast Response)

Get first 5 high-quality results quickly:

const results = await client.quickSearch("Travis Scott");

// Returns only top 5 results with quick processing

🔧 Advanced Configuration

With IP Rotation (For High-Volume Usage)

const client = await YTMusicAdvanced.initialize({
  cacheEnabled: true,
  timeout: 20000,

  // IP rotation (optional)
  enableIPRotation: true,
  proxyList: [
    { host: "proxy1.example.com", port: 8080 },
    { host: "proxy2.example.com", port: 8080 },
    { host: "proxy3.example.com", port: 8080 },
  ],

  // Retry configuration
  maxRetries: 3,
  retryDelay: 1000,

  // Cache settings
  cacheTTL: 300000, // 5 minutes
});

Mode Switching

// Start in YouTube Music mode
const client = await YTMusicAdvanced.initialize({ mode: "music" });

// Switch to regular YouTube
client.switchMode("youtube");

// Switch back to Music
client.switchMode("music");

📊 Real-World Examples

Example 1: Music Player Integration

class MusicPlayer {
  constructor() {
    this.client = null;
    this.currentTrack = null;
  }

  async initialize() {
    this.client = await YTMusicAdvanced.initialize({
      cacheEnabled: true,
      timeout: 15000,
    });
  }

  async search(query) {
    const results = await this.client.searchMusic(query, {
      limit: 20,
      minRelevanceScore: 0.5,
    });

    return results.items.map((item) => ({
      id: item.videoId,
      title: item.title,
      artist: item.artists?.[0]?.name || "Unknown",
      duration: item.duration,
      thumbnail: item.thumbnails?.[0]?.url,
      score: item.totalScore,
    }));
  }

  async play(videoId) {
    const audioData = await this.client.getAudioURLs(videoId);

    if (!audioData.success) {
      throw new Error("Failed to get audio URL");
    }

    this.currentTrack = {
      videoId,
      title: audioData.title,
      url: audioData.bestAudio.url,
      expiresAt: new Date(audioData.expiresAt),
    };

    return this.currentTrack.url;
  }

  needsRefresh() {
    if (!this.currentTrack) return false;
    return new Date() >= this.currentTrack.expiresAt;
  }

  async refreshURL() {
    if (!this.currentTrack) return;

    const audioData = await this.client.getAudioURLs(this.currentTrack.videoId);

    this.currentTrack.url = audioData.bestAudio.url;
    this.currentTrack.expiresAt = new Date(audioData.expiresAt);

    return this.currentTrack.url;
  }
}

// Usage
const player = new MusicPlayer();
await player.initialize();

const results = await player.search("Dua Lipa Levitating");
const trackURL = await player.play(results[0].id);

// Play audio using trackURL in your audio player

Example 2: Playlist Downloader

async function downloadPlaylist(playlistName, songs) {
  const client = await YTMusicAdvanced.initialize();
  const downloads = [];

  for (const song of songs) {
    try {
      // Search for song
      const results = await client.searchMusic(song, {
        limit: 1,
        preferOfficial: true,
      });

      if (results.items.length === 0) {
        console.log(`❌ Not found: ${song}`);
        continue;
      }

      const track = results.items[0];

      // Get audio URL
      const audioData = await client.getAudioURLs(track.videoId);

      if (audioData.success) {
        downloads.push({
          title: track.title,
          artist: track.artists?.[0]?.name,
          url: audioData.bestAudio.url,
          quality: audioData.bestAudio.quality,
          bitrate: audioData.bestAudio.bitrate,
        });

        console.log(`✅ ${track.title} - ${audioData.bestAudio.quality}`);
      }

      // Rate limiting
      await new Promise((resolve) => setTimeout(resolve, 1000));
    } catch (error) {
      console.error(`❌ Error: ${song}`, error.message);
    }
  }

  return downloads;
}

// Usage
const songs = [
  "The Weeknd Blinding Lights",
  "Doja Cat Paint The Town Red",
  "Taylor Swift Anti-Hero",
];

const downloads = await downloadPlaylist("My Playlist", songs);

Example 3: Music Discovery API

import express from "express";
import YTMusicAdvanced from "ytmusic-advanced";

const app = express();
const client = await YTMusicAdvanced.initialize();

// Search endpoint
app.get("/api/search", async (req, res) => {
  try {
    const { q, limit = 10 } = req.query;

    const results = await client.searchMusic(q, {
      limit: parseInt(limit),
      minRelevanceScore: 0.5,
    });

    res.json({
      success: true,
      query: q,
      results: results.items.map((item) => ({
        id: item.videoId,
        title: item.title,
        artist: item.artists?.[0]?.name,
        duration: item.duration,
        thumbnail: item.thumbnails?.[0]?.url,
        quality_score: item.scores.quality,
        relevance_score: item.scores.relevance,
      })),
    });
  } catch (error) {
    res.status(500).json({ success: false, error: error.message });
  }
});

// Stream endpoint
app.get("/api/stream/:videoId", async (req, res) => {
  try {
    const { videoId } = req.params;

    const audioData = await client.getAudioURLs(videoId);

    if (!audioData.success) {
      return res.status(404).json({ success: false, error: "Not found" });
    }

    res.json({
      success: true,
      stream_url: audioData.bestAudio.url,
      expires_at: audioData.expiresAt,
      metadata: {
        title: audioData.title,
        author: audioData.author,
        duration: audioData.duration,
        thumbnail: audioData.thumbnail?.url,
      },
      formats: audioData.formats.map((f) => ({
        quality: f.quality,
        bitrate: f.bitrate,
        codec: f.codec,
        container: f.container,
        url: f.url,
      })),
    });
  } catch (error) {
    res.status(500).json({ success: false, error: error.message });
  }
});

app.listen(3000, () => {
  console.log("Music API running on http://localhost:3000");
});

🛡️ Error Handling

try {
  const audioData = await client.getAudioURLs(videoId);

  if (!audioData.success) {
    console.error("Extraction failed:", audioData.error);
    // Handle gracefully
  }

  // Check expiry
  const expiryTime = new Date(audioData.expiresAt);
  if (expiryTime < new Date()) {
    console.warn("URL already expired, refreshing...");
    // Refresh URL
  }
} catch (error) {
  if (error.code === "NETWORK_ERROR") {
    console.error("Network issue, retry later");
  } else if (error.code === "RATE_LIMIT_ERROR") {
    console.error("Rate limited, wait before retry");
  } else {
    console.error("Unexpected error:", error.message);
  }
}

🎯 Best Practices

1. Cache Management

// Enable caching for better performance
const client = await YTMusicAdvanced.initialize({
  cacheEnabled: true,
  cacheTTL: 300000, // 5 minutes
});

// Clear cache when needed
await client.clearCache();

// Get cache stats
const stats = client.getStatus();
console.log("Cache size:", stats.cacheSize);

2. Rate Limiting

// Built-in rate limiting (1 request per second)
// For high-volume usage, add delays:

const results = await client.searchMusic(query);

for (const item of results.items) {
  const audio = await client.getAudioURLs(item.videoId);
  await new Promise((resolve) => setTimeout(resolve, 1000));
}

3. URL Expiry Handling

class AudioURLManager {
  constructor(client) {
    this.client = client;
    this.urlCache = new Map();
  }

  async getURL(videoId) {
    const cached = this.urlCache.get(videoId);

    // Check if cached and not expired
    if (cached && new Date(cached.expiresAt) > new Date()) {
      return cached.url;
    }

    // Fetch new URL
    const audioData = await this.client.getAudioURLs(videoId);

    this.urlCache.set(videoId, {
      url: audioData.bestAudio.url,
      expiresAt: audioData.expiresAt,
    });

    return audioData.bestAudio.url;
  }
}

📈 Performance Tips

  1. Enable caching - Reduces API calls by 70-80%
  2. Use quick search for instant results
  3. Limit audio fetches in bulk operations
  4. Implement IP rotation for high-volume usage
  5. Monitor expiry times and refresh URLs proactively

🔍 Comparison with Other Libraries

| Feature | ytmusic-advanced | @distube/ytdl-core | YouTube.js | | -------------------- | ---------------- | ------------------ | ---------- | | Audio URL Extraction | ✅ Built-in | ✅ Yes | ✅ Yes | | Search | ✅ Intelligent | ❌ No | ✅ Yes | | Quality Scoring | ✅ Yes | ❌ No | ❌ No | | Signature Handling | ✅ Automatic | ✅ Yes | ✅ Yes | | IP Rotation | ✅ Yes | ❌ No | ❌ No | | Caching | ✅ Multi-tier | ❌ No | ❌ Limited | | TypeScript | ✅ Yes | ✅ Yes | ✅ Yes | | Dependencies | 📦 Minimal | 📦 Many | 📦 Many |


🆘 Troubleshooting

"No streaming data available"

// Try different extraction strategies automatically
const audioData = await client.getAudioURLs(videoId);

// The library tries:
// 1. Android client (most reliable)
// 2. iOS client (fallback)
// 3. Web client (last resort)

"URL expired"

// URLs typically expire after 6 hours
// Refresh when needed:

const needsRefresh = new Date() >= new Date(audioData.expiresAt);
if (needsRefresh) {
  const newAudio = await client.getAudioURLs(videoId);
}

Rate Limiting

// Built-in rate limiting
// For heavy usage, enable IP rotation:

const client = await YTMusicAdvanced.initialize({
  enableIPRotation: true,
  proxyList: [...] // Your proxy list
});

📝 License

MIT License - Feel free to use in commercial projects

🤝 Contributing

Issues and pull requests welcome at: https://github.com/your-repo/ytmusic-advanced


✨ You now have everything you need to build production-ready music applications without any external dependencies!