Ytdlp.NET 4.0.0-preview2

Prefix Reserved
This is a prerelease version of Ytdlp.NET.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Ytdlp.NET --version 4.0.0-preview2
                    
NuGet\Install-Package Ytdlp.NET -Version 4.0.0-preview2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ytdlp.NET" Version="4.0.0-preview2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ytdlp.NET" Version="4.0.0-preview2" />
                    
Directory.Packages.props
<PackageReference Include="Ytdlp.NET" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ytdlp.NET --version 4.0.0-preview2
                    
#r "nuget: Ytdlp.NET, 4.0.0-preview2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ytdlp.NET@4.0.0-preview2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ytdlp.NET&version=4.0.0-preview2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Ytdlp.NET&version=4.0.0-preview2&prerelease
                    
Install as a Cake Tool

Static Badge NuGet Version NuGet Downloads

Ytdlp.NET

Ytdlp.NET is a fluent, strongly-typed, and immutable .NET wrapper around yt-dlp. It provides a fully asynchronous, event-driven interface for downloading, metadata extraction, and media processing from YouTube and hundreds of other platforms.


✨ Features

  • Fluent API: Build yt-dlp commands with WithXxx() methods.
  • Immutable & thread-safe: Each method returns a new instance, safe for parallel usage.
  • Progress & Events: Real-time progress tracking and post-processing notifications.
  • Format Listing: Retrieve and parse available formats.
  • Batch Downloads: Sequential or parallel execution.
  • Output Templates: Flexible naming with yt-dlp placeholders.
  • Custom Command Injection: Add extra yt-dlp options safely.
  • Cross-platform: Windows, macOS, Linux.

🚀 New in v4.0.0

  • Lifecycle Refinement: No disposal required. The library no longer implements IDisposable or IAsyncDisposable. Instances are plain configuration objects.
  • Deep Metadata Support: Added GetDeepMetadataAsync() and GetDeepMetadataRawAsync() for full hierarchical structure (playlists → seasons → episodes).
  • Traverse Helper: New Traverse() method for easy iteration over nested playlist entries.
  • Improved Auth: Enhanced WithAdobePassAuthentication() and WithAuthentication() handling.
  • Subtitle Extraction: New GetSubtitlesAsync() for streamlined subtitle retrieval.
  • MSO Listing: New GetAdobePassListAsync() for Adobe Pass mso listing.
  • Robust Core: Modernized ProcessRunner and ProcessFactory for efficient, isolated execution

🔧 Required Tools

  • Namespace: ManuHub.Ytdlp.NET
  • External JS runtime: yt-dlp requires an external JS runtime like deno.exe (from denoland/deno) for YouTube downloads with JS challenges.
  • Recommended: Use companion NuGet packages:
Package Description
ManuHub.Ytdlp Core download engine
ManuHub.Deno JavaScript challenge resolution
ManuHub.FFmpeg Post-processing, merging, and conversion
ManuHub.FFprobe Format probing and metadata extraction

Example path resolution in .NET:

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

🧬 Core Concepts

No Disposal Required

Ytdlp holds no unmanaged resources. Create instances, share them, and let the GC collect them. All internal runners are created per-call.

Immutable Fluent API

Every configuration method (e.g., WithOutputFolder, WithFormat) returns a new instance, ensuring the original is never modified. This makes branching configurations safe and clean.

Thread Safety

A single Ytdlp instance can be shared across threads. Each execution creates isolated internal runners, allowing concurrent downloads without synchronization.

Secure Authentication

Implemented secure authentication handling for various scenarios, including standard username/password and Adobe Pass authentication.

  • .WithAuthentication(string username, string password)
  • .WithAdobePassAuthentication(string mso, string username, string password)

It securely handles credentials by passing them via standard input to the yt-dlp process, avoiding exposure in command-line arguments or logs. The library ensures that sensitive information is not stored in memory longer than necessary and is properly disposed of after use.


🚀 Quick Start

1. Basic Download

var ytdlp = new Ytdlp("yt-dlp.exe")
    .WithOutputFolder("./downloads")
    .WithBestVideoPlusBestAudio()
    .WithEmbedMetadata();

// Subscribe to events
ytdlp.ProgressDownload += (s, e) => Console.WriteLine($"Progress: {e.Percent:F2}%");
ytdlp.DownloadCompleted += (s, msg) => Console.WriteLine($"Finished: {msg}");

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

2. Immutable Configuration Branching

// Define a shared base configuration
var baseConfig = new Ytdlp("yt-dlp.exe").WithOutputFolder("./media");

