Skip to main content

Upload Immich album originals to Google Photos via Playwright

Project description

immich-to-gphotos

Upload originals from an Immich album into an existing Google Photos album. Google has no public upload API; this tool uses Playwright with a saved browser session.

Disclaimer

This is an unofficial personal automation tool. It is not affiliated with Google or Immich. Google’s web UI changes can break uploads at any time. The saved session file (google-storage.json) is equivalent to staying logged in—protect it like a password (chmod 600, never commit it, never paste it in issues).

Requirements

  • Python 3.11+
  • exiftool on PATH (metadata embedding)
  • Google Chrome or Microsoft Edge — Playwright drives the system browser, not a bundled Chromium download
  • Immich API key with access to the source album

On Ubuntu:

sudo apt install google-chrome-stable

Install

pipx (recommended)

pipx install immich-to-gphotos
# or from GitHub:
# pipx install git+https://github.com/joyjit/immich-to-gphotos.git
# pipx install git+https://github.com/joyjit/immich-to-gphotos.git@v0.1.0

From a clone (development)

git clone https://github.com/joyjit/immich-to-gphotos.git
cd immich-to-gphotos
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

First-time setup (every user)

mkdir -p ~/.local/share/immich-to-gphotos
cp immich.conf-example ~/.local/share/immich-to-gphotos/immich.conf
chmod 600 ~/.local/share/immich-to-gphotos/immich.conf
# Edit immich.conf: set IMMICH_API_KEY and IMMICH_URL

Config precedence: CLI flags → environment → immich.conf → built-in defaults.

Usage

One-time Google sign-in

immich-to-gphotos auth

A system Chrome window opens (profile under ~/.local/share/immich-to-gphotos/chrome-profile). Sign in to the Google account that owns the target albums. The session is saved to ~/.local/share/immich-to-gphotos/google-storage.json (override with IMMICH_TO_GPHOTOS_AUTH_FILE).

If Google shows “This browser or app may not be secure”, use your normal Chrome via remote debugging:

google-chrome --remote-debugging-port=9222 https://photos.google.com
# Sign in in that window, then:
immich-to-gphotos auth --cdp-url http://127.0.0.1:9222

auth needs a graphical session (local desktop or switch-user). Plain SSH without a display cannot open Chrome; use --cdp-url instead (see above).

Upload

immich-to-gphotos upload \
  --immich-album "Trip 2024" \
  --google-album "Trip 2024"

Optional Immich URL override:

immich-to-gphotos upload \
  --immich-album "Trip 2024" \
  --google-album "Trip 2024" \
  --immich-url https://immich.example.com

Every upload run validates the Google session, even when Immich has nothing new:

  • New files — upload to Google, then save refreshed cookies to google-storage.json.
  • Nothing new — headless visit to Google Photos only; rewrite google-storage.json if still signed in.

If the session is missing or expired, upload exits 4 on every run (including idle cron runs). Previously, a run with no new files could exit 0 while the Google session was already dead.

Behavior

Topic Behavior
Immich album Case-insensitive name match; error if none or ambiguous
Asset limit Fails if album has more than 500 assets
Dedup By filename per Google album (state/<slug>.json)
RAW Converted to JPEG before upload
HEIC/HEIF Skipped with warning
Live Photo Uploads image + motion video when Immich links them
exiftool errors Warning only; file still uploaded
Google album Must already exist (yours or shared with you); not created by this tool
Google session Checked on every upload; cookies refreshed when signed in

Exit codes

Code Meaning
0 Success
1 Unexpected failure
2 Missing/invalid configuration
3 Immich album not found or ambiguous
4 Google auth / session expired
5 Immich API error
6 Google Photos / browser failure

Logs go to stderr with journal-style prefixes, e.g. <6>immich-to-gphotos: ….

Cron

Run upload on a schedule once auth has been done and immich.conf is in place. Re-run auth when uploads fail with exit code 4 (typically every few weeks, not on a fixed schedule).

Cron does not use your login PATH. Use the full path to the CLI, e.g. /home/you/.local/bin/immich-to-gphotos.

Each scheduled upload launches headless Chrome to validate or refresh the Google session. A frequent schedule (e.g. every 5 minutes) is fine on a small server but does add overhead when there is nothing to upload.

0 3 * * * /home/you/.local/bin/immich-to-gphotos upload --immich-album "Backup" --google-album "Backup" 2>&1 | logger -t immich-to-gphotos

Limitations

  • Filename dedup: two different Immich assets with the same basename in one Google album — only the first is uploaded.
  • Google web UI changes may break automation.
  • Shared albums: you must be allowed to add photos (collaboration enabled by the owner).
  • HEIC/HEIF assets are never uploaded.
  • Live Photo pairing on Google is best-effort.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

immich_to_gphotos-0.1.2.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

immich_to_gphotos-0.1.2-py3-none-any.whl (21.3 kB view details)

Uploaded Python 3

File details

Details for the file immich_to_gphotos-0.1.2.tar.gz.

File metadata

  • Download URL: immich_to_gphotos-0.1.2.tar.gz
  • Upload date:
  • Size: 19.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for immich_to_gphotos-0.1.2.tar.gz
Algorithm Hash digest
SHA256 206722ac73c39d8469eec6cc2a3311eb8119d13ccd0234eccafcfdf09a5ee278
MD5 4bbbdf434bdcc658660a0206e88640d8
BLAKE2b-256 25b820e16fe4510cb5a7fa48194f2445a6b2996d604006fad8dcf9b4d981dbad

See more details on using hashes here.

Provenance

The following attestation bundles were made for immich_to_gphotos-0.1.2.tar.gz:

Publisher: publish-pypi.yml on joyjit/immich-to-gphotos

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file immich_to_gphotos-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for immich_to_gphotos-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5adc1e20427adfe0c5f9a4ef108f7e36416ee3f7cefa341611098f0e7b06509e
MD5 d5f0b9e184a053b06a27cce19651e86e
BLAKE2b-256 d93f59ab304e9b8c0603e6da11ab5645f3aeab0d218e3b6e9758c646eb7bf37b

See more details on using hashes here.

Provenance

The following attestation bundles were made for immich_to_gphotos-0.1.2-py3-none-any.whl:

Publisher: publish-pypi.yml on joyjit/immich-to-gphotos

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page