Important: Downloading videos from YouTube may violate YouTube's Terms of Service unless you are downloading your own content or have permission from the copyright holder. Always:
This script is for educational purposes and personal backups of freely available content.
#!/usr/bin/env python3 """ YouTube Playlist Downloader Downloads all videos from a public YouTube playlist. Usage: python youtube_playlist_downloader.py """import os import re from pytube import Playlist from pytube.exceptions import PytubeError, VideoUnavailable youtube playlist free downloader python script
def sanitize_filename(title): """Remove invalid characters from filename.""" return re.sub(r'[<>:"/\|?*]', '_', title)
def get_user_choice(): """Get playlist URL and quality preference from user.""" print("=" * 50) print(" YouTube Playlist Downloader") print("=" * 50) YouTube Playlist Free Downloader Python Script Legal &
playlist_url = input("\nEnter YouTube Playlist URL: ").strip() print("\nSelect quality:") print("1. Highest resolution (includes audio)") print("2. Lowest resolution (fast download)") print("3. 720p (if available)") choice = input("Enter choice (1/2/3): ").strip() return playlist_url, choicedef get_stream(video, quality_choice): """ Select appropriate stream based on user's quality choice. Returns a progressive stream (video+audio combined). """ try: streams = video.streams.filter(progressive=True, file_extension='mp4')
if quality_choice == '1': # Highest return streams.order_by('resolution').last() elif quality_choice == '2': # Lowest return streams.order_by('resolution').first() elif quality_choice == '3': # 720p stream_720p = streams.filter(res='720p').first() return stream_720p if stream_720p else streams.order_by('resolution').last() else: return streams.order_by('resolution').last() except Exception as e: print(f" Error selecting stream: e") return Nonedef download_playlist(playlist_url, quality_choice, download_path="./downloads"): """Main function to download entire playlist.""" Use downloaded content for personal, offline use only
# Create download directory if not exists if not os.path.exists(download_path): os.makedirs(download_path) print(f"Created directory: download_path") try: # Fetch playlist print("\nFetching playlist...") playlist = Playlist(playlist_url) print(f"Playlist Title: playlist.title") print(f"Total Videos: len(playlist.video_urls)") confirm = input("\nProceed with download? (y/n): ").strip().lower() if confirm != 'y': print("Download cancelled.") return # Download each video success_count = 0 fail_count = 0 for idx, video in enumerate(playlist.videos, start=1): print(f"\n[idx/len(playlist.video_urls)] Processing: video.title") try: # Get appropriate stream stream = get_stream(video, quality_choice) if not stream: print(f" ✗ No suitable stream found. Skipping.") fail_count += 1 continue # Sanitize filename safe_title = sanitize_filename(video.title) filename = f"safe_title.mp4" filepath = os.path.join(download_path, filename) # Download print(f" Downloading: stream.resolution - round(stream.filesize_mb, 2) MB") stream.download(output_path=download_path, filename=filename) print(f" ✓ Saved to: filepath") success_count += 1 except VideoUnavailable: print(f" ✗ Video unavailable. Skipping.") fail_count += 1 except PytubeError as e: print(f" ✗ Pytube error: e") fail_count += 1 except Exception as e: print(f" ✗ Unexpected error: e") fail_count += 1 # Summary print("\n" + "=" * 50) print("DOWNLOAD COMPLETE") print(f"Successful: success_count") print(f"Failed: fail_count") print(f"Location: os.path.abspath(download_path)") print("=" * 50) except Exception as e: print(f"\nError loading playlist: e") print("Check URL or network connection.")
if name == "main": try: playlist_url, quality_choice = get_user_choice() download_playlist(playlist_url, quality_choice) except KeyboardInterrupt: print("\n\nDownload interrupted by user.") except Exception as e: print(f"\nUnexpected error: e")
For advanced users, consider adding:
ffmpegtkinter or PyQtimport tkinter as tk
from tkinter import messagebox
from pytube import Playlist
class YouTubePlaylistDownloader:
def __init__(self):
self.window = tk.Tk()
self.window.title("YouTube Playlist Downloader")
self.playlist_url_label = tk.Label(self.window, text="Enter the YouTube playlist URL:")
self.playlist_url_label.pack()
self.playlist_url_entry = tk.Entry(self.window, width=50)
self.playlist_url_entry.pack()
self.download_button = tk.Button(self.window, text="Download", command=self.download_playlist)
self.download_button.pack()
def download_playlist(self):
playlist_url = self.playlist_url_entry.get()
playlist = Playlist(playlist_url)
for video_url in playlist.video_urls:
video = pytube.YouTube(video_url)
video.streams.get_highest_resolution().download()
messagebox.showinfo("Success", "Playlist downloaded successfully!")
def run(self):
self.window.mainloop()
if __name__ == "__main__":
downloader = YouTubePlaylistDownloader()
downloader.run()
┌─────────────────┐
│ User Input │
│ - Playlist URL │
│ - Quality │
└────────┬────────┘
▼
┌─────────────────┐
│ Fetch Playlist │
│ (pytube.Playlist)│
└────────┬────────┘
▼
┌─────────────────┐
│ Iterate Videos │
└────────┬────────┘
▼
┌─────────────────┐
│ For each video: │
│ - Get stream │
│ - Download │
│ - Handle errors │
└─────────────────┘