Skip to content

Instantly share code, notes, and snippets.

@Tatsh
Last active December 9, 2024 00:12
Show Gist options
  • Save Tatsh/0b5a10a2d25f6c8466290401d2026055 to your computer and use it in GitHub Desktop.
Save Tatsh/0b5a10a2d25f6c8466290401d2026055 to your computer and use it in GitHub Desktop.
Use pyicloud to delete all photos from iCloud (may need to be run multiple times)
#!/usr/bin/env python
from __future__ import print_function
import json
import sys
from authentication import authenticate
from future.moves.urllib.parse import urlencode
if __name__ == '__main__':
username = sys.argv[1]
password = sys.argv[2]
smtp_username = smtp_password = smtp_host = smtp_port = smtp_no_tls = notification_email = None
print('Logging in')
icloud = authenticate(username, password, smtp_username, smtp_password, smtp_host, smtp_port, smtp_no_tls, notification_email)
photos = icloud.photos.all
operations = []
url = '{}/records/modify?{}'.format(icloud.photos._service_endpoint, urlencode(icloud.photos.params))
headers = {'Content-type': 'text/plain'}
seen_record_names = []
for photo in photos:
# Avoid duplicate operations
if photo._asset_record['recordName'] in seen_record_names:
continue
seen_record_names.append(photo._asset_record['recordName'])
mr = {'fields': {'isDeleted': {'value': 1}}}
mr['recordChangeTag'] = photo._asset_record['recordChangeTag']
mr['recordName'] = photo._asset_record['recordName']
mr['recordType'] = 'CPLAsset'
op = dict(
operationType='update',
record=mr,
)
operations.append(op)
# Limit to 100 photos at a time
if len(operations) >= 100:
post_data = json.dumps(dict(
atomic=True,
desiredKeys=['isDeleted'],
operations=operations,
zoneID={'zoneName': 'PrimarySync'},
))
print('Deleting 100 photos')
print(icloud.photos.session.post(url,
data=post_data,
headers=headers).json())
operations = []
@sfdcai
Copy link

sfdcai commented Jan 30, 2023

i am getting below error
File "delall-icloud-photos.py", line 10, in
username = sys.argv[1]
IndexError: list index out of range

@zakirangwala
Copy link

I just had a similar issue. Made a quick script to do it :
https://github.com/zakirangwala/icloud-photo-manager

@CodeCouturiers
Copy link

Works for me

from pyicloud import PyiCloudService
from pyicloud.exceptions import PyiCloudAPIResponseException
import sys
import time

# Your credentials
EMAIL = '[email protected]'
PASSWORD = 'xxxxxxx'  # Enter your password here


def handle_2fa(api):
    if api.requires_2fa:
        print("Two-factor authentication required")
        code = input("Enter the code you received: ")
        result = api.validate_2fa_code(code)
        print("2FA validation result:", result)

    if api.requires_2sa:
        print("Two-step authentication required")
        devices = api.trusted_devices
        print("Your trusted devices:")

        for i, device in enumerate(devices):
            device_name = device.get('deviceName')
            phone_number = device.get('phoneNumber')
            if device_name:
                print(f"  {i}: {device_name}")
            else:
                print(f"  {i}: SMS to {phone_number}")

        device = devices[int(input("Which device to use? "))]
        if not api.send_verification_code(device):
            print("Failed to send verification code")
            sys.exit(1)

        code = input("Enter verification code: ")
        if not api.validate_verification_code(device, code):
            print("Invalid verification code")
            sys.exit(1)


try:
    # Create connection with retries
    max_retries = 3
    retry_count = 0

    while retry_count < max_retries:
        try:
            api = PyiCloudService(EMAIL, PASSWORD)
            handle_2fa(api)  # Handle 2FA if required
            break
        except PyiCloudAPIResponseException as e:
            retry_count += 1
            if retry_count == max_retries:
                raise e
            print(f"Attempt {retry_count} failed, trying again in 5 seconds...")
            time.sleep(5)

    count = 1

    # Iterate through all photos
    for photo in api.photos.all:
        print(f"Count : {count}")
        print(f"Filename: {photo.filename}")  # Added filename output for verification
        count += 1

        # Uncomment this block when you're ready to delete photos
        try:
            photo.delete()
            print(f"Deleted photo: {photo.filename}")
        except Exception as e:
            print(f"Failed to delete photo: {photo.filename}. Error: {e}")

except PyiCloudAPIResponseException as e:
    print(f"iCloud API Error: {e}")
    print("Make sure your credentials are correct and two-factor authentication is properly set up")
except Exception as e:
    print(f"An error occurred: {e}")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment