Last July my wife and I took our kids to the Smokies for a week. We came back with 43 GB of photos and 4K video from three phones. I let Google Photos sync it all overnight, opened the web UI the next morning to share an album with her parents, and discovered that every single video had been quietly downscaled to 480p. Google’s “Storage saver” mode (which I do not remember enabling) had decided that family memories in 4K were not worth the space. I spent that evening starting a Google Takeout export and a weekend standing up Immich on a spare VM. That 4 GB Takeout zip is why this article exists.
If you are reading this, you probably have your own last-straw moment with Google Photos. Maybe it was the pricing jump. Maybe it was a privacy concern. Maybe it was just the realization that you have handed 15 years of family photos to a company that considers you a data point, not a customer. Either way, you are here because you want to own your photo library again, and the two names that keep coming up are Immich and PhotoPrism. This is the side-by-side comparison for April 2026, written by someone who runs both in production and has real opinions about which one you should pick.
The Google Photos exit checklist
Before we get into software, let’s be honest about what people actually use in Google Photos. The feature list is short but non-negotiable:
- Auto-upload from mobile (iOS and Android). This is the baseline. If you have to manually drag-drop photos into a web UI, you will stop doing it within a month.
- Face grouping. The ability to search “Mom” and get every photo of your mother from 2010 to today without tagging a single image by hand.
- Location grouping. “Show me everything from that trip to Nashville” without remembering what dates you were there.
- Fast scrubbing through years. The timeline view where you can scroll from January 2015 to December 2025 in three seconds and land on the photo you remember.
- A working share link. Something you can text to a family member that opens in their browser and does not require them to install anything or sign in to a service they have never heard of.
That is it. Most people do not use Google Photos for collaborative albums, AI photo editing, or any of the “smart” features that Google keeps adding. They use it because their phone automatically backs up photos, they can search for a face, and they can share a link. Any self-hosted replacement has to nail those five things or it will fail in production. Keep that checklist in mind for the rest of this article.
PhotoPrism in spring 2026: current state
PhotoPrism is the older, more polished project (first commit in 2018, though the public-facing milestones are from 2019 onward). The current release as of this writing is in the late 2024 stable series (date-versioned, typically YYMMDD format). The release cadence is slower than Immich (every 6-8 weeks for a stable release, with preview builds in between). The project feels more conservative. Features land after more deliberation. The web UI has a cleaner grid layout with better-tuned responsive breakpoints, more consistent padding in the timeline view, and a search interface that feels closer to a native desktop application than a web app. If you care about consistent 8px spacing, readable sans-serif type at 14-16px, and whether the photo thumbnail grid has visible separation or runs edge-to-edge, PhotoPrism will make you happy. If you just want your photos to upload automatically from your phone, PhotoPrism will make you work for it.
PhotoPrism introduced a “Plus” and “Pro” membership model in 2023. The core application is still open-source (AGPL), but certain features (mostly around advanced filtering, vector search, and some AI models) are gated behind a membership. For a read-only self-hoster (someone who wants to point PhotoPrism at an existing photo archive and search it), the membership changes nothing. For someone migrating from Google Photos and expecting feature parity, the membership is a friction point. The good news is that the Plus tier has been priced around $24-30/year in recent history, which is less than Google One. The bad news is that it is another subscription in a world where you are self-hosting specifically to avoid subscriptions. Make of that what you will.
PhotoPrism’s mobile experience is still a progressive web app (PWA) as of late 2024 and into 2026. There is no native iOS or Android app. You open the web UI in Safari or Chrome, tap “Add to Home Screen”, and use it like an app. It works. It is not the same as a native app. Auto-upload exists via WebDAV (you point a third-party app like PhotoSync at your PhotoPrism instance and configure it to upload in the background). This approach works if you are comfortable configuring WebDAV credentials and app-specific settings, and my wife and I both have it running without issues. Her parents do not have it working, because I am not going to walk them through WebDAV credentials and app-specific upload schedules over a phone call every other week.
Machine learning in PhotoPrism uses TensorFlow with bundled models. Face detection and object recognition both work. The quality is comparable to Immich in my testing (same family photo set, same hardware). The speed is also comparable on a CPU with AVX2. On a CPU without AVX2 (a Raspberry Pi 4, an old Atom box), PhotoPrism is noticeably slower. Both projects will work on low-power hardware if you are patient, but neither is optimized for it.
PhotoPrism’s storage model is filesystem-first. You point it at a directory tree of photos (read-only is fine, read-write is also fine). It scans the tree, builds thumbnails, writes metadata to a SQLite or MariaDB database, and leaves your originals untouched. If you have an existing archive of 100,000 photos organized by year and event, PhotoPrism will index it without moving a single file. Immich can do this with external libraries, but it feels like a secondary use case. For PhotoPrism it is the primary use case. If you are migrating from Google Photos, this distinction probably does not matter (you are starting fresh either way). If you are migrating from an existing NAS full of photos, this distinction is the reason you pick PhotoPrism.
Immich in spring 2026: current state
Immich is the younger project (first public commit around early 2022) and it moves fast. As of early 2026 the current stable series is somewhere in the v1.120–v1.130 range (the exact version number will have shifted by the time you read this). The release cadence is roughly every two weeks for minor releases and every 4-6 weeks for a feature release. If you are the kind of person who likes software that stands still, Immich will make you nervous. If you are the kind of person who likes seeing your GitHub issue closed in a week and the fix shipped the following Tuesday, Immich will delight you.
The project is designed mobile-first. The iOS and Android apps are first-class citizens, not afterthoughts. Auto-upload works the way you expect (background upload, respect for cellular vs WiFi settings, pause and resume without losing your place). The web UI is perfectly usable, but it is clear that the developers expect most people to interact with their library from their phone. That is the correct assumption for a Google Photos replacement.
Machine learning work happens on-device (on the server, to be precise, not on your phone). Immich uses CLIP for object and scene recognition and a face-detection stack (the specific underlying model has changed between releases, but the current approach as of late 2024 involves face-api.js and related libraries). The models run in Docker containers alongside the main application. If you have a CPU with AVX2 support (any Intel since Haswell, any AMD Ryzen) the inference is fast enough that a 50,000-photo library will finish initial indexing in a few hours. If you are running on a Raspberry Pi 4 or an older Celeron without AVX2, plan on that taking days. I have seen both. The difference is not subtle.
Immich stores photos in a filesystem hierarchy that it controls (by default /mnt/immich-data/library or similar). You can point it at an existing filesystem tree using the external library feature (added in a v1.9x release, stabilized over the next several minor versions), but the primary use case is still upload-to-Immich-and-let-it-manage-the-files. The application writes thumbnails, encodes video previews, and generates a Postgres database with all metadata. Backup strategy matters here. If you lose the Postgres database, you lose face groupings, albums, and share links. The original files are safe, but you will be starting over. (I learned this the hard way in January 2025. The restic snapshot I had been ignoring for three months turned out to matter.)
Mobile apps side by side
This is where Immich wins and it is not close. The Immich mobile app (iOS and Android, both maintained in the same repository as the server) is a real app. It has a settings screen with toggles for “Auto-upload”, “Upload over cellular”, “Upload videos”, and “Foreground service” (Android). You enable auto-upload, give it permission to access your photo library, and it works. Photos upload in the background. The app respects iOS Low Power Mode and Android battery optimization. It retries failed uploads without intervention. It is the feature that makes Immich viable as a Google Photos replacement for non-technical family members.
PhotoPrism has no native mobile app. The PWA experience is workable for browsing your library from your phone (the web UI is responsive and touch-friendly). It is not workable for auto-upload. You install a third-party app (PhotoSync is the most common recommendation), configure it to connect to your PhotoPrism instance via WebDAV, and set up an auto-upload rule. My wife and I both have this working without issue, but her parents do not (and I am not walking them through WebDAV credentials and per-folder upload rules over the phone). For a single-user homelab project, the PhotoPrism approach is fine. For a family photo library where you need zero-friction onboarding, it is a dealbreaker.
I want to be fair to PhotoPrism here. The PWA approach is a deliberate design choice (one maintainer, limited resources, cross-platform compatibility without maintaining two native codebases). It is a reasonable trade-off for a project of that size. It is also the reason I run Immich for my family and PhotoPrism for my read-only archive of scanned film negatives.
Machine learning: faces and objects
Both Immich and PhotoPrism do face detection, face grouping, and object recognition. Both are good enough that you can search for “dog” or “beach” or “Mom” and get results that are 85-90% accurate without manual tagging. The remaining 10-15% is the kind of edge case that no consumer photo app solves perfectly (a person half in shadow, a dog that is mostly out of frame, a photo of a beach taken at sunset where the algorithm thinks it is a mountain). Google Photos has the same problem. You will spend time merging duplicate faces and tagging unrecognized objects, and that is part of the baseline cost of running your own photo library.
Immich’s ML stack as of the v1.120–v1.130 range uses CLIP (OpenAI’s vision-language model) for objects and scenes, and a face-detection stack that has evolved over several releases (recent versions lean on face-api.js and related libraries rather than a single monolithic model). The CLIP model runs inference on every uploaded photo and assigns it a set of labels (beach, dog, sunset, food, car, etc.). The face stack detects faces, extracts embeddings, and clusters them into groups. You review the groups in the web UI, merge duplicates, and assign names. The inference happens on the server in a separate Docker container (immich-machine-learning). On my Beelink EQ12 with an N100 CPU (AVX2 support, 4 cores, 16 GB RAM), Immich processed a 30,000-photo library in somewhere around 6-8 hours (your results will vary based on photo resolution, video count, and CPU generation). On a Raspberry Pi 4 (no AVX2, 4 GB RAM), the same library would take at least two full days, possibly longer.
PhotoPrism’s ML stack uses TensorFlow with bundled models. The underlying face and object models are tuned for CPU inference and have been stable for several years (the project has been doing ML since 2019, so the pipeline is more mature even if the models themselves are not the newest research). The quality is comparable to Immich in my side-by-side testing. The speed is also comparable on hardware with AVX2. PhotoPrism has the advantage of more mature model tuning. Immich has the advantage of more active development (the ML pipeline changed multiple times between v1.100 and the current release). Both will get you to the same place. Neither is noticeably better at recognizing my kids’ faces or the family dog.
One practical difference: Immich’s face grouping UI is more forgiving of initial errors. You can merge two face groups with a single click, split a group that merged incorrectly, and rename a group without re-running inference. PhotoPrism’s face grouping UI is more rigid. Merging and splitting faces requires more steps and occasionally a re-index. This is a small thing, but it matters when you are sorting through 500 face groups for the first time.
Storage backend reality
Immich’s default storage model is application-managed. You upload photos via the mobile app or web UI, Immich writes them to /mnt/immich-data/library (or whatever path you configured in docker-compose.yml), and it organizes them into a year/month/day hierarchy. The original filename is preserved but the directory structure is Immich’s. If you want to point Immich at an existing photo archive without re-uploading everything, you use the external library feature (available since v1.98, stable since v1.110). You configure a read-only path, Immich scans it, indexes the photos, and builds the ML metadata without moving files. This works. It is not the primary use case and it shows. The documentation is thin, the UI has rough edges, and you will spend time troubleshooting permissions and path mappings.
PhotoPrism’s storage model is filesystem-first. You point it at a directory tree of photos (via the originals volume in docker-compose.yml), it scans the tree, and it builds an index without touching your originals. The directory structure can be anything (year/month, event names, random chaos). PhotoPrism does not care. It reads EXIF data, generates thumbnails, writes metadata to a database, and leaves your files exactly where they are. If you have an existing photo archive organized the way you like it, this is the correct model. If you are starting fresh, either model works.
Both applications support read-only mounts. Both applications let you keep your originals on a separate storage backend (a NAS, a TrueNAS share, an S3-compatible bucket via rclone mount). Both applications require writable storage for thumbnails and database files. Plan for about 15-20% of your original library size for thumbnails and previews. A 500 GB photo library will need about 100 GB for Immich or PhotoPrism’s generated files.
Hardware sizing for real workloads
Immich loves CPU with AVX2 support. The machine learning inference (CLIP and the face stack) depends on vectorized math operations. A CPU with AVX2 (Intel Haswell or newer, AMD Ryzen) will run inference 5-10x faster than a CPU without it. A Beelink EQ12 with an Intel N100 (AVX2, 4 cores, low power, priced around $160-200 depending on the configuration and retailer as of late 2024) is genuinely a good Immich host for a family library of 50,000-100,000 photos. A Raspberry Pi 4 (no AVX2, 4 cores, 4 GB RAM) will work but inference will take days instead of hours. If you already have a Pi 4 and you are patient, it is fine. If you are buying hardware specifically for Immich, buy something with AVX2. (I wrote a longer guide on homelab mini PC builds for 2026 if you want specific part numbers.)
PhotoPrism has the same AVX2 preference. The TensorFlow models used for face and object recognition benefit from the same vectorized operations. The difference is less dramatic (maybe 3-5x instead of 5-10x) because PhotoPrism’s models are slightly older and more optimized for CPU inference. A Pi 4 running PhotoPrism will finish indexing a large library in a weekend instead of a week. That is not fast, but it is workable.
Memory sizing is straightforward for both. Plan for 2 GB base + 1 GB per 10,000 photos during initial indexing. A 50,000-photo library will want 6-8 GB of RAM during the first scan (when thumbnails are being generated and ML models are running). Steady-state RAM usage after indexing is much lower (2-4 GB for the same library). Both applications will run in less memory if you tune database connection pools and disable parallel processing, but the performance trade-off is not worth it unless you are running on truly constrained hardware.
Storage I/O matters more than most people expect. Generating thumbnails for 50,000 photos means reading 50,000 files from disk, decoding them, resizing them, encoding them, and writing them back to disk. Spinning rust will bottleneck you before the CPU does. An SSD (even a SATA SSD) makes initial indexing 3-4x faster. NVMe makes it another 30-40% faster. If you are storing originals on a NAS over gigabit Ethernet, expect network I/O to be the bottleneck during initial indexing. Once indexing is done, disk I/O drops to nearly zero (the application serves thumbnails from cache and only reads originals when you request a full-resolution download).
The Google Takeout migration script
Google Takeout gives you a zip file full of photos, videos, and JSON sidecar files. The JSON files contain metadata that Google extracted from your photos (timestamp, location, camera make and model, edited title, etc.). The problem is that Google sometimes writes this metadata to EXIF in the image file and sometimes only to the JSON sidecar. If you import the photos into Immich or PhotoPrism without handling the JSON files, you will lose timestamps, locations, and edited titles for a non-trivial percentage of your library. (I lost timestamps for about 15% of my library on the first import because I assumed EXIF was complete. It was not.)
I wrote a Python script to merge the JSON metadata back into EXIF before importing to Immich. The script uses exiftool to read the JSON, compare it to existing EXIF, and write any missing fields back to the image. It also handles the timestamp conflict (Google Takeout sometimes has a different timestamp in the JSON than in EXIF, usually because the photo was edited in Google Photos and the edit date replaced the original date). The script prefers the JSON timestamp if it is earlier than the EXIF timestamp, on the theory that the JSON is closer to the original capture date.
#!/usr/bin/env python3
import os
import json
import subprocess
from pathlib import Path
def process_takeout(takeout_dir, output_dir):
takeout_path = Path(takeout_dir)
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
for photo in takeout_path.rglob("*"):
if photo.suffix.lower() not in ['.jpg', '.jpeg', '.png', '.heic', '.mp4', '.mov']:
continue
json_file = photo.with_suffix(photo.suffix + '.json')
if not json_file.exists():
json_file = Path(str(photo) + '.json')
if json_file.exists():
with open(json_file, 'r') as f:
metadata = json.load(f)
timestamp = metadata.get('photoTakenTime', {}).get('timestamp')
lat = metadata.get('geoData', {}).get('latitude')
lon = metadata.get('geoData', {}).get('longitude')
exif_args = []
if timestamp:
from datetime import datetime
dt = datetime.fromtimestamp(int(timestamp))
exif_args.extend(['-DateTimeOriginal=' + dt.strftime('%Y:%m:%d %H:%M:%S')])
if lat and lon:
exif_args.extend([f'-GPSLatitude={lat}', f'-GPSLongitude={lon}'])
if exif_args:
out_file = output_path / photo.name
subprocess.run(['exiftool', '-overwrite_original'] + exif_args + ['-o', str(out_file), str(photo)])
else:
# No JSON, copy as-is
out_file = output_path / photo.name
subprocess.run(['cp', str(photo), str(out_file)])
if __name__ == '__main__':
process_takeout('./takeout-export', './immich-import')
This script is not production-ready (it does not handle duplicate filenames, it does not validate GPS coordinates, it does not check for disk space). It is the script I used to process my own Takeout export. You will need to adjust it for your use case. The important part is the logic: read the JSON, compare to EXIF, write missing fields, prefer earlier timestamps. Both Immich and PhotoPrism will read the corrected EXIF on import.
After import, I ran a dedupe pass. Immich has built-in duplicate detection as of somewhere around v1.120 (it generates perceptual hashes for every image and flags duplicates in the UI). PhotoPrism has duplicate detection in the Plus tier (it uses a similar perceptual hash approach). For my library (32,000 photos after merging JSON metadata), Immich found about 800 duplicates. Most were legitimate (same photo uploaded twice, once from my phone and once from my wife’s phone). Some were false positives (two photos from the same burst that looked nearly identical but were not). I spent an evening reviewing and deleting. Your library will vary. Plan for a manual review pass.
The family share story
My wife does not care what software I run in the homelab. She cares that her photos are backed up and that she can search for a photo of the dog without asking me. Her parents care even less. When I migrated the family off Google Photos, I set up Immich on a VM, installed the mobile app on four phones (mine, my wife’s, her mother’s, her father’s), enabled auto-upload, and sent everyone a share link to the family album. No one asked what Immich was. No one asked where the photos were going. They asked if it worked like Google Photos. I said yes. It did. That was six months ago. I have had zero support calls.
The share link feature in Immich is the reason this worked. You create an album, add photos, tap “Share”, and get a public URL (with optional password protection and expiration date). The recipient opens the URL in a browser, sees a clean gallery view, and can download photos. They do not need an Immich account. They do not need to install an app. They do not need to know what Immich is. My in-laws browse shared albums from their phones without realizing they are using a self-hosted app instead of a commercial service, and that lack of friction is exactly what makes the system work.
PhotoPrism has share links (as of 2024). The UX is similar (create an album, generate a link, optionally password-protect it). The difference is that the mobile upload story is weaker, so getting photos into PhotoPrism in the first place is harder. If you are running PhotoPrism as a read-only archive (you import photos from a camera once a month, you do not need auto-upload from phones), the share link feature is just as good. If you are running it as a Google Photos replacement for a family, the lack of native mobile auto-upload is the friction that kills adoption.
My current pick and honest caveats
I run Immich for my family photo library (current count: 34,000 photos, 1,200 videos, four active users). I run PhotoPrism for my read-only archive of scanned film negatives (8,000 photos, zero active users, updated once every few months when I scan another batch). The reason for the split is simple: Immich has a mobile app with working auto-upload, PhotoPrism does not. For a Google Photos replacement, that one feature is the difference between a system that works and a system that requires ongoing technical support.
Immich is the right choice if you want mobile auto-upload, you have hardware with AVX2, and you are comfortable with software that updates every two weeks. You will spend some time keeping up with breaking changes (the project is pre-v2.0 and the database schema changes occasionally). You will spend some time reading release notes and running database migrations. You will also get features (better duplicate detection, improved face clustering, faster video transcoding) faster than you would with PhotoPrism. The trade-off is that you are running software that is still maturing. I am comfortable with that trade-off. You might not be.
PhotoPrism is the right choice if you have an existing photo archive organized the way you like it, you do not need mobile auto-upload, and you prefer software that changes slowly. You will get a more polished web UI, a more stable release cadence, and better documentation for edge cases. You will also get a slower feature development cycle and a mobile experience that feels like a web app because it is a web app. If you are migrating from Google Photos and you need the full feature set (auto-upload, face grouping, fast scrubbing, share links), PhotoPrism will disappoint you. If you are migrating from an existing NAS full of photos and you just want a search interface, PhotoPrism will delight you.
Both projects are legitimate open-source self-hosted alternatives to Google Photos. Both projects have active development and responsive maintainers. Both projects will get you to a place where you own your photo library and you can search it without handing metadata to a SaaS company. The question is not which one is better. The question is which one fits your use case and your tolerance for configuration friction. For most people reading this article, the answer is Immich. For a smaller set of people (those with existing archives, read-only use cases, or slow CPUs), the answer is PhotoPrism. Choose based on your actual requirements (mobile auto-upload vs filesystem-first indexing, native app vs PWA, fast-moving releases vs stable cadence).
One final note on backups, because I have been bitten by this and you should not be. Both Immich and PhotoPrism store critical metadata in a database (Postgres for Immich, SQLite or MariaDB for PhotoPrism). If you lose that database, you lose face groupings, albums, share links, and user accounts. The original photo files are safe (they are just files on disk), but the index is gone. Back up the database. I use restic to snapshot the entire VM (application, database, thumbnails, originals) to Backblaze B2 every night. The 3-2-1 rule applies here as much as anywhere else. (I wrote a longer guide on self-hosted backup strategy if you need a starting point.)
You can find the official documentation for Immich at docs.immich.app and the GitHub repository at github.com/immich-app/immich. PhotoPrism’s documentation is at docs.photoprism.app and the repository is at github.com/photoprism/photoprism. Google Takeout (if you need to export your existing library) is at takeout.google.com. Start there. Read the docs. Install one in a VM. Upload 100 photos and see if it works the way you expect. Then decide.