Last active
December 9, 2024 00:12
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 = [] |
i am getting below error
File "delall-icloud-photos.py", line 10, in
username = sys.argv[1]
IndexError: list index out of range
I just had a similar issue. Made a quick script to do it :
https://github.com/zakirangwala/icloud-photo-manager
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
Hi, combining the previous comments and making some further changes, the following process worked for me:
git clone https://github.com/ndbroadbent/icloud_photos_downloader
cd icloud_photos_downloader
cd icloudpd
curl -sfLO https://gist.github.com/Tatsh/0b5a10a2d25f6c8466290401d2026055/raw/77d23ca0d1448f8e8eb4f208dfcfe84781d98d67/delall-icloud-photos.py
Change the line:
icloud = authenticate(username, password, smtp_username, smtp_password, smtp_host, smtp_port, smtp_no_tls, notification_email)
to
icloud = authenticate(username, password)
Install icloudpd dependencies by installing icloudpd (Its documentation talks about how to do this)
Finally, run:
python delall-icloud-photos.py
The first time you run this, it will perform two factor authentication.
It will work well afterwards.