How to Save All Images from Same Album Group in Telegram Bot Handler?

I’m working on a Telegram bot that needs to process multiple images sent together as an album. Right now my function only saves one image even when users send several photos at once.

Here’s what I have so far:

async def save_images(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Save all photos from a message with highest quality."""
    photos = update.message.photo
    saved_files = []

    if photos:
        # Get the best quality version
        photo_file_id = photos[-1].file_id
        print(f'Found photo: {photo_file_id}')

        try:
            telegram_file = await context.bot.get_file(photo_file_id)
            file_url = telegram_file.file_path
            
            # Make unique filename
            filename = f'image_{update.message.message_id}_{photos[-1].file_unique_id}.jpg'

            # Download the image
            response = requests.get(file_url)
            response.raise_for_status()
            
            with open(filename, 'wb') as image_file:
                image_file.write(response.content)
            
            saved_files.append(filename)
            print(f'Saved image: {photo_file_id}')
            
        except Exception as error:
            print(f'Failed to save image {photo_file_id}: {error}')

    print(f'Total saved images: {saved_files}')
    return saved_files

When I send two photos together, only one gets processed. The bot receives the album but my handler doesn’t loop through all the images in the group. How can I modify this to handle all photos from the same media group instead of just processing one at a time?

you’re missing the album handling completly. telegram sends each photo with same media_group_id but as seperate messages. try using a dict to collect them first like pending_albums = {} then check if media_group_id exists and append photos to that list. process after small delay or when you detect the album is complete.

check if update.message.media_group_id exists first - thats how telegram groups album photos together. your code ignores this completly and just grabs single photo. i use ConversationHandler with states to buffer incoming photos untill no more arrive within timeout period.

The issue is that your current handler processes individual messages, but Telegram sends each photo in an album as a separate message with the same media_group_id. You need to collect all messages belonging to the same media group before processing them. I had this exact problem when building a document archiving bot. What worked for me was implementing a delay mechanism to gather all photos from the same group. Store incoming photos in a temporary dictionary using update.message.media_group_id as the key, then use asyncio.sleep() for about 1-2 seconds before processing. This gives Telegram time to send all photos in the group. After the delay, check if more photos arrived with the same media group ID, and if not, process the entire batch. You’ll also want to add a check for update.message.media_group_id being None to handle single photos normally. The tricky part is managing the timing - too short and you miss photos, too long and users wait unnecessarily.

The core problem is that Telegram doesn’t send albums as single messages but rather as multiple individual messages that happen to share a media_group_id. Your current function processes each message immediately without considering whether more photos are coming. I ran into this exact scenario when building a gallery management bot last year. The solution involves implementing a debouncing mechanism where you temporarily store photos by their media group identifier and only process them after a brief pause. You’ll need to maintain a global dictionary to track pending albums and use asyncio.call_later() to schedule processing after approximately 1.5 seconds. Make sure to handle the case where media_group_id is None for single photos. One gotcha I discovered is that the delay timing can vary depending on network conditions, so you might want to make the timeout configurable. The final batch processing should iterate through all collected photos and download each one using the same logic you already have.

I faced similar issue with my photo backup bot. The problem is telegram’s album behavior - each photo arrives as individual message but they share same media_group_id. Your handler triggers for every single photo instead of waiting for complete album.

What I did was create a message collector that buffers photos by their media_group_id for few seconds before processing. Use asyncio.create_task() to schedule delayed processing and cancel previous task if new photo from same group arrives. This approach handles both single photos and albums properly.

Also consider using context.bot.download() instead of manual requests - it’s cleaner and handles telegram’s file download logic better. The key insight is treating albums as batch operations rather than individual messages.