CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pytube

Python library for downloading YouTube videos with comprehensive stream management and metadata extraction capabilities.

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Handling

Comprehensive exception hierarchy for handling various error conditions including video availability, network issues, extraction failures, and other operational errors in pytube.

Capabilities

Base Exception

Root exception class for all pytube-specific errors.

class PytubeError(Exception):
    """
    Base exception class for all pytube errors.
    
    All other pytube exceptions inherit from this base class,
    allowing for comprehensive error handling.
    """

Network and Retry Exceptions

Exceptions related to network operations and request failures.

class MaxRetriesExceeded(PytubeError):
    """
    Exception raised when maximum retry attempts are exceeded.
    
    Occurs during download operations when network requests
    fail repeatedly beyond the configured retry limit.
    """

HTML Parsing and Data Extraction Exceptions

Exceptions related to parsing YouTube pages and extracting video data.

class HTMLParseError(PytubeError):
    """
    Exception raised when HTML parsing fails.
    
    Occurs when pytube cannot parse YouTube page content,
    often due to page structure changes or malformed HTML.
    """

class ExtractError(PytubeError):
    """
    Exception raised when data extraction fails.
    
    General exception for failures in extracting video information,
    stream data, or metadata from YouTube responses.
    """

class RegexMatchError(ExtractError):
    def __init__(self, caller: str, pattern: Union[str, Pattern]):
        """
        Exception raised when regular expression matching fails.
        
        Args:
            caller (str): The function or method where the regex failed
            pattern (str or Pattern): The regex pattern that failed to match
        """

Video Availability Exceptions

Base class and specific exceptions for various video availability issues.

class VideoUnavailable(PytubeError):
    def __init__(self, video_id: str):
        """
        Base exception for video unavailability issues.
        
        Args:
            video_id (str): The YouTube video ID that is unavailable
        """

class AgeRestrictedError(VideoUnavailable):
    def __init__(self, video_id: str):
        """
        Exception raised when video is age-restricted.
        
        Occurs when attempting to access age-restricted content
        without proper authentication or when content has
        tier 3 age restrictions that cannot be bypassed.
        
        Args:
            video_id (str): The age-restricted video ID
        """

class LiveStreamError(VideoUnavailable):
    def __init__(self, video_id: str):
        """
        Exception raised when attempting to download live streams.
        
        Live streams cannot be downloaded as they are ongoing
        broadcasts without fixed content.
        
        Args:
            video_id (str): The live stream video ID
        """

class VideoPrivate(VideoUnavailable):
    def __init__(self, video_id: str):
        """
        Exception raised when video is private.
        
        Occurs when attempting to access private videos that
        require specific permissions or are only visible to
        the uploader.
        
        Args:
            video_id (str): The private video ID
        """

class RecordingUnavailable(VideoUnavailable):
    def __init__(self, video_id: str):
        """
        Exception raised when live stream recording is unavailable.
        
        Occurs when a live stream has ended but the recording
        is not yet available or has been disabled.
        
        Args:
            video_id (str): The unavailable recording video ID
        """

class MembersOnly(VideoUnavailable):
    def __init__(self, video_id: str):
        """
        Exception raised when video is members-only content.
        
        Occurs when attempting to access content restricted
        to channel members without proper membership status.
        
        Args:
            video_id (str): The members-only video ID
        """

class VideoRegionBlocked(VideoUnavailable):
    def __init__(self, video_id: str):
        """
        Exception raised when video is blocked in the user's region.
        
        Occurs when content is geo-restricted and not available
        in the user's geographic location.
        
        Args:
            video_id (str): The region-blocked video ID
        """

Usage Examples

Basic Exception Handling

from pytube import YouTube
from pytube.exceptions import VideoUnavailable, AgeRestrictedError, PytubeError

def safe_download(video_url):
    """Download video with comprehensive error handling."""
    try:
        yt = YouTube(video_url)
        stream = yt.streams.get_highest_resolution()
        
        if stream:
            file_path = stream.download()
            print(f"Successfully downloaded: {file_path}")
            return file_path
        else:
            print("No suitable stream found")
            return None
            
    except VideoUnavailable as e:
        print(f"Video unavailable: {e}")
        return None
    except AgeRestrictedError as e:
        print(f"Age-restricted content: {e}")
        return None
    except PytubeError as e:
        print(f"Pytube error: {e}")
        return None
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None

