How To Download YouTube Playlist Using Python
Tags: python, programming, automation
Published: 2023-05-01 15:34:55

---
title: How To Download YouTube Playlist Using Python
published: true
date: 2023-04-30 17:54:24 UTC
tags: Python, Programming, Automation
canonical_url: https://blog.ashutoshkrris.in/how-to-download-youtube-playlist-using-python
---

YouTube is the world's largest video-sharing platform with millions of videos uploaded every day. Many times you come across a playlist of videos on YouTube that you want to watch offline or save for future reference. However, downloading a single video from YouTube is easy, but when it comes to downloading an entire playlist, it can be a daunting task. In such cases, automating the process using Python can save a lot of time and effort.

In this tutorial, you will be using the Pytube library in Python to download entire YouTube playlists in various resolutions, including the high-quality 2160p resolution. Pytube is a lightweight library that allows easy access to YouTube videos and metadata. With Pytube, we can easily extract video URLs, download videos, and even extract audio from videos. So, let's dive into the tutorial and learn how to download a YouTube playlist using Python.

> If you're in a hurry, jump to the [GitHub gist](https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50) to get the code immediately.

## Prerequisites

To follow this tutorial, you should have a basic understanding of Python programming language, including installing Python packages using pip.

You will also need to install the Pytube library, which can be installed using pip. Open a command prompt or terminal window and type the following command:

```bash
pip install pytube
```

