• Stars
    star
    2,473
  • Rank 18,586 (Top 0.4 %)
  • Language
    C#
  • License
    MIT License
  • Created over 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Abstraction layer over YouTube's internal API

YoutubeExplode

Status Made in Ukraine Build Coverage Version Downloads Discord Fuck Russia

Development of this project is entirely funded by the community. Consider donating to support!

Icon

YoutubeExplode is a library that provides an interface to query metadata of YouTube videos, playlists and channels, as well as to resolve and download video streams and closed caption tracks. Behind a layer of abstraction, this library works by scraping raw page data and exploiting reverse-engineered internal endpoints.

📝 Interested in the inner workings of this library? See the Reverse-Engineering YouTube article.

Extension packages:

Terms of use[?]

By using this project or its source code, for any purpose and in any shape or form, you grant your implicit agreement to all the following statements:

  • You condemn Russia and its military aggression against Ukraine
  • You recognize that Russia is an occupant that unlawfully invaded a sovereign state
  • You support Ukraine's territorial integrity, including its claims over temporarily occupied territories of Crimea and Donbas
  • You reject false narratives perpetuated by Russian state propaganda

To learn more about the war and how you can help, click here. Glory to Ukraine! 🇺🇦

Install

  • 📦 NuGet: dotnet add package YoutubeExplode

Screenshots

demo

Usage

YoutubeExplode exposes its functionality through a single entry point — the YoutubeClient class. Create an instance of this class and use the provided operations on Videos, Playlists, Channels, and Search properties to send requests.

Videos

Retrieving video metadata

To retrieve the metadata associated with a YouTube video, call Videos.GetAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

// You can specify either the video URL or its ID
var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs";
var video = await youtube.Videos.GetAsync(videoUrl);

var title = video.Title; // "Collections - Blender 2.80 Fundamentals"
var author = video.Author.ChannelTitle; // "Blender"
var duration = video.Duration; // 00:07:20

Downloading video streams

Every YouTube video has a number of streams available, differing in containers, video quality, bitrate, framerate, and other parameters. Additionally, the streams are further divided into 3 categories based on their content:

  • Muxed streams — contain both video and audio
  • Audio-only streams — contain only audio
  • Video-only streams — contain only video

Warning: Muxed streams contain both audio and video, but these streams are limited in quality (up to 720p30). To download the video in the highest available quality, you will need to resolve the best audio-only and video-only streams separately and then mux them together. The muxing process can be performed using FFmpeg with the help of the YoutubeExplode.Converter package.

You can request the manifest that lists all available streams for a particular video by calling Videos.Streams.GetManifestAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs";
var streamManifest = await youtube.Videos.Streams.GetManifestAsync(videoUrl);

Once the manifest is obtained, you can filter through the streams and identify the ones you're interested in:

using YoutubeExplode;
using YoutubeExplode.Videos.Streams;

// ...

// Get highest quality muxed stream
var streamInfo = streamManifest.GetMuxedStreams().GetWithHighestVideoQuality();

// ...or highest bitrate audio-only stream
var streamInfo = streamManifest.GetAudioOnlyStreams().GetWithHighestBitrate();

// ...or highest quality MP4 video-only stream
var streamInfo = streamManifest
    .GetVideoOnlyStreams()
    .Where(s => s.Container == Container.Mp4)
    .GetWithHighestVideoQuality()

Finally, you can resolve the actual stream represented by the specified metadata using Videos.Streams.GetAsync(...) or download it directly to a file with Videos.Streams.DownloadAsync(...):

// ...

// Get the actual stream
var stream = await youtube.Videos.Streams.GetAsync(streamInfo);

// Download the stream to a file
await youtube.Videos.Streams.DownloadAsync(streamInfo, $"video.{streamInfo.Container}");

Warning: While the Url property in the stream metadata can be used to access the underlying content, you need a series of carefully crafted HTTP requests in order to do so. It's highly recommended to use Videos.Streams.GetAsync(...) or Videos.Streams.DownloadAsync(...) instead, as they will perform all the heavy lifting for you.

Downloading closed captions

Closed captions can be downloaded in a similar way to media streams. To get the list of available closed caption tracks, call Videos.ClosedCaptions.GetManifestAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs";
var trackManifest = await youtube.Videos.ClosedCaptions.GetManifestAsync(videoUrl);

Then retrieve the metadata for a particular track:

// ...

// Find closed caption track in English
var trackInfo = trackManifest.GetByLanguage("en");

Finally, use Videos.ClosedCaptions.GetAsync(...) to get the actual content of the track:

// ...

var track = await youtube.Videos.ClosedCaptions.GetAsync(trackInfo);

// Get the caption displayed at 0:35
var caption = track.GetByTime(TimeSpan.FromSeconds(35));
var text = caption.Text; // "collection acts as the parent collection"

You can also download the closed caption track in the SRT file format with Videos.ClosedCaptions.DownloadAsync(...):

// ...

await youtube.Videos.ClosedCaptions.DownloadAsync(trackInfo, "cc_track.srt");

Playlists

Retrieving playlist metadata

