Skip to main content

Overview

Media classes represent different types of media content (photos, videos, animated GIFs) attached to tweets. These classes provide methods for accessing media URLs and downloading content.

Media Base Class

The base class for all media types.

Attributes

id
str
The media ID.
display_url
str
The display URL.
expanded_url
str
The expanded display URL.
media_url
str
The media URL (HTTPS).
source_status_id
str
The source tweet ID.
source_user_id
str
The ID of the user who posted the source tweet.
type
str
The media type (‘photo’, ‘video’, or ‘animated_gif’).
url
str
The URL of the media.
sizes
dict
The sizes of the media (thumb, small, medium, large).
original_info
dict
Original media information including width and height.
width
int
The width of the media.
height
int
The height of the media.
focus_rects
list
Focus rectangles for the media.

Methods

get()

Retrieves the media content. Returns: bytes - The raw content of the media.
content = await media.get()

download()

Downloads the media content and saves it to the specified file.
output_path
str
required
The path where the downloaded file will be saved.
await media.download('image.jpg')

Photo Class

Represents a photo media object.

Additional Attributes

features
dict
The features of the photo.

Example

tweet = await client.get_tweet_by_id('1234567890')

for media in tweet.media:
    if media.type == 'photo':
        print(f"Photo ID: {media.id}")
        print(f"Size: {media.width}x{media.height}")
        print(f"URL: {media.media_url}")
        
        # Download the photo
        await media.download(f'photo_{media.id}.jpg')

Stream Class

Represents a media stream for videos and animated GIFs.

Attributes

url
str
The URL of the stream.
bitrate
int
The bitrate of the stream.
content_type
str
The MIME type of the stream content.

Methods

get()

Retrieves the stream content. Returns: bytes - The raw content of the stream.
content = await stream.get()

download()

Downloads the stream content and saves it to the specified file.
output_path
str
required
The path where the downloaded file will be saved.
await stream.download('video.mp4')

AnimatedGif Class

Represents an animated GIF media object.

Additional Attributes

video_info
dict
The video information of the GIF.
aspect_ratio
tuple[int, int]
The aspect ratio of the GIF.
streams
list[Stream]
The list of video streams for the GIF.

Example

tweet = await client.get_tweet_by_id('1234567890')

for media in tweet.media:
    if isinstance(media, AnimatedGif):
        print(f"Animated GIF ID: {media.id}")
        print(f"Aspect Ratio: {media.aspect_ratio}")
        
        # Download the GIF (as MP4)
        if media.streams:
            await media.streams[0].download(f'gif_{media.id}.mp4')

Video Class

Represents a video media object.

Additional Attributes

video_info
dict
The video information.
aspect_ratio
tuple[int, int]
The aspect ratio of the video.
duration_millis
int
The duration of the video in milliseconds.
streams
list[Stream]
The list of video streams for the video. Streams are sorted by quality, with higher quality streams first.

Methods

get_subtitles()

Retrieves the subtitles for the video. Returns: webvtt.WebVTT | None - Returns the subtitles for the video. If the video does not have subtitles, returns None. Refer to the webvtt-py documentation for more information on working with subtitles.
tweet = await client.get_tweet_by_id('1234567890')
video = tweet.media[0]
subtitles = await video.get_subtitles()

if subtitles:
    for caption in subtitles:
        print(caption.start)
        print(caption.end)
        print(caption.text)

Example

tweet = await client.get_tweet_by_id('1234567890')

for media in tweet.media:
    if media.type == 'video':
        print(f"Video ID: {media.id}")
        print(f"Duration: {media.duration_millis / 1000} seconds")
        print(f"Aspect Ratio: {media.aspect_ratio}")
        
        # Get available streams
        streams = media.streams
        print(f"Available streams: {len(streams)}")
        
        for i, stream in enumerate(streams):
            print(f"  Stream {i+1}:")
            print(f"    Bitrate: {stream.bitrate}")
            print(f"    Content Type: {stream.content_type}")
        
        # Download highest quality stream
        if streams:
            await streams[0].download('video.mp4')

Complete Examples

Download All Media from a Tweet

# Media classes are returned by Tweet.media - no import needed

