Retrieving Google+ Auto-Backup Images via Python

Learn retrieving google+ auto-backup images via python with practical examples, diagrams, and best practices. Covers python, google-data-api development techniques with visual explanations.

Retrieving Google+ Auto-Backup Images via Python

Hero image for Retrieving Google+ Auto-Backup Images via Python

Learn how to programmatically access and download your Google+ Auto-Backup images using Python and the Google Photos Library API.

Before Google+ was deprecated, many users utilized its auto-backup feature to store photos and videos. While Google Photos has largely superseded this functionality, you might still have legacy content or wish to manage your media programmatically. This article guides you through the process of using Python to access and retrieve these images, leveraging the Google Photos Library API. We'll cover authentication, searching for media, and downloading files.

Understanding the Google Photos Library API

The Google Photos Library API is the primary interface for interacting with user content in Google Photos. It allows applications to list media items, search for specific photos or videos, and retrieve their metadata and download URLs. It's important to note that this API provides read-only access to user data; it does not support uploading, deleting, or modifying media items. For our purpose of retrieving auto-backup images, this API is perfectly suited.

sequenceDiagram
    participant User
    participant PythonApp as Python Application
    participant GoogleAPI as Google Photos Library API
    participant GoogleAuth as Google OAuth2

    User->>PythonApp: Initiates script
    PythonApp->>GoogleAuth: Request authorization URL
    GoogleAuth-->>PythonApp: Authorization URL
    PythonApp->>User: Open browser for authentication
    User->>GoogleAuth: Grants permission
    GoogleAuth-->>PythonApp: Authorization Code
    PythonApp->>GoogleAuth: Exchange code for tokens
    GoogleAuth-->>PythonApp: Access & Refresh Tokens
    PythonApp->>GoogleAPI: Search media items (with Access Token)
    GoogleAPI-->>PythonApp: List of media items (metadata + download URLs)
    PythonApp->>GoogleAPI: Download each media item
    GoogleAPI-->>PythonApp: Media file data
    PythonApp->>User: Saves images locally

Authentication and Media Retrieval Flow

Setting Up Your Google Cloud Project

Before you can write any Python code, you need to set up a project in the Google Cloud Console and enable the Google Photos Library API. This involves creating OAuth 2.0 client credentials, which your Python application will use to authenticate with Google's services. Make sure to download the client_secret.json file, as it contains the necessary credentials for your application.

1. Create a Google Cloud Project

Navigate to the Google Cloud Console (console.cloud.google.com), create a new project, or select an existing one.

2. Enable the Google Photos Library API

In the Cloud Console, go to 'APIs & Services' > 'Library'. Search for 'Google Photos Library API' and enable it.

Go to 'APIs & Services' > 'OAuth consent screen'. Configure it with an application name and scope https://www.googleapis.com/auth/photoslibrary.readonly.

4. Create OAuth 2.0 Client ID

Under 'APIs & Services' > 'Credentials', click 'Create Credentials' > 'OAuth client ID'. Choose 'Desktop app' as the application type. Download the client_secret.json file and save it in your project directory.

Python Implementation for Image Retrieval

With your Google Cloud project configured, we can now proceed with the Python implementation. We'll use the google-auth-oauthlib and google-api-python-client libraries to handle authentication and API interactions. The script will first authenticate, then list media items, and finally download them.

import os
import pickle
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
import io

# Scopes required for read-only access to Google Photos
SCOPES = ['https://www.googleapis.com/auth/photoslibrary.readonly']

def authenticate_google_photos():
    creds = None
    # The file token.pickle stores the user's access and refresh tokens
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)

    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'client_secret.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)
    return creds

def get_photos_service():
    creds = authenticate_google_photos()
    service = build('photoslibrary', 'v1', credentials=creds, static_discovery=False)
    return service