You can get the metadata associated with a YouTube playlist by calling the Playlists.GetAsync(...) method:

using YoutubeExplode;

var youtube = new YoutubeClient();

var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";
var playlist = await youtube.Playlists.GetAsync(playlistUrl);

var title = playlist.Title; // "First Steps - Blender 2.80 Fundamentals"
var author = playlist.Author.ChannelTitle; // "Blender"

Retrieving videos included in a playlist

To get the videos included in a playlist, call Playlists.GetVideosAsync(...):

using YoutubeExplode;
using YoutubeExplode.Common;

var youtube = new YoutubeClient();
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";

// Get all playlist videos
var videos = await youtube.Playlists.GetVideosAsync(playlistUrl);

// Get only the first 20 playlist videos
var videosSubset = await youtube.Playlists.GetVideosAsync(playlistUrl).CollectAsync(20);

You can also enumerate the videos iteratively without waiting for the whole list to load:

using YoutubeExplode;

var youtube = new YoutubeClient();
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";

await foreach (var video in youtube.Playlists.GetVideosAsync(playlistUrl))
{
    var title = video.Title;
    var author = video.Author;
}

If you need precise control over how many requests you send to YouTube, use Playlists.GetVideoBatchesAsync(...) which returns videos wrapped in batches:

using YoutubeExplode;

var youtube = new YoutubeClient();
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6";

// Each batch corresponds to one request
await foreach (var batch in youtube.Playlists.GetVideoBatchesAsync(playlistUrl))
{
    foreach (var video in batch.Items)
    {
        var title = video.Title;
        var author = video.Author;
    }
}

Note: You can craft playlist IDs to fetch special auto-generated playlists, such as music mixes, popular channel uploads, liked videos, and more. See this reference for more information.

Channels

Retrieving channel metadata

You can get the metadata associated with a YouTube channel by calling the Channels.GetAsync(...) method:

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg";
var channel = await youtube.Channels.GetAsync(channelUrl);

var title = channel.Title; // "Blender"

You can also get the channel metadata by username or profile URL with Channels.GetByUserAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/user/BlenderFoundation";
var channel = await youtube.Channels.GetByUserAsync(channelUrl);

var id = channel.Id; // "UCSMOQeBJ2RAnuFungnQOxLg"

To get the channel metadata by slug or legacy custom URL, use Channels.GetBySlugAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/c/BlenderFoundation";
var channel = await youtube.Channels.GetBySlugAsync(channelUrl);

var id = channel.Id; // "UCSMOQeBJ2RAnuFungnQOxLg"

To get the channel metadata by handle or custom URL, use Channels.GetByHandleAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

var channelUrl = "https://youtube.com/@BeauMiles";
var channel = await youtube.Channels.GetByHandleAsync(channelUrl);

var id = channel.Id; // "UCm325cMiw9B15xl22_gr6Dw"

Retrieving channel uploads

To get the list of videos uploaded by a channel, call Channels.GetUploadsAsync(...):

using YoutubeExplode;
using YoutubeExplode.Common;

var youtube = new YoutubeClient();
var channelUrl = "https://youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg";

var videos = await youtube.Channels.GetUploadsAsync(channelUrl);

Search

You can execute a search query by calling the Search.GetResultsAsync(...) method. Each search result may represent either a video, a playlist, or a channel, so you need to apply pattern matching to handle the corresponding cases:

using YoutubeExplode;

var youtube = new YoutubeClient();

await foreach (var result in youtube.Search.GetResultsAsync("blender tutorials"))
{
    // Use pattern matching to handle different results (videos, playlists, channels)
    switch (result)
    {
        case VideoSearchResult video:
        {
            var id = video.Id;
            var title = video.Title;
            var duration = video.Duration;
            break;
        }
        case PlaylistSearchResult playlist:
        {
            var id = playlist.Id;
            var title = playlist.Title;
            break;
        }
        case ChannelSearchResult channel:
        {
            var id = channel.Id;
            var title = channel.Title;
            break;
        }
    }
}

To limit the results to a specific type, use Search.GetVideosAsync(...), Search.GetPlaylistsAsync(...), or Search.GetChannelsAsync(...):

using YoutubeExplode;
using YoutubeExplode.Common;

var youtube = new YoutubeClient();

var videos = await youtube.Search.GetVideosAsync("blender tutorials");
var playlists = await youtube.Search.GetPlaylistsAsync("blender tutorials");
var channels = await youtube.Search.GetChannelsAsync("blender tutorials");

Similarly to playlists, you can also enumerate results in batches by calling Search.GetResultBatchesAsync(...):

using YoutubeExplode;

var youtube = new YoutubeClient();

// Each batch corresponds to one request
await foreach (var batch in youtube.Search.GetResultBatchesAsync("blender tutorials"))
{
    foreach (var result in batch.Items)
    {
        switch (result)
        {
            case VideoSearchResult videoResult:
            {
                // ...
            }
            case PlaylistSearchResult playlistResult:
            {
                // ...
            }
            case ChannelSearchResult channelResult:
            {
                // ...
            }
        }
    }
}

Authentication