tweet = await client.get_tweet_by_id('1234567890')

if tweet.media:
    print(f"Found {len(tweet.media)} media items")
    
    for i, media in enumerate(tweet.media):
        if media.type == 'photo':
            filename = f'photo_{i+1}.jpg'
            await media.download(filename)
            print(f"Downloaded photo: {filename}")
        
        elif media.type == 'video':
            filename = f'video_{i+1}.mp4'
            # Download highest quality stream
            await media.streams[0].download(filename)
            print(f"Downloaded video: {filename}")
            
            # Get subtitles if available
            subtitles = await media.get_subtitles()
            if subtitles:
                sub_filename = f'video_{i+1}_subtitles.vtt'
                subtitles.save(sub_filename)
                print(f"Downloaded subtitles: {sub_filename}")
        
        elif media.type == 'animated_gif':
            filename = f'gif_{i+1}.mp4'
            await media.streams[0].download(filename)
            print(f"Downloaded GIF: {filename}")
else:
    print("No media found in tweet")

Download Specific Video Quality

tweet = await client.get_tweet_by_id('1234567890')

for media in tweet.media:
    if media.type == 'video':
        # Find the stream with desired bitrate
        # Streams are typically ordered by quality (highest first)
        
        # Get highest quality
        highest_quality = media.streams[0]
        print(f"Highest quality bitrate: {highest_quality.bitrate}")
        await highest_quality.download('video_high.mp4')
        
        # Or find a specific bitrate range
        target_bitrate = 1000000  # 1 Mbps
        best_stream = min(
            media.streams,
            key=lambda s: abs(s.bitrate - target_bitrate)
        )
        await best_stream.download('video_medium.mp4')

Get Media Information

tweet = await client.get_tweet_by_id('1234567890')

if tweet.media:
    for media in tweet.media:
        print(f"Media Type: {media.type}")
        print(f"Media ID: {media.id}")
        print(f"Dimensions: {media.width}x{media.height}")
        print(f"URL: {media.media_url}")
        
        if media.type == 'video':
            print(f"Duration: {media.duration_millis / 1000} seconds")
            print(f"Streams: {len(media.streams)}")
            for stream in media.streams:
                bitrate_mbps = stream.bitrate / 1_000_000
                print(f"  - {bitrate_mbps:.2f} Mbps ({stream.content_type})")
        
        print("-" * 50)

Process Video Subtitles

tweet = await client.get_tweet_by_id('1234567890')

for media in tweet.media:
    if media.type == 'video':
        subtitles = await media.get_subtitles()
        
        if subtitles:
            print("Video Subtitles:")
            print("-" * 50)
            
            for caption in subtitles:
                print(f"[{caption.start} --> {caption.end}]")
                print(caption.text)
                print()
        else:
            print("No subtitles available for this video")

Bulk Download User’s Media

import os
# Media classes are returned by Tweet.media - no import needed

user = await client.get_user_by_screen_name('example_user')
tweets = await user.get_tweets('Media', count=100)

# Create directory for downloads
os.makedirs(f'media_{user.screen_name}', exist_ok=True)

media_count = {'photos': 0, 'videos': 0, 'gifs': 0}

for tweet in tweets:
    if tweet.media:
        for media in tweet.media:
            if media.type == 'photo':
                filename = f'media_{user.screen_name}/photo_{tweet.id}_{media.id}.jpg'
                await media.download(filename)
                media_count['photos'] += 1
            
            elif media.type == 'video':
                filename = f'media_{user.screen_name}/video_{tweet.id}_{media.id}.mp4'
                await media.streams[0].download(filename)
                media_count['videos'] += 1
            
            elif media.type == 'animated_gif':
                filename = f'media_{user.screen_name}/gif_{tweet.id}_{media.id}.mp4'
                await media.streams[0].download(filename)
                media_count['gifs'] += 1

print(f"Downloaded:")
print(f"  Photos: {media_count['photos']}")
print(f"  Videos: {media_count['videos']}")
print(f"  GIFs: {media_count['gifs']}")
print(f"  Total: {sum(media_count.values())}")
For a complete example of downloading tweet media, see the download_tweet_media.py example in the Twikit repository.

Build docs developers (and LLMs) love