def download_media_items(service, download_path='google_photos_backup'):
    if not os.path.exists(download_path):
        os.makedirs(download_path)

    page_token = None
    while True:
        results = service.mediaItems().list(pageSize=100, pageToken=page_token).execute()
        items = results.get('mediaItems', [])

        if not items:
            print('No media items found.')
            break

        for item in items:
            filename = item['filename']
            base_url = item['baseUrl']
            # Append '=d' to the baseUrl to get the direct download link
            download_url = f"{base_url}=d"

            file_path = os.path.join(download_path, filename)
            if os.path.exists(file_path):
                print(f"Skipping existing file: {filename}")
                continue

            print(f"Downloading {filename}...")
            try:
                request = service.mediaItems().get(mediaItemId=item['id'])
                # The actual download requires a separate HTTP request, not directly via service.mediaItems().get
                # For direct download, we use the 'baseUrl=d' approach with a simple HTTP GET
                # For simplicity, this example assumes direct download via requests library or similar
                # A more robust solution would use googleapiclient.http.MediaIoBaseDownload for resumable downloads
                # For this example, we'll simulate a direct download using the base_url=d
                # In a real scenario, you'd use requests.get(download_url, stream=True) and save content
                
                # Placeholder for actual download logic:
                # response = requests.get(download_url, stream=True)
                # with open(file_path, 'wb') as f:
                #     for chunk in response.iter_content(chunk_size=8192):
                #         f.write(chunk)
                
                # For demonstration, we'll just print the download URL
                print(f"Simulating download of {filename} from {download_url}")
                # To make this functional, you'd integrate a library like 'requests'
                # import requests
                # r = requests.get(download_url, stream=True)
                # with open(file_path, 'wb') as f:
                #     for chunk in r.iter_content(chunk_size=8192):
                #         f.write(chunk)

            except Exception as e:
                print(f"Error downloading {filename}: {e}")

        page_token = results.get('nextPageToken')
        if not page_token:
            break

if __name__ == '__main__':
    service = get_photos_service()
    download_media_items(service)
    print("Download process completed.")

Python script for authenticating and listing Google Photos media items. Note: Actual download logic using requests library is commented out for brevity but is essential for a functional script.

Refining Your Search and Download

The provided script lists all media items. You might want to filter these items, for example, by date, album, or specific keywords. The Google Photos Library API offers robust search capabilities through the mediaItems.search method. You can specify dateFilter, contentFilter, or mediaTypeFilter to narrow down your results. For instance, to find only photos, you would use mediaTypeFilter={'mediaTypes': ['PHOTO']}.

def search_and_download_photos(service, download_path='filtered_photos_backup'):
    if not os.path.exists(download_path):
        os.makedirs(download_path)

    # Example: Search for photos only
    body = {
        'filters': {
            'mediaTypeFilter': {
                'mediaTypes': ['PHOTO']
            }
        },
        'pageSize': 100
    }

    page_token = None
    while True:
        if page_token:
            body['pageToken'] = page_token
        
        results = service.mediaItems().search(body=body).execute()
        items = results.get('mediaItems', [])

        if not items:
            print('No filtered media items found.')
            break

        for item in items:
            filename = item['filename']
            base_url = item['baseUrl']
            download_url = f"{base_url}=d"
            file_path = os.path.join(download_path, filename)

            if os.path.exists(file_path):
                print(f"Skipping existing file: {filename}")
                continue

            print(f"Downloading filtered {filename}...")
            # Actual download logic using 'requests' library would go here
            # import requests
            # r = requests.get(download_url, stream=True)
            # with open(file_path, 'wb') as f:
            #     for chunk in r.iter_content(chunk_size=8192):
            #         f.write(chunk)
            print(f"Simulating download of {filename} from {download_url}")

        page_token = results.get('nextPageToken')
        if not page_token:
            break

# To run this:
# if __name__ == '__main__':
#     service = get_photos_service()
#     search_and_download_photos(service)
#     print("Filtered download process completed.")

Example of searching for specific media types (photos only) before downloading.