You can access private videos and playlists by providing cookies that correspond to a pre-authenticated YouTube account. To do that, create an instance of YoutubeClient using a constructor that accepts IReadOnlyList<Cookie>:

using YoutubeExplode;

// Perform authentication and extract cookies
var cookies = ...;

// Cookie collection must be of type IReadOnlyList<System.Net.Cookie>
var youtube = new YoutubeClient(cookies);

In order to actually perform the authentication, you can use an embedded browser such as WebView to navigate the user to the YouTube login page, let them log in, and then extract the cookies from the browser.

Etymology

The "Explode" in YoutubeExplode comes from the name of a PHP function that splits up strings, explode(...). When I was starting the development of this library, most of the reference source code I read was written in PHP, hence the inspiration for the name.

More Repositories

1

DiscordChatExporter

Exports Discord chat logs to a file
C#
5,677
star
2

YoutubeDownloader

Downloads videos and playlists from YouTube
C#
4,837
star
3

CliWrap

Library for running command-line processes
C#
3,705
star
4

LightBulb

Reduces eye strain by adjusting gamma based on the current time
C#
1,762
star
5

CliFx

Class-first framework for building command-line interfaces
C#
1,324
star
6

Onova

Unintrusive auto-update framework
C#
400
star
7

DotnetRuntimeBootstrapper

Bootstrapped framework-dependent deployment for .NET applications
C#
238
star
8

GitHubActionsTestLogger

.NET test logger that reports to GitHub Actions
C#
221
star
9

MiniRazor

Portable Razor compiler & code generator
C#
214
star
10

Gress

Progress reporting toolbox
C#
137
star
11

LtGt

Lightweight HTML processor
C#
117
star
12

OsuHelper

Beatmap suggester for osu!
C#
95
star
13

YoutubeExplode.Converter

Muxes and converts videos from YoutubeExplode
C#
87
star
14

SpellingUkraine

Learn the correct way to spell Ukrainian names in English
TypeScript
77
star
15

interview-questions

Collection of popular interview questions and their answers
66
star
16

Ressy

Resource editor for PE files
C#
43
star
17

Contextual

Implicit parameters via contexts
C#
40
star
18

JetBrainsDotnetDay2020

Presentation and code for my talk at JetBrains .NET Day Online 2020
F#
35
star
19

JsonExtensions

Extensions for System.Text.Json
C#
29
star
20

Extensions

My .NET extensions
C#
29
star
21

YoutubeMusicDownloader

Downloads Youtube videos and playlists as mp3 files
C#
26
star
22

Hallstatt

Low-ceremony testing framework optimized for modern C#
C#
25
star
23

Deorcify

Prevent your software from being used by terrorists
C#
22
star
24

WpfExtensions

My WPF extensions, converters and behaviors
C#
19
star
25

route-descriptor

Single source of truth for routing
TypeScript
17
star
26

Cogwheel

Library for managing application settings
C#
16
star
27

QuickJson

Simple JSON parser in a source-only package
C#
14
star
28

LockFile

Simplest lock file implementation
C#
13
star
29

Failsafe

Retry utility
C#
13
star
30

Tyrrrz.me

My personal website
TypeScript
13
star
31

.github

Assets shared between my repositories
12
star
32

FuncTestingInAspNetCoreExample

Example of doing functional testing with an ASP.NET Core application
C#
12
star
33

PolyShim

Polyfills for projects targeting older versions of .NET
C#
11
star
34

MyFlickList

Social cataloging app for movies and TV-shows
TypeScript
9
star
35

RaidTrend

Documenting air raid alerts across Ukraine
TypeScript
8
star
36

DotNetFest2019

My presentation and live demo project used during my talk at .NET Fest 2019
C#
8
star
37

WPSteamMarketExcerpt

Embeds Steam Market listings into WordPress pages
PHP
6
star
38

hip-cloud-test

will delete later
TypeScript
6
star
39

netfwdays-hipster-cloud

.NET fwdays'21 workshop
TypeScript
4
star
40

DiscordFonts

4
star
41

PrintForegroundWindow

Prints info about current foreground window
C#
4
star
42

Hashsum

Culture-invariant fluent checksum builder
C#
3
star
43

Tyrrrz

Profile readme
2
star
44

action-http-request

GitHub Action that sends an HTTP request
JavaScript
2
star
45

gatsby-plugin-clicky

Clicky web analytics integration for Gatsby
JavaScript
2
star
46

twitter-auth-cli

Quickly generate access token and secret for Twitter API
TypeScript
2
star
47

Scheddulit

Post scheduler and batcher for Reddit
TypeScript
1
star
48

OnovaTestRepo

Test repository used for Onova integration tests
1
star
49

AspNetCore.Mvc.Lightbox

Tag helper used to initialize Lightbox
C#
1
star
50

action-get-tag

GitHub Action that extracts current git tag
JavaScript
1
star
51

AspNetCore.Mvc.Clicky

Tag helper used to render Clicky activity tracker
C#
1
star
52

AspNetCore.Mvc.Disqus

Tag helper used to render Disqus threads
C#
1
star
53

BMAC-API-Cache

Caching layer for BuyMeACoffee API
TypeScript
1
star