Download a full YouTube playlist with PowerShell

Published July 08, 2014 by FoxDeploy

Recently, a colleague approached me requesting pointers on the quickest possible way to download a YouTube playlist.  I’d used previously, to download videos one at a time, but never found a good tool to use to download a full playlist.  So I decided to make one!


This tool depends on you already having the wonderfully useful youtube-dl.exe downloaded on your system.  I placed it in my %PATH% directory, but you can also run this code directly from wherever you placed the binary.  Get the tool here if you don’t already have it:

You should make sure your link loads in Playlist form.  It should look like this:

You can get your playlist by selecting the URL from a page that will generally look like this.

If it doesn’t contain a playlist, this method won’t work for you.  Once you have your URL, provide it in the $PlayListURL in the top line of the code:

$Playlisturl = "" 
#Next, the real magic happens in this ungainly one-liner

$VideoUrls= (invoke-WebRequest -uri $Playlisturl).Links | ? {$\_.HREF -like "/watch\*"} | \` ? innerText -notmatch ".\[0-9\]:\[0-9\]." | ? {$\_.innerText.Length -gt 3} | Select innerText, \` @{Name="URL";Expression={'' + $\_.href}} | ? innerText -notlike "\*Play all\*"

We’ll break it down element by element:

We begin by Invoking a WebRequest for our URL and selecting all of the links. Next, we select only the playlist items that contain a direct video reference (contains “/watch”), then further filter to remove those without a playtime in the innerText field, which indicates direct links to times within videos.

Next, we remove items with a title with less than three characters, to remove duplicate entries, then we move on down the pipeline to set up a calculated property to perform some adjustment to the URL property.  We finally remove all items that survived to this point, which have ‘Play All’ in their name (which is typically reserved for the first entry in a playlist.

Sample output of a playlist

This gets saved and then fed to the binary one by one!

ForEach ($video in $VideoUrls){ Write-Host "Downloading $($video.innerText)" .\\youtube-dl.exe $video.URL } 

This process supports WGET, so your downloads can even resume!

Completed Code

$Playlisturl = "" 
$VideoUrls= (invoke-WebRequest -uri $Playlisturl).Links | ? {$\_.HREF -like "/watch\*"} | \` ? innerText -notmatch ".\[0-9\]:\[0-9\]." | ? {$\_.innerText.Length -gt 3} | Select innerText, \` @{Name="URL";Expression={'' + $\_.href}} | ? innerText -notlike "\*Play all\*"


ForEach ($video in $VideoUrls){ Write-Host ("Downloading " + $video.innerText) .\\youtube-dl.exe $video.URL } 

Microsoft MVP

Five time Microsoft MVP, and now I work for the mothership

Need Help?

Get help much faster on our new dedicated Subreddit!

depicts a crowd of people in a night club with colored lights and says 'join the foxdeploy subrreddit today'

Blog Series
series_sml_PowerShellGUI series_sml_IntroToRaspberryPi Programming series_sml_IntroToWindows Remote Management Series The Logo for System Center Configuration Manager is displayed here Depicts a road sign saying 'Learning PowerShell Autocomplete'

Blog Stats