// Create specialized versions
var audioOnly = baseConfig.WithBestAudioOnly();
var highRes = baseConfig.WithMaxHeightOrBest(1080);

// baseConfig, audioOnly, and highRes are independent, thread-safe instances
await Task.WhenAll(
    audioOnly.DownloadAsync(url1),
    highRes.DownloadAsync(url2)
);

📦 Usage Examples

Fetch Metadata

var ytdlp = new Ytdlp("tools\\yt-dlp.exe");

var metadata = await ytdlp.GetMetadataAsync("https://www.youtube.com/watch?v=abc123");

Console.WriteLine($"Title: {metadata?.Title}, Duration: {metadata?.Duration}");

Deep Metadata Extraction

var metadata = await ytdlp.GetDeepMetadataAsync(url);

foreach (var root in metadata.Entries ?? [])
{
    foreach (var item in root.Traverse())
    {
        Console.WriteLine(item.Title);
    }
}

Parallel Execution

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

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

// Safe: Concurrent usage of the same instance
await ytdlp.DownloadBatchAsync(urls, maxConcurrency: 3);

Extract Audio

var ytdlp = new Ytdlp("tools\\yt-dlp.exe")
    .WithExtractAudio(AudioFormat.Mp3, 5)
    .WithOutputFolder("./audio")
    .WithEmbedThumbnail()
    .WithEmbedMetadata();

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

Download a Playlist

var ytdlp = new Ytdlp("tools\\yt-dlp.exe")
    .WithFormat("best")
    .WithOutputFolder("./playlists")
    .WithPlaylistStart(1)
    .WithPlaylistEnd(5)
    .OutputTemplate("%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s");

await ytdlp.DownloadAsync("https://www.youtube.com/playlist?list=PL12345");

Fetch Formats

var ytdlp = new Ytdlp("tools\\yt-dlp.exe");

var formats = await ytdlp.GetFormatsAsync("https://www.youtube.com/watch?v=abc123");

foreach(var format in formats)
    Console.WriteLine($"Id: {metadata?.Id}, Extension: {metadata?.Extension}");

Best Format Selection

var ytdlp = new Ytdlp("tools\\yt-dlp.exe");

string bestAudio = await ytdlp.GetBestAudioFormatIdAsync(url);
string bestVideo = await ytdlp.GetBestVideoFormatIdAsync(url, maxHeight: 720);

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

Get Subtitles

var ytdlp = new Ytdlp("tools\\yt-dlp.exe");
var subtitles = await ytdlp.GetSubtitlesAsync("https://www.youtube.com/watch?v=abc123");
foreach (var sub in subtitles)
{
    Console.WriteLine($"Language: {sub.Language}, Format: {sub.Format}, Url: {sub.Url}");
}

Get Adobe Pass MSO List

var msoList = await ytdlp.GetAdobePassListAsync();

📡 Events

Event Description
ProgressDownload Download progress
ProgressMessage Informational messages
DownloadCompleted File finished
PostProcessingStarted Post‑processing start
PostProcessingCompleted Post‑processing finished
OutputMessage Raw output line
ErrorMessage Error message
CommandCompleted Process finished

Example

// Progress events
ytdlp.ProgressDownload += (s, e) => Console.WriteLine($"{e.Percent:F1}%  {e.Speed}  ETA {e.ETA}");
ytdlp.ProgressMessage += (s, msg) => Console.WriteLine(msg);

// Output events
ytdlp.ErrorMessage += (s, err) => Console.WriteLine($"Error: {err}");
ytdlp.OutputMessage += (s, msg) => Console.WriteLine(msg);

// Lifecycle events
ytdlp.DownloadCompleted += (s, msg) => Console.WriteLine($"Finished: {msg}");
ytdlp.CommandCompleted += (s, e) => Console.WriteLine($"Command finished: {e.Command}");

// Post-Processing events
ytdlp.PostProcessingStarted += (s, msg) => Console.WriteLine($"Post-processing-start: {msg}");
ytdlp.PostProcessingCompleted += (s, msg) => Console.WriteLine($"Post-processing-complete: {msg}");

🛠 Methods

Probe

  • VersionAsync()
  • UpdateAsync(UpdateChannel channel, string specificVersion)
  • GetExtractorsAsync()
  • GetAdobePassListAsync()
  • GetSubtitlesAsync(string url)
  • GetMetadataAsync(string url)
  • GetMetadataRawAsync(string url)
  • GetDeepMetadataAsync(string url)
  • GetDeepMetadataRawAsync(string url)
  • GetFormatsAsync(string url)
  • GetMetadataLiteAsync(string url)
  • GetMetadataLiteAsync(string url, IEnumerable<string> fields)
  • GetBestAudioFormatIdAsync(string url)
  • GetBestVideoFormatIdAsync(string url, int maxHeight)

