Youtube Playlist Free Downloader Python Script
High-quality streams usually separate video and audio. Downloading them requires merging the two files (often using ffmpeg), but you can grab the video stream like this:
stream = video.streams.filter(resolution="1080p").first()
Before we dive into the code, a critical disclaimer. Downloading videos from YouTube may violate YouTube's Terms of Service. However, fair use arguments exist for:
This script is for educational purposes. Do not use it to redistribute copyrighted material or avoid paying for music. Respect content creators' rights.
The search term "free downloader" is the hook. Here is the reality of the cost: youtube playlist free downloader python script
End.
python -m venv yt_env
source yt_env/bin/activate # On Windows: yt_env\Scripts\activate
#!/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
def sanitize_filename(title): """Remove invalid characters from filename.""" return re.sub(r'[<>:"/\|?*]', '_', title) High-quality streams usually separate video and audio
def get_user_choice(): """Get playlist URL and quality preference from user.""" print("=" * 50) print(" YouTube Playlist Downloader") print("=" * 50)
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.""" Before we dive into the code, a critical disclaimer
# 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")
The real power comes from customizing ydl_opts. Here are three common scenarios.