Skip to content
Manojbabu edited this page Mar 24, 2026 · 10 revisions

Ytdlp.NET

Static Badge NuGet Version NuGet Downloads

Ytdlp.NET is an open-source, modern .NET wrapper library for yt-dlp, the popular command-line audio/video downloader and metadata extractor.
It provides a fluent, strongly-typed API to build yt-dlp commands, fetch rich metadata, list formats, monitor progress, and execute downloads with full event support.

Ytdlp.NET
Developer Manojbabu (manusoft/manuhub)
Initial release 2025
Stable release 3.0.0
Repository github.com/manusoft/Ytdlp.NET
Written in C# (.NET 8.0 or later)
License MIT
Website https://github.com/manusoft/Ytdlp.NET

✨ Features

  • Fluent API (WithXxx() methods)
  • Immutable design (thread‑safe instances)
  • Real‑time progress events
  • Metadata & format probing
  • Batch downloads
  • Cancellation support
  • Cross‑platform support
  • Strongly typed event system
  • Async execution
  • IAsyncDisposable support

⚠️ Important Notes

  • Namespace migrated: ManuHub.Ytdlp.NET — update your using directives.
  • External JS runtime: yt-dlp requires an external JS runtime like deno.exe (from denoland/deno) for YouTube downloads with JS challenges.
  • Required tools:
Tools/
├─ yt-dlp.exe
├─ deno.exe
├─ ffmpeg.exe
└─ ffprobe.exe

Recommended: Use companion NuGet packages:

  • ManuHub.Ytdlp
  • ManuHub.Deno
  • ManuHub.FFmpeg
  • ManuHub.FFprobe

Example path resolution in .NET:

var ytdlpPath = Path.Combine(AppContext.BaseDirectory, "tools", "yt-dlp.exe");
var ffmpegPath = Path.Combine(AppContext.BaseDirectory, "tools");

🔧 Basic Usage

Download a video

await using var ytdlp = new Ytdlp("tools\\yt-dlp.exe")
    .WithFormat("best")
    .WithOutputFolder("./downloads")
    .WithOutputTemplate("%(title)s.%(ext)s");

ytdlp.OnProgressDownload += (s, e) =>
    Console.WriteLine($"{e.Percent:F1}% {e.Speed} ETA {e.ETA}");

await ytdlp.DownloadAsync("https://www.youtube.com/watch?v=VIDEO_ID");

🎧 Extract audio

await using var ytdlp = new Ytdlp()
    .WithExtractAudio("mp3")
    .WithOutputFolder("./audio");

await ytdlp.DownloadAsync(url);

📊 Monitor Progress

ytdlp.OnProgressDownload += (s, e) =>
{
    Console.WriteLine($"{e.Percent:F1}%  {e.Speed}  ETA {e.ETA}");
};

ytdlp.OnCompleteDownload += (s, msg) =>
{
    Console.WriteLine($"Finished: {msg}");
};

📦 Fetch Metadata

await using var ytdlp = new Ytdlp();

var metadata = await ytdlp.GetMetadataAsync(url);

Console.WriteLine(metadata?.Title);
Console.WriteLine(metadata?.Duration);

🎬 Auto‑Select Best Formats

await using var ytdlp = new Ytdlp();

string bestVideo = await ytdlp.GetBestVideoFormatIdAsync(url, 1080);
string bestAudio = await ytdlp.GetBestAudioFormatIdAsync(url);

await ytdlp
    .WithFormat($"{bestVideo}+{bestAudio}/best")
    .DownloadAsync(url);

⚡ Parallel Downloads

var urls = new[]
{
    "https://youtu.be/video1",
    "https://youtu.be/video2"
};

var tasks = urls.Select(async url =>
{
    await using var ytdlp = new Ytdlp()
        .WithFormat("best")
        .WithOutputFolder("./batch");

    await ytdlp.DownloadAsync(url);
});

await Task.WhenAll(tasks);

OR

var urls = new[] { "https://youtu.be/vid1", "https://youtu.be/vid2" };

 await using var ytdlp = new Ytdlp("tools\\yt-dlp.exe")
        .WithFormat("best")
        .WithOutputFolder("./batch");

await ytdlp.DownloadBatchAsync(urls, maxConcurrency: 3);

📡 Events

Event Description
OnProgressDownload Download progress
OnProgressMessage Informational messages
OnCompleteDownload File finished
OnPostProcessingComplete Post‑processing finished
OnOutputMessage Raw output line
OnErrorMessage Error message
OnCommandCompleted Process finished

🔧 Thread Safety & Disposal

  • Immutable & thread-safe: Each WithXxx() call returns a new instance.
  • Async disposal: Ytdlp implements IAsyncDisposable.

Sequential download example:

await using var ytdlp = new Ytdlp("tools\\yt-dlp.exe", new ConsoleLogger())
    .WithFormat("best")
    .WithOutputFolder("./downloads");

ytdlp.OnProgressDownload += (s, e) => Console.WriteLine($"Progress: {e.Percent:F2}%");
ytdlp.OnCompleteDownload += (s, msg) => Console.WriteLine($"Download complete: {msg}");

await ytdlp.DownloadAsync("https://www.youtube.com/watch?v=RGg-Qx1rL9U");

Parallel download example:

var urls = new[] { "https://youtu.be/video1", "https://youtu.be/video2" };

var tasks = urls.Select(async url =>
{
    await using var ytdlp = new Ytdlp("tools\\yt-dlp.exe", new ConsoleLogger())
        .WithFormat("best")
        .WithOutputFolder("./batch");

    ytdlp.OnProgressDownload += (s, e) => Console.WriteLine($"[{url}] {e.Percent:F2}%");
    ytdlp.OnCompleteDownload += (s, msg) => Console.WriteLine($"[{url}] Download complete: {msg}");

    await ytdlp.DownloadAsync(url);
});

await Task.WhenAll(tasks);

Key points:

  1. Always create a new instance per download for parallel operations.
  2. Always use await using for proper resource cleanup.
  3. Attach events after the WithXxx() call.

Dependencies

  • .NET 8.0 or later
  • yt-dlp executable (required)
  • FFmpeg / FFprobe (recommended for merging, audio extraction, thumbnails)

See also

References

  1. GitHub repository: https://github.com/manusoft/Ytdlp.NET
  2. yt-dlp releases: https://github.com/yt-dlp/yt-dlp/releases
  3. FFmpeg builds: https://www.gyan.dev/ffmpeg/builds/

This page was last edited on MArch 24, 2026.

Clone this wiki locally