Download

  • DownloadAsync(string url)
  • DownloadBatchAsync(IEnumerable<string> urls, int maxConcurrency)

🛠 Fluent Methods

General Options

  • .WithIgnoreErrors()
  • .WithAbortOnError()
  • .WithIgnoreConfig()
  • .WithConfigLocations(string path)
  • .WithPluginDirs(string path)
  • .WithNoPluginDirs(string path)
  • .WithJsRuntime(Runtime runtime, string runtimePath)
  • .WithNoJsRuntime()
  • .WithFlatPlaylist()
  • .WithLiveFromStart()
  • .WithWaitForVideo(TimeSpan? maxWait = null)
  • .WithMarkWatched()

Network Options

  • .WithProxy(string? proxy)
  • .WithSocketTimeout(TimeSpan timeout)
  • .WithForceIpv4()
  • .WithForceIpv6()
  • .WithEnableFileUrls()

Geo-restriction Options

  • .WithGeoVerificationProxy(string url)
  • .WithGeoBypassCountry(string countryCode)

Video Selection

  • .WithPlaylistItems(string items)
  • .WithMinFileSize(string size)
  • .WithMaxFileSize(string size)
  • .WithDate(string date)
  • .WithDateBefore(string date)
  • .WithDateAfter(string date)
  • .WithMatchFilter(string filterExpression)
  • .WithNoPlaylist()
  • .WithYesPlaylist()
  • .WithAgeLimit(int years)
  • .WithDownloadArchive(string archivePath = "archive.txt")
  • .WithMaxDownloads(int count)
  • .WithBreakOnExisting()

Download Options

  • .WithConcurrentFragments(int count = 8)
  • .WithLimitRate(string rate)
  • .WithThrottledRate(string rate)
  • .WithRetries(int maxRetries)
  • .WithFileAccessRetries(int maxRetries)
  • .WithFragmentRetries(int retries)
  • .WithSkipUnavailableFragments()
  • .WithAbortOnUnavailableFragments()
  • .WithKeepFragments()
  • .WithBufferSize(string size)
  • .WithNoResizeBuffer()
  • .WithPlaylistRandom()
  • .WithHlsUseMpegts()
  • .WithNoHlsUseMpegts()
  • .WithDownloadSections(string regex)

Filesystem Options

  • .WithHomeFolder(string path)
  • .WithTempFolder(string path)
  • .WithOutputFolder(string path)
  • .WithFFmpegLocation(string path)
  • .WithOutputTemplate(string template)
  • .WithRestrictFilenames()
  • .WithWindowsFilenames()
  • .WithTrimFilenames(int length)
  • .WithNoOverwrites()
  • .WithForceOverwrites()
  • .WithNoContinue()
  • .WithNoPart()
  • .WithMtime()
  • .WithWriteDescription()
  • .WithWriteInfoJson()
  • .WithNoWritePlaylistMetafiles()
  • .WithNoCleanInfoJson()
  • .WriteComments()
  • .WithNoWriteComments()
  • .WithLoadInfoJson(string path)
  • .WithCookiesFile(string path)
  • .WithCookiesFromBrowser(string browser)
  • .WithNoCacheDir()
  • .WithRemoveCacheDir()

Thumbnail Options

  • .WithThumbnails(bool allSizes = false)

Verbosity and Simulation Options

  • .WithQuiet()
  • .WithNoWarnings()
  • .WithSimulate()
  • .WithNoSimulate()
  • .WithSkipDownload()
  • .WithVerbose()

Workgrounds

  • .WithAddHeader(string header, string value)
  • .WithSleepInterval(double seconds, double? maxSeconds = null)
  • .WithSleepSubtitles(double seconds)

Video Format Options

  • .WithFormat(string format)
  • .WithMergeOutputFormat(string format)

Subtitle Options

  • .WithSubtitles(string languages = "all", bool auto = false)

Authentication Options

  • .WithAuthentication(string username, string password)
  • .WithTwoFactor(string code)
  • .WithVideoPassword(string password)
  • .WithAdobePassAuthentication(string mso, string username, string password)

