Build a YouTube Playlist Downloader with Python and Pytube
If you’ve ever wanted to download an entire YouTube playlist for offline viewing or archiving, Python makes this process simple and automatable thanks to the pytube
library. In this blog post, you’ll learn how to build a robust YouTube Playlist Downloader using Python and pytube
, complete with progress indicators and proper error handling.
1. Setting Up Your Environment
Before diving into code, make sure you have Python 3 installed. You’ll also need the pytube
library. You can install it using pip:
pip install pytube
Optionally, create a virtual environment to keep dependencies organized:
python -m venv yt-downloader-env
source yt-downloader-env/bin/activate # On Unix/macOS
yt-downloader-env\Scripts\activate.bat # On Windows
2. Fetching Playlist Metadata
First, let’s retrieve the playlist and list all video titles and URLs. We’ll use Playlist
from pytube
to parse the playlist link:
from pytube import Playlist
playlist_url = 'https://www.youtube.com/playlist?list=YOUR_PLAYLIST_ID'
playlist = Playlist(playlist_url)
print(f'Downloading: {playlist.title}')
for video_url in playlist.video_urls:
print(video_url)
This script loads the playlist and iterates through the video URLs. This is useful to verify that pytube
is parsing the list correctly.
3. Downloading Videos with Progress Tracking
Now, let’s download each video. We’ll use the YouTube
class from pytube
and download streams in 720p resolution or best available:
from pytube import YouTube
import os
def on_progress(stream, chunk, remaining):
percent = 100 * (1 - remaining / stream.filesize)
print(f"Progress: {percent:.2f}%", end='\r')
output_path = 'downloads/' + playlist.title.replace(' ', '_')
os.makedirs(output_path, exist_ok=True)
for url in playlist.video_urls:
try:
yt = YouTube(url, on_progress_callback=on_progress)
stream = yt.streams.filter(progressive=True, file_extension='mp4').order_by('resolution').desc().first()
print(f"\nDownloading: {yt.title}")
stream.download(output_path=output_path)
print(f"Downloaded: {yt.title}\n")
except Exception as e:
print(f"Error downloading {url}: {e}")
Using a progress callback gives you real-time download feedback. We also use progressive=True
to ensure both video and audio are downloaded in one file.
4. Error Handling and Resilience
Downloading multiple files from external sources can lead to a range of issues: videos may be private, deleted, or geo-restricted. Our above implementation wraps each download attempt in a try/except
block to prevent the script from crashing on a single failed download.
To improve further, you might want to log failed URLs to a file for debugging later:
with open('errors.log', 'a') as f:
f.write(f"Failed to download: {url} - {str(e)}\n")
This makes your downloader more resilient during long batch jobs and helps troubleshoot issues post-process.
5. Performance Tips and Real-World Automation
Here are a few suggestions to optimize and automate your playlist downloader:
- Use threading or async to download multiple videos in parallel for large playlists.
- Schedule downloads via a task scheduler (like cron or Windows Task Scheduler).
- Filter resolutions or audio-only streams for music playlists.
- Track completed downloads using a JSON or SQLite database so you can resume later.
For example, to download audio-only:
audio_stream = yt.streams.filter(only_audio=True).first()
audio_stream.download(output_path=output_path)
Or, to skip already downloaded videos:
existing_files = set(os.listdir(output_path))
if f"{yt.title}.mp4" in existing_files:
print(f"Skipping {yt.title}, already downloaded.")
continue
Conclusion
Using pytube
, it’s easy to build a fully functional YouTube Playlist Downloader in just a few lines of Python. You’ve learned how to fetch playlist videos, download them with real-time progress tracking, and add robustness with error handling and performance optimizations. Whether you’re archiving educational playlists or binge-worthy content, this tool can save considerable time and bandwidth.
Happy coding!
Useful links: