{"id":23098931,"url":"https://github.com/xob0t/google-photos-toolkit","last_synced_at":"2025-05-16T13:05:52.592Z","repository":{"id":215886757,"uuid":"739967207","full_name":"xob0t/Google-Photos-Toolkit","owner":"xob0t","description":"Userscript to filter, search, organize, or delete your Google Photos library","archived":false,"fork":false,"pushed_at":"2025-05-03T07:20:35.000Z","size":18108,"stargazers_count":396,"open_issues_count":13,"forks_count":24,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-03T08:34:58.545Z","etag":null,"topics":["bulk-operation","google-photos","javascipt","mass-delete","organize","userscript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xob0t.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-01-07T05:03:58.000Z","updated_at":"2025-05-03T07:22:08.000Z","dependencies_parsed_at":"2024-07-31T17:30:18.723Z","dependency_job_id":"f6df5c24-2ccf-4dfe-a2b3-2a366cae2f1e","html_url":"https://github.com/xob0t/Google-Photos-Toolkit","commit_stats":null,"previous_names":["xob0t/google-photos-fast-purge","xob0t/google-photos-toolkit"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xob0t%2FGoogle-Photos-Toolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xob0t%2FGoogle-Photos-Toolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xob0t%2FGoogle-Photos-Toolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xob0t%2FGoogle-Photos-Toolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xob0t","download_url":"https://codeload.github.com/xob0t/Google-Photos-Toolkit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254535827,"owners_count":22087399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bulk-operation","google-photos","javascipt","mass-delete","organize","userscript"],"created_at":"2024-12-16T23:15:17.912Z","updated_at":"2025-05-16T13:05:52.574Z","avatar_url":"https://github.com/xob0t.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Google Photos Toolkit\n\nBulk organize your media\n\n![demo](media/demo.png)\n\n## How It Works\n\nIn your browser, utilizing GP's undocumented web api\n\n## How To Install\n\n1. Install any recommended userscript manager for your browser\n\n   - [Violentmonkey](https://violentmonkey.github.io/)\n   - [Tampermonkey](https://www.tampermonkey.net/)\n   - If you're on Android, try [Firefox](https://www.mozilla.org/firefox/browsers/mobile/android/) browser, it supports Tampermonkey\n\n2. Click [Install](https://github.com/xob0t/Google-Photos-Toolkit/releases/latest/download/google_photos_toolkit.user.js)\n3. Accept installation\n\n## How to use\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cstrong\u003e🚀 Click to expand: Tutorial\u003c/strong\u003e\u003c/summary\u003e\n\n1. Go to [photos.google.com](https://photos.google.com/) and click the GPTK icon in the top bar to open it\n\n   ![demo](media/tutorial/step0.png)\n\n2. Select a source from which to read from:\n\n   ![demo](media/tutorial/step1.png)\n\n3. Use Filters to filter found items with:\n\n   ![demo](media/tutorial/step2.png)\n\n4. Select an action to apply to found items:\n\n   ![demo](media/tutorial/step3.png)\n\n\u003c/details\u003e\n\n### Finding space-consuming media\n\nThis example groups all space-consuming media in one album.\n\n1. Make sure \"Library\" is the selected source\n2. Select `SPACE-CONSUMING` in the `Space` filter\n3. Select action `Add to new album`\n\n### Identify media not in any albums\n\nSelect all albums in the `Exclude albums` filter, then use appropriate action.\n\n### Identifying duplicates/similar images\n\nUse `Similarity` filter with action `Add to new album`\nMedia with similar thumbnails will be added to the album.\n\n### Deleting all media in the library\n\nAs simple as selecting \"Library\" source, clicking `Move to trash`, then clearing it.\n\n### Use GPTK's api\n\nGPTK exports it's api class globally so you can use it in your browser's console.  \nIt's much more powerful than the UI!\n\nExample usage.\nScan the whole library for media owned by `ownerName` and move it to trash if found.\n\n```js\nlet nextPageId = null;\nconst ownerName = \"John\";\ndo {\n  const page = await gptkApi.getItemsByUploadedDate(nextPageId);\n  for (const item of page.items) {\n    if (item.isOwned) continue;\n    const itemInfo = await gptkApi.getItemInfoExt(item.mediaKey);\n    console.log(`${item.mediaKey} is shared by ${itemInfo.owner.name}`);\n    if (itemInfo.owner.name == ownerName) {\n      await gptkApi.moveItemsToTrash([itemInfo.dedupKey]);\n      console.log(`${item.mediaKey} moved to trash`);\n    }\n  }\n  nextPageId = page.nextPageId;\n} while (nextPageId);\nconsole.log(\"DONE\");\n```\n\n## Contributions welcome\n\nIf you want to learn more about how GP's api works, read [https://kovatch.medium.com/deciphering-google-batchexecute-74991e4e446c](https://kovatch.medium.com/deciphering-google-batchexecute-74991e4e446c)  \nI just found this post, after doing all the work from zero :D\n\nAlso, i've made a userscript that parses all responses and logs them to console in a more readable way, you can find it here - [https://github.com/xob0t/Google-Photos-Toolkit/tree/main/tools](https://github.com/xob0t/Google-Photos-Toolkit/tree/main/tools)\n\n## BUGS\n\nIf something does not work, open an [issue](https://github.com/xob0t/Google-Photos-Toolkit/issues) and describe it in detail\n\nIf you have a question, open a [discussion](https://github.com/xob0t/Google-Photos-Toolkit/discussions)\n\n## Credits\n\nBorrowed some code and UI inspiration from [undiscord](https://github.com/victornpb/undiscord)\n\n## My Other Google Photos Projects\n\n- Python client with unlimited uploads: [https://github.com/xob0t/gphotos_mobile_client](https://github.com/xob0t/gphotos_mobile_client)\n- Disguise any file as media for GP to accept and store it: [https://github.com/xob0t/gp-file-hide](https://github.com/xob0t/gp-file-hide)\n\n## ♥\n\nIf GPTK is useful to you, please consider supporting the project:\n\nBTC `12znTocLytrrYhQT4AJVeJdR8KTULWbKb7`  \nBTC Cash `qq7w48d6s3rddgxshl6ae48k7c5jyck76crvppqenn`  \nDOGE `DQjBzT2qMuXkLMawUXG7umTf3k9VeT4Y6K`  \nEtherium `0xcfe559D9F6056F82a6CFdEDA51c00132035955c8`  \nLitecoin `ltc1qcgc873py5k28qm85sk5d53yfwzle4cztmvkh6l`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxob0t%2Fgoogle-photos-toolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxob0t%2Fgoogle-photos-toolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxob0t%2Fgoogle-photos-toolkit/lists"}