Post-Processing Options

  • .WithExtractAudio(string format, int quality = 5)
  • .WithRemuxVideo(string format) usage 'mp4' or 'mp4>mkv'
  • .WithRecodeVideo(string format, string? videoCodec = null, string? audioCodec = null)
  • .WithPostprocessorArgs(PostProcessors postprocessor, string args)
  • .WithKeepVideo()
  • .WithNoPostOverwrites()
  • .WithEmbedSubtitles()
  • .WithEmbedThumbnail()
  • .WithEmbedMetadata()
  • .WithEmbedChapters()
  • .WithEmbedInfoJson()
  • .WithNoEmbedInfoJson()
  • .WithReplaceInMetadata(string field, string regex, string replacement)
  • .WithConcatPlaylist(string policy = "always")
  • .WithFFmpegLocation(string? ffmpegPath)
  • .WithConvertSubtitles(string format = "none")
  • .WithConvertThumbnails(string format = "jpg")
  • .WithSplitChapters() => AddFlag("--split-chapters")
  • .WithRemoveChapters(string regex)
  • .WithForceKeyframesAtCuts()
  • .WithUsePostProcessor(PostProcessors postProcessor, string? postProcessorArgs = null)

SponsorBlock Options

  • .WithSponsorblockMark(string categories = "all")
  • .WithSponsorblockRemove(string categories = "all")
  • .WithNoSponsorblock()

Advanced Options

  • .AddFlag(string flag)
  • .AddOption(string key, string value)

Downloaders

  • .WithExternalDownloader(string downloaderName, string? downloaderArgs = null)
  • .WithAria2(int connections = 16)
  • .WithHlsNative()
  • .WithFfmpegAsLiveDownloader(string? extraFfmpegArgs = null)

⚙️ Customization

If you need specific arguments not covered by the fluent API:

ytdlp.AddFlag("--no-check-certificate")
     .AddOption("--external-downloader", "aria2c")
     .DownloadAsync(url);

🔄 Migration Guide: Upgrading to v4

Version 4.0.0 is a major release that refines the API for better maintainability and removes the overhead of manual lifecycle management.

Note: The primary breaking change is the removal of IDisposable/IAsyncDisposable. You no longer need to dispose of your Ytdlp instances.

1. Key Changes at a Glance

Feature v3.x v4.x
Lifecycle Required IAsyncDisposable No disposal required
Architecture Immutable Fluent API Immutable Fluent API (Refactored)
Core Process ProcessFactory ProcessFactory (Refactored)
Core Runner ProbeRunner DownloadRunner ProcessRunner

2. Side-by-Side Comparison

❌ Legacy API (v3)
// Previously required disposal
await using var ytdlp = new Ytdlp()
    .WithFormat("best")
    .WithOutputFolder("./downloads");

await ytdlp.DownloadAsync(url);

✅ New API (v4)
// Cleaner: No disposal required
var ytdlp = new Ytdlp()
    .WithFormat("best")
    .WithOutputFolder("./downloads");

await ytdlp.DownloadAsync(url);

3. Why the change?

We have streamlined the Ytdlp lifecycle. Because the instance does not hold unmanaged resources that require explicit cleanup, we have removed the IDisposable and IAsyncDisposable interfaces.

  • Cleaner Code: Your codebase is now free of await using or using statements for Ytdlp instances.
  • Refactored Core: The internal ProcessFactory has been updated and introduce ProcessRunner to handle process execution more efficiently without needing to manage the object lifecycle manually.

4. Migration Checklist

  • Remove await using or using: Simply delete the disposal keywords where you instantiate Ytdlp.
  • Verify Events: Ensure event subscriptions are attached to the instance used for the specific execution.

💡 Notes

  • Dependencies: Ensure yt-dlp (and optionally FFmpeg/FFprobe) are available on your system path or point to their specific locations via WithFfmpegLocation() (if configured).
  • Performance: tuneProcess: true (default) is enabled for download methods to optimize output buffer management.

📜 License

MIT License — see LICENSE

Author: Manojbabu (ManuHub)
Repository: Ytdlp.NET

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Ytdlp.NET

✨ Features
- No disposal required, Ytdlp holds no unmanaged resources.
- Added more Fluent methods and Probe methods.
- Enhanced security for authentication methods.
- Implemented file permission for Unix based system.
- Events renamed for better usage.

🛠 Notes
- Companion packages recommended: ManuHub.Ytdlp, ManuHub.FFmpeg, ManuHub.FFprobe, ManuHub.Deno.
- All examples and documentation updated.
- This release greatly improves reliability, cancellation, and maintainability.

See the repository for the full documentation and migration guide.