Apart from Python and Pytube, you will also need to have FFmpeg installed on your system. FFmpeg is a command-line tool used for handling multimedia files. It is required for Pytube to be able to download videos in various resolutions. You can download FFmpeg from the [official website](https://www.ffmpeg.org/download.html) and follow the installation instructions for your operating system.

## Let's Code It!

Roll up your sleeves, fire up your favorite code editor, and let's get started!

![Cat Coder Gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1682874768386/bd85e9cc-f6b0-40ba-814b-5d8f72deacb5.gif)

### Import the Libraries

Let's import the necessary libraries for the program to run correctly.

```py
import os
import re
from pytube import Playlist, YouTube
```

The code imports the `os` module to handle operating system functionalities, `re` module to handle regular expressions, and `pytube` module to download the YouTube playlist.

### Create the Function

Let's define a function called `download_playlist`. The function takes two parameters; the playlist URL and the desired video resolution.

```py
def download_playlist(playlist_url, resolution):
    playlist = Playlist(playlist_url)
    playlist_name = re.sub(r'\W+', '-', playlist.title)

    if not os.path.exists(playlist_name):
        os.mkdir(playlist_name)
```

It first creates a new `Playlist` object using the Pytube library and extracts the name of the playlist. It then checks if a folder with the same name exists in the current working directory. If not, it creates a new folder with the playlist name.

Note that the `re.sub()` function replaces any non-alphanumeric characters in the playlist title with a hyphen ("-") character. We do so because folder and file names in most file systems have restrictions on the characters they can contain.

### Downloading the Videos

The `Playlist` object provides a `videos` property which is an iterable of `YouTube` objects. You first iterate through the list of videos in the playlist using a `for` loop and `enumerate` function.:

```py
for index, v in enumerate(playlist.videos, start=1):
    ...
```

The `start` parameter set to 1 to start counting from 1 instead of 0 because you're going to use the index in the filenames. Thus it makes sense to start from 1.

Next, create a `YouTube` object for each video using its watch URL, and specify to use OAuth for authentication:

```py
for index, v in enumerate(playlist.videos, start=1):
    video = YouTube(v.watch_url, use_oauth=True)
```

> Recently, there were several issues where PyTube was throwing a KeyError. The fix was to use the `use_oauth=True` parameter. When you run the code for the first time, it will ask you to login into your YouTube account.

Filter the available video streams to select the one with the desired resolution, and get its filename:

```py
for index, v in enumerate(playlist.videos, start=1):
    video = YouTube(v.watch_url, use_oauth=True)
    video_resolution = video.streams.filter(res=resolution).first()
    video_filename = f"{index}. {video_resolution.default_filename}"
```

Determine the full path and filename for the video file, and check if it already exists. If it does, skip downloading this video and move on to the next one:

```py
for index, v in enumerate(playlist.videos, start=1):
    video = YouTube(v.watch_url, use_oauth=True)
    video_resolution = video.streams.filter(res=resolution).first()
    video_filename = f"{index}. {video_resolution.default_filename}"
    video_path = os.path.join(playlist_name, video_filename)
    if os.path.exists(video_path):
        print(f"{video_filename} already exists")
        continue
```

If the desired resolution is not available, download the video with the highest resolution instead:

```py
for index, v in enumerate(playlist.videos, start=1):
    ...
    video_streams = video.streams.filter(res=resolution)

    if not video_streams:
        highest_resolution_stream = video.streams.get_highest_resolution()
        video_name = highest_resolution_stream.default_filename
        print(f"Downloading {video_name} in {highest_resolution_stream.resolution}")
        highest_resolution_stream.download(filename=video_path)
```

If the desired resolution is available, you don't have to download it directly. If you do so, the downloaded video won't have sound. Instead, download both the video and audio streams separately, and merge them using the FFmpeg library to create the final video file. Finally, rename the merged file and delete the temporary video and audio files:

```py
for index, v in enumerate(playlist.videos, start=1):
    ...
    video_streams = video.streams.filter(res=resolution)

    if not video_streams:
        ...
    else:
        video_stream = video_streams.first()
        video_name = video_stream.default_filename
        print(f"Downloading video for {video_name} in {resolution}")
        video_stream.download(filename="video.mp4")

        audio_stream = video.streams.get_audio_only()
        print(f"Downloading audio for {video_name}")
        audio_stream.download(filename="audio.mp4")

        os.system("ffmpeg -y -i video.mp4 -i audio.mp4 -c:v copy -c:a aac final.mp4 -loglevel quiet -stats")
        os.rename("final.mp4", video_path)
        os.remove("video.mp4")
        os.remove("audio.mp4")
```

The video stream is initially downloaded as `video.mp4` and the audio stream is downloaded as `audio.mp4`. Next, the `ffmpeg` command takes two input files (`video.mp4` and `audio.mp4`), copies the video codec from the input file and uses the AAC codec for audio, and saves the output as `final.mp4`. The output file is created by merging the video and audio streams from the two input files.

After `ffmpeg` finishes processing, the `final.mp4` is renamed `video_path` and the video and audio stream files are deleted.

### The `download_playlist` Function

At this point, you have completed the `download_playlist` function. It should look like this:

```py
def download_playlist(playlist_url, resolution):
    playlist = Playlist(playlist_url)
    playlist_name = re.sub(r'\W+', '-', playlist.title)

    if not os.path.exists(playlist_name):
        os.mkdir(playlist_name)

    for index, v in enumerate(playlist.videos, start=1):
        video = YouTube(v.watch_url, use_oauth=True)
        video_resolution = video.streams.filter(res=resolution).first()
        video_filename = f"{index}. {video_resolution.default_filename}"
        video_path = os.path.join(playlist_name, video_filename)
        if os.path.exists(video_path):
            print(f"{video_filename} already exists")
            continue

        video_streams = video.streams.filter(res=resolution)

        if not video_streams:
            highest_resolution_stream = video.streams.get_highest_resolution()
            video_name = highest_resolution_stream.default_filename
            print(f"Downloading {video_name} in {highest_resolution_stream.resolution}")
            highest_resolution_stream.download(filename=video_path)

        else:
            video_stream = video_streams.first()
            video_name = video_stream.default_filename
            print(f"Downloading video for {video_name} in {resolution}")
            video_stream.download(filename="video.mp4")

            audio_stream = video.streams.get_audio_only()
            print(f"Downloading audio for {video_name}")
            audio_stream.download(filename="audio.mp4")

            os.system("ffmpeg -y -i video.mp4 -i audio.mp4 -c:v copy -c:a aac final.mp4 -loglevel quiet -stats")
            os.rename("final.mp4", video_path)
            os.remove("video.mp4")
            os.remove("audio.mp4")

        print("----------------------------------")
```

A line of dashes is also printed after every iteration to separate each video as they are downloaded.

### Main Function

Let's create the main function that takes input from the user for the playlist URL and desired video resolution. It then calls the `download_playlist` function with the user's inputs.

```py
if __name__ == " __main__":
    playlist_url = input("Enter the playlist url: ")
    resolutions = ["240p", "360p", "480p", "720p", "1080p", "1440p", "2160p"]
    resolution = input(f"Please select a resolution {resolutions}: ")
    download_playlist(playlist_url, resolution)
```

## Completed Code

{% embed https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50 %}

## Conclusion

In this tutorial, you learned how you can use PyTube and FFmpeg libraries to download videos from a YouTube playlist in high resolutions such as 1080p, 1440p, and even 2160p.

I hope you found the tutorial helpful. If so, don't forget to star the [GitHub gist](https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50) and share this tutorial with others.

> The code has been tested with Pytube 12.1.3. It may not work properly at a later point in time.