Youtube Playlist Free Downloader Python Script May 2026
Note: This script downloads videos in the highest available resolution. Be aware that downloading copyrighted content may be against YouTube's terms of service.
download_playlist("YOUR_PLAYLIST_URL_HERE") youtube playlist free downloader python script
Critique of the Code:
Before diving into the code, let's address the "why." Pre-built websites and software exist, but they often come with: Note : This script downloads videos in the
A self-made Python script is:
from pytube import Playlist
def download_playlist(playlist_url):
playlist = Playlist(playlist_url)
for video_url in playlist.video_urls:
video = pytube.YouTube(video_url)
video.streams.get_highest_resolution().download()
if __name__ == "__main__":
playlist_url = input("Enter the YouTube playlist URL: ")
download_playlist(playlist_url)
Recommendation: For a serious playlist downloader, use yt-dlp. It is the industry standard for open-source video downloading. Critique of the Code: Before diving into the
Replace the stream selection line in the loop above with:
# Filter for audio only and download
stream = video.streams.filter(only_audio=True).first()
# Tip: The file will be an MP4 file containing audio.
# You can rename the extension to .mp3 manually or use a library like 'os' to rename it.
#!/usr/bin/env python3
"""
youtube_playlist_downloader.py
Downloads all videos from a YouTube playlist using yt-dlp.
Usage:
python youtube_playlist_downloader.py PLAYLIST_URL /path/to/output_dir
"""
import sys
import os
import time
import argparse
from yt_dlp import YoutubeDL
from yt_dlp.utils import sanitize_filename
def parse_args():
p = argparse.ArgumentParser(description="Download all videos from a YouTube playlist.")
p.add_argument("playlist_url", help="YouTube playlist URL")
p.add_argument("output_dir", nargs="?", default=".", help="Directory to save videos")
p.add_argument("--format", default="mp4", help="Container format (mp4/mkv/webm). yt-dlp will pick best video+audio.")
p.add_argument("--sleep", type=float, default=0.5, help="Seconds to sleep between downloads")
p.add_argument("--retries", type=int, default=3, help="Retries per video on failure")
return p.parse_args()
def ensure_dir(path):
os.makedirs(path, exist_ok=True)
return os.path.abspath(path)
def build_outtmpl(output_dir):
# Keep playlist index prefix for ordering
return os.path.join(output_dir, "%(playlist_index)03d - %(title)s.%(ext)s")
def download_playlist(url, output_dir, fmt="mp4", sleep=0.5, retries=3):
outtmpl = build_outtmpl(output_dir)
ydl_opts =
"format": f"bestvideo[ext!=webm]+bestaudio/best",
"outtmpl": outtmpl,
"merge_output_format": fmt,
"noplaylist": False,
"ignoreerrors": True,
"continuedl": True,
"nooverwrites": False,
"writesubtitles": False,
"quiet": True,
"progress_hooks": [progress_hook],
# Restrict filenames to safe chars
"restrictfilenames": False,
"allow_unplayable_formats": False,
attempts = {}
with YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
if not info:
print("Failed to fetch playlist info.")
return
entries = info.get("entries") or [info]
print(f"Found len(entries) entries in playlist.")
for i, entry in enumerate(entries, start=1):
if entry is None:
print(f"[i] Skipping unavailable entry.")
continue
video_url = entry.get("webpage_url") or entry.get("url")
title = entry.get("title") or f"video_i"
index = entry.get("playlist_index") or i
safe_title = sanitize_filename(title)
ext = fmt
filename = f"index:03d - safe_title.ext"
outpath = os.path.join(output_dir, filename)
if os.path.exists(outpath):
print(f"[index] Already downloaded: filename")
continue
attempt = 0
while attempt < retries:
attempt += 1
try:
print(f"[index] Downloading (attempt/retries): title")
ydl.download([video_url])
# Small pause to be polite
time.sleep(sleep)
break
except Exception as e:
print(f"[index] Error on attempt attempt: e")
if attempt >= retries:
print(f"[index] Failed after retries attempts, skipping.")
else:
time.sleep(2 ** attempt)
print("Done.")
def progress_hook(d):
if d.get("status") == "downloading":
eta = d.get("eta")
speed = d.get("speed")
downloaded = d.get("downloaded_bytes", 0)
total = d.get("total_bytes") or d.get("total_bytes_estimate")
pct = ""
if total:
pct = f"downloaded/total*100:5.1f%"
print(f"Downloading: d.get('filename','') pct ETA:eta speed:speed", end="\r")
elif d.get("status") == "finished":
print(f"\nFinished downloading: d.get('filename')")
if __name__ == "__main__":
args = parse_args()
out = ensure_dir(args.output_dir)
download_playlist(args.playlist_url, out, fmt=args.format, sleep=args.sleep, retries=args.retries)
┌─────────────────┐
│ User Input │
│ - Playlist URL │
│ - Quality │
└────────┬────────┘
▼
┌─────────────────┐
│ Fetch Playlist │
│ (pytube.Playlist)│
└────────┬────────┘
▼
┌─────────────────┐
│ Iterate Videos │
└────────┬────────┘
▼
┌─────────────────┐
│ For each video: │
│ - Get stream │
│ - Download │
│ - Handle errors │
└─────────────────┘