pyicloud

repository·master·Indexed 25 days ago

https://github.com/picklepete/pyicloud

A Python module for interacting with iCloud web services. It provides functionality to manage Find My iPhone (location, status, Lost Mode), Calendar events, Contacts, and the iCloud Photo Library. It also supports file operations in iCloud Drive and Ubiquity, including uploading, downloading, and directory management. The library includes support for Two-Factor (2FA) and Two-Step (2SA) authentication via the PyiCloudService class.

Tokens
2.1K
Snippets
3
Records
14
Agent score
34%

What's inside pyicloud

  1. Access and download photos from iCloud Photo Library

    master

    The iCloud Photo Library is accessed via the api.photos property.

    Browsing Photos:

    • api.photos.all: Access the 'All Photos' album. This album is sorted by added_date (most recent first).
    • api.photos.albums['AlbumName']: Access specific albums. These are sorted by asset_date (EXIF date).
    • Iterating over an album yields PhotoAsset objects.

    Downloading Photos:

    • Use photo.download() to download the original version. This returns a requests.Response object with stream=True. Use download.raw.read() or a buffered strategy like shutil.copyfile to save the file.
    • Versions: Each photo has a .versions property (e.g., ['medium', 'original', 'thumb']). To download a specific version, pass the version key to the download method: photo.download('thumb').

    Photo Metadata:

    • photo.filename: The filename of the asset.
    • photo.versions[version_key]['filename']: The filename associated with a specific version.
  2. Authenticate with PyiCloudService

    master

    To connect to iCloud, instantiate the PyiCloudService class with your username and password. If your Apple ID is registered in mainland China, you must pass china_mainland=True.

    If you have stored your password in the system keyring using the icloud CLI tool, you can instantiate the service without providing a password.

  3. Access and manage files in iCloud Drive

    master

    iCloud Drive is accessed via the api.drive property. It uses a dictionary-like interface to navigate directories and files.

    Navigation:

    • Use api.drive.dir() to list contents of the root.
    • Access folders and files using bracket notation: api.drive['Folder']['Subfolder']['file.ext'].
    • Use .dir() on a folder object to list its contents.

    File Metadata:

    • .name: The filename.
    • .date_modified: The modification timestamp (in UTC).
    • .size: File size in bytes.
    • .type: Returns 'file' for files.

    File Operations:

    • Download: Use .open(stream=True) to get a response object. It is recommended to use shutil.copyfileobj with response.raw to save the file to disk efficiently.
    • Upload: Use .upload(file_like_object) on a folder object. Always open local files in binary mode ('rb') to avoid decoding errors.
    • Management: Use .mkdir('name'), .rename('new_name'), and .delete() on folder or file objects.
  4. Handle Two-Factor Authentication (2FA)

    master
    When authenticating with PyiCloudService, check the requires_2fa property. If true, you must select a trusted device from api.trusted_devices, send a verification code using api.send_verification_code(device), and then validate the code using api.validate_verification_code(device, code). Trusted devices can be identified by their deviceName or phoneNumber.
  5. Debug pyicloud with SSL verification disabled

    master

    To debug network traffic using tools like mitmproxy, fiddler, or charles, you can monkeypatch requests.Session.merge_environment_settings to disable SSL verification. This allows the library to work even when intercepting proxies are used. Additionally, you can enable full HTTP debugging by patching http.client.print to use the logging framework and setting http.client.HTTPConnection.debuglevel = 1.

    import http.client
    import logging
    import requests
    import warnings
    from urllib3.exceptions import InsecureRequestWarning
    from pyicloud import PyiCloudService
    
    # 1. Disable SSL verification for requests
    old_merge_environment_settings = requests.Session.merge_environment_settings
    
    def merge_environment_settings(self, url, proxies, stream, verify, cert):
        settings = old_merge_environment_settings(self, url, proxies, stream, verify, cert)
        settings["verify"] = False
        return settings
    
    requests.Session.merge_environment_settings = merge_environment_settings
    
    # 2. Enable HTTP client debug logging
    httpclient_logger = logging.getLogger("http.client")
    def httpclient_logging_patch(level=logging.DEBUG):
        def httpclient_log(*args):
            httpclient_logger.log(level, " ".join(args))
        http.client.print = httpclient_log
        http.client.HTTPConnection.debuglevel = 1
    
    logging.basicConfig(level=logging.DEBUG)
    httpclient_logging_patch()
    
    # 3. Use the API
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", InsecureRequestWarning)
        api = PyiCloudService(username, password)
        # Perform requests...
  6. Handle Two-Factor (2FA) and Two-Step (2SA) Authentication

    master

    If your account has security enabled, you must handle the authentication flow by checking api.requires_2fa or api.requires_2sa.

    • 2FA: Use api.validate_2fa_code(code) to verify the code. If the session is not trusted, call api.trust_session().
    • 2SA: Access api.trusted_devices to find a device, call api.send_verification_code(device) to trigger the code, and then use api.validate_verification_code(device, code) to verify it.
  7. Access iCloud Contacts

    master

    Use the api.contacts.all() method to iterate through all contacts stored in iCloud. Note that this only includes contacts stored in iCloud, not those federated from other services like Facebook.

    for c in api.contacts.all():
        print(c.get('firstName'), c.get('phones'))
  8. Manage iCloud Files (Ubiquity)

    master

    Interact with the iCloud file system using the api.files property.

    • api.files.dir(): Lists the contents of the root directory.
    • Navigation: Use filenames as keys to navigate folders and files (e.g., api.files['Folder']['Subfolder']).
    • File Metadata: Access .name, .type ('folder' or 'file'), .size, and .modified (datetime).
    • Downloading: Use .open() on a file object. This returns a requests.Response object. You can access .content for raw data, .json() for JSON files, or use stream=True for large files to read the raw response.
  9. Manage iCloud Devices

    master

    Access the list of devices associated with your account via the api.devices property. This returns a dictionary mapping device IDs to AppleDevice objects. You can access a specific device by its index or its ID.

    As a shorthand, api.iphone provides access to the first device associated with your account (though this may not always be an iPhone).