# Usage
result = safe_download('https://www.youtube.com/watch?v=VIDEO_ID')

Specific Exception Handling

from pytube import YouTube
from pytube.exceptions import (
    VideoPrivate, MembersOnly, LiveStreamError, 
    RecordingUnavailable, VideoRegionBlocked
)

def handle_specific_errors(video_url):
    """Handle specific video availability issues."""
    try:
        yt = YouTube(video_url)
        return yt.streams.get_highest_resolution()
        
    except VideoPrivate:
        print("This video is private and cannot be accessed")
        return None
        
    except MembersOnly:
        print("This video is for channel members only")
        print("Consider becoming a channel member to access this content")
        return None
        
    except LiveStreamError:
        print("Cannot download live streams - wait for the recording")
        return None
        
    except RecordingUnavailable:
        print("Live stream recording not yet available")
        return None
        
    except VideoRegionBlocked:
        print("Video is blocked in your region")
        print("Consider using a VPN or proxy")
        return None

# Usage
stream = handle_specific_errors('https://www.youtube.com/watch?v=VIDEO_ID')

Retry Logic with Exception Handling

from pytube import YouTube
from pytube.exceptions import MaxRetriesExceeded, ExtractError, HTMLParseError
import time
import random

def download_with_retry(video_url, max_attempts=3):
    """Download with custom retry logic."""
    
    for attempt in range(max_attempts):
        try:
            print(f"Attempt {attempt + 1}/{max_attempts}")
            
            yt = YouTube(video_url)
            stream = yt.streams.get_highest_resolution()
            
            if stream:
                file_path = stream.download()
                print(f"Download successful: {file_path}")
                return file_path
                
        except MaxRetriesExceeded:
            print(f"Max retries exceeded on attempt {attempt + 1}")
            if attempt < max_attempts - 1:
                wait_time = random.uniform(1, 3) * (attempt + 1)
                print(f"Waiting {wait_time:.1f} seconds before retry...")
                time.sleep(wait_time)
            
        except (ExtractError, HTMLParseError) as e:
            print(f"Extraction/parsing error on attempt {attempt + 1}: {e}")
            if attempt < max_attempts - 1:
                print("Retrying with fresh YouTube object...")
                time.sleep(2)
            
        except Exception as e:
            print(f"Unexpected error: {e}")
            break
    
    print("All attempts failed")
    return None

# Usage
result = download_with_retry('https://www.youtube.com/watch?v=VIDEO_ID')

Bulk Operations with Error Logging

from pytube import Playlist
from pytube.exceptions import PytubeError, VideoUnavailable
import logging
from datetime import datetime

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('pytube_errors.log'),
        logging.StreamHandler()
    ]
)

def download_playlist_with_error_logging(playlist_url):
    """Download playlist with comprehensive error logging."""
    
    try:
        playlist = Playlist(playlist_url)
        logging.info(f"Starting download of playlist: {playlist.title}")
        logging.info(f"Total videos: {playlist.length}")
        
        successful = []
        failed = []
        
        for i, video in enumerate(playlist.videos, 1):
            try:
                logging.info(f"Processing video {i}/{playlist.length}: {video.title}")
                
                stream = video.streams.get_highest_resolution()
                if stream:
                    file_path = stream.download()
                    successful.append({
                        'title': video.title,
                        'url': video.watch_url,
                        'file_path': file_path
                    })
                    logging.info(f"Successfully downloaded: {video.title}")
                else:
                    raise PytubeError("No suitable stream found")
                    
            except VideoUnavailable as e:
                error_info = {
                    'title': getattr(video, 'title', 'Unknown'),
                    'url': getattr(video, 'watch_url', 'Unknown'),
                    'error': str(e),
                    'error_type': type(e).__name__
                }
                failed.append(error_info)
                logging.warning(f"Video unavailable: {error_info['title']} - {e}")
                
            except PytubeError as e:
                error_info = {
                    'title': getattr(video, 'title', 'Unknown'),
                    'url': getattr(video, 'watch_url', 'Unknown'),
                    'error': str(e),
                    'error_type': type(e).__name__
                }
                failed.append(error_info)
                logging.error(f"Pytube error for {error_info['title']}: {e}")
                
            except Exception as e:
                error_info = {
                    'title': getattr(video, 'title', 'Unknown'),
                    'url': getattr(video, 'watch_url', 'Unknown'),
                    'error': str(e),
                    'error_type': type(e).__name__
                }
                failed.append(error_info)
                logging.error(f"Unexpected error for {error_info['title']}: {e}")
        
        # Summary logging
        logging.info(f"Download completed - Success: {len(successful)}, Failed: {len(failed)}")
        
        return {
            'successful': successful,
            'failed': failed,
            'playlist_title': playlist.title
        }
        
    except Exception as e:
        logging.error(f"Failed to process playlist {playlist_url}: {e}")
        return None

