BenV's notes

Rant: Google Photos

by on Dec.08, 2024, under Morons, Software

Paying for storage

<google> Would you like to pay us monthly for storage?
<BenV> Uhhh, not really. That said, Google Photos is MIGHTY convenient. I’ll think about it.

You’ve got to admit that having an app on your phone that automatically uploads and lets you easily edit photos, make albums, share them, search through them is awesome. It’s part of what caused the silent decline of bringing a proper DLSR camera for me.

Of course Google getting you hooked by offering all this convenience for free up to a certain amount is one thing. Then after a number of years of use you’ll probably hit that 15GB (or whatever it is today) limit, triggering them to nudge you towards “For only $ per month you’ll get Y GB of storage!” (and continued service). Not a bad deal in my opinion, but I hate paying monthly subscriptions.

Initially I went along with it, but even before the first payment went through I was scouring for alternatives. Surely there should be an alternative?

Immich to the rescue

It didn’t take long to find Immich, which is basically the exact same thing, but hosted yourself. Advantages include “private” (no matter what Google tells me, I’ll never accept uploading anything means they won’t read it), having proper control, and it being free, apart from having to run your own server. If you don’t do that already, well, it’s probably going to end up more expensive. But I have servers, and the storage for photo’s isn’t that huge (at Google Photos it was 15GB, a single movie can be bigger these days).

Running Immich is fairly trivial as well, depending on what you have in place. In my case:

  1. Create /docker/immich/docker-compose.yaml, losely based on their docker-compose.yaml
  2. Expose this to traefik:
    services:
    immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    # stuff here
    labels:
    # Have Watchtower auto-update this, it's a choice ;)
    - "com.centurylinklabs.watchtower.enable=true"
    # Traefik routing
    - "traefik.enable=true"
    - "traefik.docker.network=traefik"
    - "traefik.http.routers.immich.rule=Host(`immich.junerules.com`)"
    - "traefik.http.routers.immich.entrypoints=websecure"
    - "traefik.http.routers.immich.tls=true"
    - "traefik.http.routers.immich.tls.certresolver=junerules"
    - "traefik.http.routers.immich.tls.domains[0].main=junerules.com"
    - "traefik.http.routers.immich.tls.domains[0].sans=*.junerules.com"
    # other stuff
    networks:
    traefik:
    external: true
    name: traefik
  3. docker-compose up -d, we have a working https://immich.junerules.com (well, use your own domain :p)
  4. Add authentik in front, see https://docs.goauthentik.io/docs/install-config/install/docker-compose and https://docs.goauthentik.io/integrations/services/immich/
  5. immich authentik login

Great, so we’ve got a Google Photos replacement that’s (relatively) free. Comes with a phone app that’s almost the same too, excellent.

The Google Photos PROBLEM

Initially, things were smooth. Google has this awesome service to takeout your photos, simply go to https://takeout.google.com – state you want ALL your photos, 50GB zipfiles thanks, and a little later you’re downloading all your pictures including album info and metadata in a few big chunks.

Grab yourself a tool such as Immich-Go to import these (it’s straightforward – create api key, point to your zips, make sure it’s sane, run), and within a few hours you should have all your stuff imported into Immich. Yay!

Next: Removing your old photos from Google Photos. So this part certainly made me hate Google and their filthy $#%(^(*@#($*. *cough*

You’d think this would be the easy part. Just delete everything. “DELETE FROM table photos WHERE user_id = 'benv'", or rm -rf /photos/benv or one of many trivial options on the Google side of things. But noooo. Since this is that one thing that Google makes money off, they don’t want you to delete anything. So instead of giving a “remove my shit” button, even obscured somewhere, this is simply not possible. NOT POSSIBLE. You’d hope GDPR or one of the privacy “erase my data” laws would hit google with a 2-by-4, but nope. You see, there is a way: go to google photos, select your pictures one by one, hit trash button, hit confirm. WHAT.

In order to find a workaround, I figured I’d give ChatGPT a shot.

ChatGPT spitting out the usual hallucinations and other bullshit


It comes up with some useless and non-existing options as usual (seriously, option 1 is exactly what I told it I did not want, and 2 isn’t even getting rid of photos), but the API variant sounds like a workable one. But it needs a key, so you go to the cloud console and enable it – https://console.cloud.google.com/marketplace/product/google/photoslibrary.googleapis.com

Then we need to create some credentials for the script. Then you realize another ChatGPT problem, it tries to use service account credentials, this won’t work according to the API docs:
photos api

So you think let’s go for an OAuth client instead, but that’s not really an option either anymore:

So given the above, it sounds a lot like the API will only allow you to mess around with photos you uploaded through that same API, but not manage the rest of google photos. Just great.
Or in their words:
updated google photos api
SO WHERE IS THE FSCKING DELETE EVERYTHING BUTTON?!

I tried a Golang approach with ChatGPT as well, but given that there seems to be no workable API around (for long), I gave up on that as well. Too bad, wanted to make a go-photobomb app :p

The tedious workaround

So obviously while the trainwreck above hasn’t helped I still needed to get rid of the photos without clicking several tens of thousands times. I opted for the Tampermonkey approach:
Install tampermonkey, grab https://gist.github.com/sanghviharshit/59aa5615a9ec2dc548c23870e21ce069, adjust it until it works.
In my case I needed a small change: line 31 originally had if (d.ariaLabel == "Delete") {, which I needed to convert to if (d.ariaLabel == "Move to trash") { in order to match what the button actually said. Locale related probably. It might work for you, you might need to change languages. Another tweak I made was increasing the timeout values to delay the mainloop to every 60 seconds in order to have the delete complete before it tried reselecting/reloading.
After that, set your zoom-size to as small as possible, disable image loading through in the case of Chrome “Settings” -> “Privacy and Security” -> “Site settings” -> “Images” and add “photos.google.com” to the “Not allowed to show images”. It’ll speed things up.
Then you go to photos.google.com and wait while your tampermonkey script nukes the whole thing.

Tedious? Absolutely! This thing was stresstesting both Google photos as well as my network while digging through the deletes.
But we do have results:

Recommendation to Google

Please give people an option to simply delete everything. It saves you blogposts like this, as well as a ton of data traffic from your servers to me. Not to mention the horror stories my family are going to hear telling them to use my Immich server instead of your lock-in-a-tron.
What happened to “Don’t be evil” anyway?

:, ,

Leave a Reply

You must be logged in to post a comment.