pytubefix
Python3 library for downloading YouTube Videos. Current version is 10.3.8. It's a lightweight, Pythonic, dependency-free, library (and command-line utility) for downloading YouTube Videos. pytubefix is an actively maintained fork of pytube that solves broken functionality and adds new features, regularly addressing YouTube's continuous changes. It supports progressive and DASH streams, callback functions for download progress, and caption extraction.
Common errors
-
pytubefix.exceptions.VideoUnavailable: {video_id} is unavailablecause The video is private, deleted, region-locked, or YouTube's API structure changed, preventing `pytubefix` from accessing it.fixVerify the video URL is correct and the video is publicly accessible. Try updating `pytubefix` (`pip install --upgrade pytubefix`). For region-locked content, consider using proxies. Wrap calls in `try-except VideoUnavailable` for graceful handling. -
HTTP Error 410: Gone
cause YouTube has changed its internal API, rendering the current parsing logic in `pytubefix` obsolete for that specific video or stream. Often happens when YouTube deprecates old stream manifest formats.fixUpdate `pytubefix` to the latest version (`pip install --upgrade pytubefix`). This error frequently indicates that a new patch has been released to accommodate YouTube's changes. -
pytubefix.exceptions.AgeRestrictedError: {video_id} is age restricted, and can't be accessed without logging in.cause Attempting to download an age-restricted video without providing OAuth credentials.fixInstantiate `YouTube` with OAuth enabled: `yt = YouTube(url, use_oauth=True, allow_oauth_cache=True)`. This will prompt for browser authentication and cache the token. -
KeyError: 'videoDetails' or other dictionary key
cause YouTube frequently changes the keys in its JSON responses for video metadata, causing `pytubefix` to fail when parsing the data.fixThis typically requires a `pytubefix` library update. Install the latest version (`pip install --upgrade pytubefix`) to get the fix for the changed dictionary keys.
Warnings
- breaking YouTube's internal APIs change frequently, which can cause `pytubefix` functionality to break without warning. While `pytubefix` is actively maintained, users should expect occasional disruptions.
- gotcha Accessing age-restricted content or private videos often requires OAuth authentication. If `allow_oauth_cache=False` (default for some operations), you may be prompted repeatedly for authentication.
- gotcha Live streams typically cannot be downloaded until after they have concluded. Trying to download an active or recently finished live stream may result in errors or `LiveStreamEnded` exceptions.
- breaking Older versions (prior to v10.1.1 and v10.3.3) could encounter `TypeError` when accessing attributes like `.length` or find `yt.title` and `yt.duration` as bound methods instead of properties.
Install
-
pip install pytubefix
Imports
- YouTube
from pytubefix import YouTube
- Playlist
from pytubefix import Playlist
- Search
from pytubefix import Search
- on_progress
from pytubefix.cli import on_progress
- VideoUnavailable
from pytubefix.exceptions import VideoUnavailable
Quickstart
import os
from pytubefix import YouTube
def on_progress(stream, chunk, bytes_remaining):
total_size = stream.filesize
bytes_downloaded = total_size - bytes_remaining
percentage_of_completion = bytes_downloaded / total_size * 100
print(f"\rDownloading: {percentage_of_completion:.2f}%", end='')
video_url = os.environ.get('YOUTUBE_VIDEO_URL', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ') # Rick Astley - Never Gonna Give You Up
try:
yt = YouTube(video_url, on_progress_callback=on_progress)
print(f"\nTitle: {yt.title}")
print(f"Author: {yt.author}")
print(f"Views: {yt.views}")
# Get the highest resolution progressive stream
# Progressive streams contain both video and audio
stream = yt.streams.get_highest_resolution()
if stream:
print(f"Downloading '{yt.title}' in {stream.resolution}...")
stream.download(output_path='./downloads')
print("\nDownload complete!")
else:
print("No suitable progressive stream found.")
except Exception as e:
print(f"\nAn error occurred: {e}")