# Usage
results = download_playlist_with_error_logging(
    'https://www.youtube.com/playlist?list=PLAYLIST_ID'
)

if results:
    print(f"Playlist: {results['playlist_title']}")
    print(f"Successful downloads: {len(results['successful'])}")
    print(f"Failed downloads: {len(results['failed'])}")
    
    if results['failed']:
        print("\nFailed downloads:")
        for failure in results['failed']:
            print(f"- {failure['title']}: {failure['error_type']}")

Age-Restricted Content Handling

from pytube import YouTube
from pytube.exceptions import AgeRestrictedError

def handle_age_restricted_content(video_url):
    """Handle age-restricted content with OAuth fallback."""
    
    # First attempt without OAuth
    try:
        yt = YouTube(video_url)
        yt.check_availability()  # This will raise AgeRestrictedError if needed
        
        stream = yt.streams.get_highest_resolution()
        return stream.download()
        
    except AgeRestrictedError:
        print("Video is age-restricted, attempting OAuth authentication...")
        
        try:
            # Retry with OAuth
            yt_oauth = YouTube(
                video_url,
                use_oauth=True,
                allow_oauth_cache=True
            )
            
            stream = yt_oauth.streams.get_highest_resolution()
            if stream:
                return stream.download()
            else:
                print("No suitable stream found even with OAuth")
                return None
                
        except AgeRestrictedError:
            print("Content has tier 3 age restrictions and cannot be accessed")
            return None
            
        except Exception as e:
            print(f"OAuth authentication failed: {e}")
            return None

# Usage
result = handle_age_restricted_content('https://www.youtube.com/watch?v=AGE_RESTRICTED_VIDEO')

Custom Exception Context Manager

from pytube import YouTube
from pytube.exceptions import PytubeError
from contextlib import contextmanager

@contextmanager
def pytube_error_context(operation_description="pytube operation"):
    """Context manager for pytube operations with standardized error handling."""
    
    try:
        yield
        
    except VideoUnavailable as e:
        print(f"Video unavailable during {operation_description}: {e}")
        raise
        
    except AgeRestrictedError as e:
        print(f"Age-restricted content encountered during {operation_description}: {e}")
        raise
        
    except MaxRetriesExceeded as e:
        print(f"Network issues during {operation_description}: {e}")
        raise
        
    except (ExtractError, HTMLParseError) as e:
        print(f"Data extraction failed during {operation_description}: {e}")
        raise
        
    except PytubeError as e:
        print(f"Pytube error during {operation_description}: {e}")
        raise
        
    except Exception as e:
        print(f"Unexpected error during {operation_description}: {e}")
        raise

# Usage
def safe_video_info(video_url):
    with pytube_error_context("video info extraction"):
        yt = YouTube(video_url)
        return {
            'title': yt.title,
            'author': yt.author,
            'length': yt.length,
            'views': yt.views
        }

# Usage
try:
    info = safe_video_info('https://www.youtube.com/watch?v=VIDEO_ID')
    print(f"Video info: {info}")
except PytubeError:
    print("Failed to get video info due to pytube error")
except Exception:
    print("Failed to get video info due to unexpected error")

Types

from typing import Union
import re

# Type for regex patterns
Pattern = Union[str, re.Pattern]

# Exception hierarchy summary for type checking
VideoAvailabilityError = Union[
    VideoUnavailable,
    AgeRestrictedError,
    LiveStreamError,
    VideoPrivate,
    RecordingUnavailable,
    MembersOnly,
    VideoRegionBlocked
]

ExtractionError = Union[
    HTMLParseError,
    ExtractError,
    RegexMatchError
]

NetworkError = Union[
    MaxRetriesExceeded
]

Install with Tessl CLI

npx tessl i tessl/pypi-pytube

docs

captions.md

collections.md

exceptions.md

index.md

stream-management.md

video-downloads.md

tile.json