Expose GPS coordinates from EXIF data in asset responses. The latitude and longitude fields are included in get_assets service responses and event data when available. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Immich Album Watcher
A Home Assistant custom integration that monitors Immich photo/video library albums for changes and exposes them as Home Assistant entities with event-firing capabilities.
Tip: For the best experience, use this integration with the Immich Album Watcher Blueprint to easily create automations for album change notifications.
Features
- Album Monitoring - Watch selected Immich albums for asset additions and removals
- Rich Sensor Data - Multiple sensors per album:
- Album ID (with album name and share URL attributes)
- Asset Count (total assets with detected people list)
- Photo Count (number of photos)
- Video Count (number of videos)
- Last Updated (last modification timestamp)
- Created (album creation date)
- Public URL (public share link)
- Protected URL (password-protected share link)
- Protected Password (password for protected link)
- Camera Entity - Album thumbnail displayed as a camera entity for dashboards
- Binary Sensor - "New Assets" indicator that turns on when assets are added
- Face Recognition - Detects and lists people recognized in album photos
- Event Firing - Fires Home Assistant events when albums change:
immich_album_watcher_album_changed- General album changesimmich_album_watcher_assets_added- When new assets are addedimmich_album_watcher_assets_removed- When assets are removed
- Enhanced Event Data - Events include detailed asset info:
- Asset type (photo/video)
- Filename
- Creation date
- Asset owner (who uploaded the asset)
- Asset description/caption
- Public URL (if album has a shared link)
- Detected people in the asset
- Services - Custom service calls:
immich_album_watcher.refresh- Force immediate data refreshimmich_album_watcher.get_assets- Get assets from an album with filtering and orderingimmich_album_watcher.send_telegram_notification- Send text, photo, video, or media group to Telegram
- Share Link Management - Button entities to create and delete share links:
- Create/delete public (unprotected) share links
- Create/delete password-protected share links
- Edit protected link passwords via Text entity
- Configurable Polling - Adjustable scan interval (10-3600 seconds)
- Localization - Available in multiple languages:
- English
- Russian (Русский)
Installation
HACS Installation (Recommended)
- Open HACS in Home Assistant
- Click on the three dots in the top right corner
- Select Custom repositories
- Add this repository URL:
https://github.com/DolgolyovAlexei/haos-hacs-immich-album-watcher - Select Integration as the category
- Click Add
- Search for "Immich Album Watcher" in HACS and install it
- Restart Home Assistant
- Add the integration via Settings → Devices & Services → Add Integration
Manual Installation
- Download or clone this repository
- Copy the
custom_components/immich_album_watcherfolder to your Home Assistantconfig/custom_componentsdirectory - Restart Home Assistant
- Add the integration via Settings → Devices & Services → Add Integration
Configuration
| Option | Description | Default |
|---|---|---|
| Server URL | Your Immich server URL (e.g., https://immich.example.com) |
Required |
| API Key | Your Immich API key | Required |
| Albums | Albums to monitor | Required |
| Scan Interval | How often to check for changes (seconds) | 60 |
| Telegram Bot Token | Bot token for sending media to Telegram (optional) | - |
Entities Created (per album)
| Entity Type | Name | Description |
|---|---|---|
| Sensor | Album ID | Album identifier with album_name and share_url attributes |
| Sensor | Asset Count | Total number of assets (includes people list in attributes) |
| Sensor | Photo Count | Number of photos in the album |
| Sensor | Video Count | Number of videos in the album |
| Sensor | Last Updated | When the album was last modified |
| Sensor | Created | When the album was created |
| Sensor | Public URL | Public share link URL (accessible links without password) |
| Sensor | Protected URL | Password-protected share link URL (if any exist) |
| Sensor | Protected Password | Password for the protected share link (read-only) |
| Binary Sensor | New Assets | On when new assets were recently added |
| Camera | Thumbnail | Album cover image |
| Text | Protected Password | Editable password for the protected share link |
| Button | Create Share Link | Creates an unprotected public share link |
| Button | Delete Share Link | Deletes the unprotected public share link |
| Button | Create Protected Link | Creates a password-protected share link |
| Button | Delete Protected Link | Deletes the password-protected share link |
Services
Refresh
Force an immediate refresh of all album data:
service: immich_album_watcher.refresh
Get Assets
Get assets from a specific album with optional filtering and ordering (returns response data). Only returns fully processed assets (videos with completed transcoding, photos with generated thumbnails).
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 10 # Maximum number of assets (1-100)
favorite_only: false # true = favorites only, false = all assets
filter_min_rating: 4 # Min rating (1-5)
order_by: "date" # Options: "date", "rating", "name", "random"
order: "descending" # Options: "ascending", "descending"
asset_type: "all" # Options: "all", "photo", "video"
min_date: "2024-01-01" # Optional: assets created on or after this date
max_date: "2024-12-31" # Optional: assets created on or before this date
Parameters:
limit(optional, default: 10): Maximum number of assets to return (1-100)favorite_only(optional, default: false): Filter to show only favorite assetsfilter_min_rating(optional, default: 1): Minimum rating for assets (1-5 stars). Applied independently offavorite_onlyorder_by(optional, default: "date"): Field to sort assets by"date": Sort by creation date"rating": Sort by rating (assets without rating are placed last)"name": Sort by filename"random": Random order (ignoresorder)
order(optional, default: "descending"): Sort direction"ascending": Ascending order"descending": Descending order
asset_type(optional, default: "all"): Filter by asset type"all": No type filtering, return both photos and videos"photo": Return only photos"video": Return only videos
min_date(optional): Filter assets created on or after this date. Use ISO 8601 format (e.g.,"2024-01-01"or"2024-01-01T10:30:00")max_date(optional): Filter assets created on or before this date. Use ISO 8601 format (e.g.,"2024-12-31"or"2024-12-31T23:59:59")
Examples:
Get 5 most recent favorite assets:
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 5
favorite_only: true
order_by: "date"
order: "descending"
Get 10 random assets rated 3 stars or higher:
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 10
filter_min_rating: 3
order_by: "random"
Get 20 most recent photos only:
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 20
asset_type: "photo"
order_by: "date"
order: "descending"
Get top 10 highest rated favorite videos:
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 10
favorite_only: true
asset_type: "video"
order_by: "rating"
order: "descending"
Get photos sorted alphabetically by name:
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 20
asset_type: "photo"
order_by: "name"
order: "ascending"
Get photos from a specific date range:
service: immich_album_watcher.get_assets
target:
entity_id: sensor.album_name_asset_limit
data:
limit: 50
asset_type: "photo"
min_date: "2024-06-01"
max_date: "2024-06-30"
order_by: "date"
order: "descending"
Send Telegram Notification
Send notifications to Telegram. Supports multiple formats:
- Text message - When
urlsis empty or not provided - Single photo - When
urlscontains one photo - Single video - When
urlscontains one video - Media group - When
urlscontains multiple items
The service downloads media from Immich and uploads it to Telegram, bypassing any CORS restrictions. Large lists of media are automatically split into multiple media groups based on the max_group_size parameter (default: 10 items per group).
Examples:
Text message:
service: immich_album_watcher.send_telegram_notification
target:
entity_id: sensor.album_name_asset_limit
data:
chat_id: "-1001234567890"
caption: "Check out the new album!"
disable_web_page_preview: true
Single photo:
service: immich_album_watcher.send_telegram_notification
target:
entity_id: sensor.album_name_asset_limit
data:
chat_id: "-1001234567890"
urls:
- url: "https://immich.example.com/api/assets/xxx/thumbnail?key=yyy"
type: photo
caption: "Beautiful sunset!"
Media group:
service: immich_album_watcher.send_telegram_notification
target:
entity_id: sensor.album_name_asset_limit
data:
chat_id: "-1001234567890"
urls:
- url: "https://immich.example.com/api/assets/xxx/thumbnail?key=yyy"
type: photo
- url: "https://immich.example.com/api/assets/zzz/video/playback?key=yyy"
type: video
caption: "New photos from the album!"
reply_to_message_id: 123
HTML formatting:
service: immich_album_watcher.send_telegram_notification
target:
entity_id: sensor.album_name_asset_limit
data:
chat_id: "-1001234567890"
caption: |
<b>Album Updated!</b>
New photos by <i>{{ trigger.event.data.added_assets[0].owner }}</i>
<a href="https://immich.example.com/album">View Album</a>
parse_mode: "HTML" # Default, can be omitted
Non-blocking mode (fire-and-forget):
service: immich_album_watcher.send_telegram_notification
target:
entity_id: sensor.album_name_asset_limit
data:
chat_id: "-1001234567890"
urls:
- url: "https://immich.example.com/api/assets/xxx/thumbnail?key=yyy"
type: photo
caption: "Quick notification"
wait_for_response: false # Automation continues immediately
| Field | Description | Required |
|---|---|---|
chat_id |
Telegram chat ID to send to | Yes |
urls |
List of media items with url and type (photo/video). Empty for text message. |
No |
bot_token |
Telegram bot token (uses configured token if not provided) | No |
caption |
For media: caption applied to first item. For text: the message text. Supports HTML formatting by default. | No |
reply_to_message_id |
Message ID to reply to | No |
disable_web_page_preview |
Disable link previews in text messages | No |
parse_mode |
How to parse caption/text. Options: HTML, Markdown, MarkdownV2, or empty string for plain text. Default: HTML |
No |
max_group_size |
Maximum media items per group (2-10). Large lists split into multiple groups. Default: 10 | No |
chunk_delay |
Delay in milliseconds between sending multiple groups (0-60000). Useful for rate limiting. Default: 0 | No |
wait_for_response |
Wait for Telegram to finish processing. Set to false for fire-and-forget (automation continues immediately). Default: true |
No |
max_asset_data_size |
Maximum asset size in bytes. Assets exceeding this limit will be skipped. Default: no limit | No |
send_large_photos_as_documents |
Handle photos exceeding Telegram limits (10MB or 10000px dimension sum). If true, send as documents. If false, skip oversized photos. Default: false |
No |
The service returns a response with success status and message_id (single message), message_ids (media group), or groups_sent (number of groups when split). When wait_for_response is false, the service returns immediately with {"success": true, "status": "queued"} while processing continues in the background.
Events
The integration fires multiple event types that you can use in your automations:
Available Events
| Event Type | Description | When Fired |
|---|---|---|
immich_album_watcher_album_changed |
General album change event | Fired for any album change |
immich_album_watcher_assets_added |
Assets were added to the album | When new photos/videos are added |
immich_album_watcher_assets_removed |
Assets were removed from the album | When photos/videos are removed |
immich_album_watcher_album_renamed |
Album name was changed | When the album is renamed |
immich_album_watcher_album_deleted |
Album was deleted | When the album is deleted from Immich |
immich_album_watcher_album_sharing_changed |
Album sharing status changed | When album is shared or unshared |
Example Usage
automation:
- alias: "New photos added to album"
trigger:
- platform: event
event_type: immich_album_watcher_assets_added
action:
- service: notify.mobile_app
data:
title: "New Photos"
message: "{{ trigger.event.data.added_limit }} new photos in {{ trigger.event.data.album_name }}"
- alias: "Album renamed"
trigger:
- platform: event
event_type: immich_album_watcher_album_renamed
action:
- service: notify.mobile_app
data:
title: "Album Renamed"
message: "Album '{{ trigger.event.data.old_name }}' renamed to '{{ trigger.event.data.new_name }}'"
- alias: "Album deleted"
trigger:
- platform: event
event_type: immich_album_watcher_album_deleted
action:
- service: notify.mobile_app
data:
title: "Album Deleted"
message: "Album '{{ trigger.event.data.album_name }}' was deleted"
Event Data
| Field | Description | Available In |
|---|---|---|
hub_name |
Hub name configured in integration | All events |
album_id |
Album ID | All events |
album_name |
Current album name | All events |
album_url |
Public URL to view the album (only present if album has a shared link) | All events except album_deleted |
change_type |
Type of change (assets_added, assets_removed, album_renamed, album_sharing_changed, changed) | All events except album_deleted |
shared |
Current sharing status of the album | All events except album_deleted |
added_limit |
Number of assets added | album_changed, assets_added |
removed_limit |
Number of assets removed | album_changed, assets_removed |
added_assets |
List of added assets with details (see below) | album_changed, assets_added |
removed_assets |
List of removed asset IDs | album_changed, assets_removed |
people |
List of all people detected in the album | All events except album_deleted |
old_name |
Previous album name | album_renamed |
new_name |
New album name | album_renamed |
old_shared |
Previous sharing status | album_sharing_changed |
new_shared |
New sharing status | album_sharing_changed |
Added Assets Fields
Each item in the added_assets list contains the following fields:
| Field | Description |
|---|---|
id |
Unique asset ID |
type |
Type of asset (IMAGE or VIDEO) |
filename |
Original filename of the asset |
created_at |
Date/time when the asset was originally created |
owner |
Display name of the user who owns the asset |
owner_id |
Unique ID of the user who owns the asset |
description |
Description/caption of the asset (from EXIF data) |
is_favorite |
Whether the asset is marked as favorite (true or false) |
rating |
User rating of the asset (1-5 stars, or null if not rated) |
latitude |
GPS latitude coordinate (or null if no geolocation) |
longitude |
GPS longitude coordinate (or null if no geolocation) |
url |
Public URL to view the asset (only present if album has a shared link) |
download_url |
Direct download URL for the original file (if shared link exists) |
playback_url |
Video playback URL (for VIDEO assets only, if shared link exists) |
photo_url |
Photo preview URL (for IMAGE assets only, if shared link exists) |
people |
List of people detected in this specific asset |
Note: Assets are only included in events and service responses when they are fully processed by Immich. For videos, this means transcoding must be complete (with
encodedVideoPath). For photos, thumbnail generation must be complete (withthumbhash). This ensures that all media URLs are valid and accessible. Unprocessed assets are silently ignored until their processing completes.
Example accessing asset owner in an automation:
automation:
- alias: "Notify when someone adds photos"
trigger:
- platform: event
event_type: immich_album_watcher_assets_added
action:
- service: notify.mobile_app
data:
title: "New Photos"
message: >
{{ trigger.event.data.added_assets[0].owner }} added
{{ trigger.event.data.added_limit }} photos to {{ trigger.event.data.album_name }}
Requirements
- Home Assistant 2024.1.0 or newer
- Immich server with API access
- Valid Immich API key with the following permissions:
Required API Permissions
| Permission | Required | Description |
|---|---|---|
album.read |
Yes | Read album data and asset lists |
asset.read |
Yes | Read asset details (type, filename, creation date) |
user.read |
Yes | Resolve asset owner names |
person.read |
Yes | Read face recognition / people data |
sharedLink.read |
Yes | Read shared links for public/protected URL sensors |
sharedLink.create |
Optional | Create share links via the Button entities |
sharedLink.edit |
Optional | Edit shared link passwords via the Text entity |
sharedLink.delete |
Optional | Delete share links via the Button entities |
Note: Without optional permissions, the corresponding entities will be unavailable or non-functional.
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
This project is licensed under the MIT License - see the LICENSE file for details.