Jellyfin for Home Assistant
- 🎬 Display movies and TV shows from your library
- 📺 Cast media directly to Chromecast (Gen 1 supported)
- ⏯️ Full playback control: Play, Pause, Stop, Seek, Next/Previous Track
- 🎮 Per-user media players with transport and volume controls
- ⏭️ "Next Up" support to resume TV shows
- 🎨 Three layouts: Carousel, Grid, List
- 🌙 Automatic dark/light theme adaptation
- 🔗 Click to open in Jellyfin (new tab)
- ⭐ IMDB ratings for movies, TMDB for TV shows
- 🆕 "New" badge for recently added items
- 🔍 Built-in Search Bar with Title and Genre filtering
- 🔐 Secure login via Username/Password or API Key
- 🤖 Advanced automation triggers via custom sensors & services
- 📂 Full integration with Home Assistant Media Browser
- 💾 Local storage caching
- ⚡ Instant loading via WebSocket
- 🌍 7 languages: English, German, French, Spanish, Italian, Dutch, Slovenian
- 🎛️ Graphical card editor (no YAML required)
JellyHA requires two installation steps: installing the integration and adding the dashboard card resource.
Before installing JellyHA, ensure you have HACS (Home Assistant Community Store) installed.
Please follow the official HACS installation guide to install HACS on your Home Assistant instance.
Option A: Using the Quick Link
Option B: Manual Search
- Open HACS in Home Assistant
- In the search bar, type JellyHA
Then:
- Click the JellyHA integration and click Download
- Restart Home Assistant
- Copy
custom_components/jellyhato yourconfig/custom_components/directory - Restart Home Assistant
⚠️ Important: This step is required even if you installed via HACS. The dashboard card will not work without it.
- Go to Settings → Dashboards
- Click ⋮ (three-dot menu) → Resources
- Click + Add Resource
- Enter the URL:
- URL:
/jellyha/jellyha-cards.js
- URL:
- Select Resource type: JavaScript Module
- Click Create
Note: If you don't see the Resources menu, enable Advanced Mode in your user profile settings.
⚠️ Note: Only a single instance of this integration is supported. Please configure it once for your main user.
Then continue to step 3. and 4. below.
- Go to Settings → Devices & Services → Add Integration
- Search for "JellyHA"
- Enter your Jellyfin server URL and select authentication method (Username/Password or API Key)
- Enter your Jellyfin API key or credentials
- Select the user and libraries to monitor
- Click Submit
- Add Device to the Area (optional)
Note: You can update these credentials later by re-configuring the integration.
To get your Jellyfin API key:
- Open Jellyfin Dashboard
- Go to Administration → API Keys
- Click + to create a new key
- Copy the generated key
The JellyHA Library provides a beautiful way to browse and play your media collection directly in Home Assistant.
ℹ️ Info: Use Add to dashboard and search for JellyHA Card. YAML below is just informational.
type: custom:jellyha-library-card
entity: sensor.jellyha_library
title: Jellyfin Library
layout: carousel
media_type: both
items_per_page: 3
max_pages: 5| Option | Type | Default | Description |
|---|---|---|---|
entity |
string | Required | The sensor entity ID (e.g. sensor.jellyha_library) |
title |
string | Jellyfin Library |
Card title |
layout |
string | carousel |
Layout mode: carousel, grid, or list |
media_type |
string | both |
Filter: movies, series, next_up, or movies & series |
columns |
number | 4 |
Number of columns for grid & list layout. Changes to number of rows with Grid layout and Auto-Swipe On. |
items_per_page |
number | 3 |
Items visible per page. Note for Height Cut Off: Use YAML editor to set > 8 rows. |
max_pages |
number | 5 |
Maximum number of pages to display (0 = infinite) |
auto_swipe_interval |
number | 0 |
Auto-scroll interval in seconds (0 = disabled) |
new_badge_days |
number | 3 |
Items added within X days show "New" badge |
click_action |
string | jellyfin |
Action on click: jellyfin, more-info, cast, trailer, or none |
hold_action |
string | cast |
Action on hold: jellyfin, cast, more-info, trailer, or none |
double_tap_action |
string | none |
Action on double tap: jellyfin, cast, more-info, trailer, or none |
default_cast_device |
string | '' |
Default media_player entity for casting |
show_now_playing |
boolean | true |
Show currently playing item banner if active |
show_title |
boolean | true |
Show media title |
show_year |
boolean | true |
Show release year |
show_ratings |
boolean | true |
Show combined rating |
show_runtime |
boolean | true |
Show runtime duration |
show_date_added |
boolean | false |
Show the date item was added in List view |
show_genres |
boolean | true |
Show genres list |
show_description_on_hover |
boolean | true |
Show overview when hovering/tapping |
show_media_type_badge |
boolean | true |
Show Movie/Series badge |
show_watched_status |
boolean | true |
Show watched checkmarks (Movies) and unplayed counts (Series) |
show_search |
boolean | false |
Show Search Bar for filtering by Title and Genre |
metadata_position |
string | below |
Position of text: below or above image |
sort_option |
string | date_added_desc |
Sort order options |
enable_pagination |
boolean | true |
Enable pagination dots |
show_pagination_dots |
boolean | true |
Enable pagination dots visibility |
status_filter |
string | all |
Filter Watch Status: all, unwatched, watched |
filter_favorites |
boolean | false |
Filter Favorites (Show only favorite items) |
filter_newly_added |
boolean | false |
Filter New Items (Show only new items) |
use_series_image |
boolean | false |
(Next Up only) Show series cover instead of episode thumbnail |
⚠️ Performance Note: Using Auto Swipe with a large number of items may impact performance on some devices. We recommend limiting the number of items for the best experience.
The JellyHA Now Playing Card shows a rich media control interface for the currently playing item.
ℹ️ Info: Use Add to dashboard and search for JellyHA Card. YAML below is just informational.
type: custom:jellyha-now-playing-card
entity: sensor.jellyha_now_playing_admin # Replace with your user sensor
title: Now Playing
show_background: true| Option | Type | Default | Description |
|---|---|---|---|
entity |
string | Required | The user-specific Now Playing sensor (e.g. sensor.jellyha_now_playing_marko) |
title |
string | Jellyfin |
Optional title header |
show_background |
boolean | true |
Show blurred backdrop fanart as background |
show_title |
boolean | true |
Show media title text |
show_client |
boolean | true |
Show client device name (e.g. "Chrome") |
show_media_type_badge |
boolean | true |
Show badge (MOVIE, SERIES, EPISODE) |
show_genres |
boolean | true |
Show genres list |
show_ratings |
boolean | true |
Show community rating |
show_runtime |
boolean | true |
Show runtime duration |
show_year |
boolean | true |
Show release year |
use_series_image |
boolean | false |
Show series cover instead of episode thumbnail |
JellyHA provides several sensors to monitor your Jellyfin server and library. All sensors are prefixed with sensor.jellyha_ (unless a custom device name was used during setup).
| Entity ID | Description | State | Attributes |
|---|---|---|---|
sensor.jellyha_library |
Primary library sensor | Count of items | server_name, movies, series, episodes |
sensor.jellyha_favorites |
Favorite items | Count | - |
sensor.jellyha_unwatched |
Total unwatched content | Count | movies, series |
sensor.jellyha_unwatched_movies |
Unwatched movies | Count | - |
sensor.jellyha_unwatched_series |
Unwatched TV series | Count | - |
sensor.jellyha_unwatched_episodes |
Unwatched individual episodes | Count | - |
sensor.jellyha_watched |
Total watched content | Count | movies, series |
sensor.jellyha_watched_movies |
Fully watched movies | Count | - |
sensor.jellyha_watched_series |
Fully watched TV series | Count | - |
sensor.jellyha_watched_episodes |
Fully watched series count | Count | - |
| Entity ID | Description | State | Attributes |
|---|---|---|---|
sensor.jellyha_websocket |
WebSocket connection status | connected/disconnected |
- |
sensor.jellyha_version |
Jellyfin server version | e.g. 10.11.6 |
- |
sensor.jellyha_active_sessions |
Number of active playbacks | Count | sessions (list of active session info) |
sensor.jellyha_last_refresh |
Last time data was fetched | Timestamp | - |
sensor.jellyha_last_data_change |
Last time library data changed | Timestamp | - |
sensor.jellyha_refresh_duration |
Duration of the last library refresh | 5.2s, 1m 30s |
duration_seconds (float) |
| Entity ID Prefix | Description | State | Key Attributes |
|---|---|---|---|
sensor.jellyha_now_playing_[user] |
Real-time monitoring for specific user | playing, paused, idle |
title, series_title, season, episode, progress_percent, image_url, media_type, client, device_name |
JellyHA provides two types of media_player entities:
| Entity ID Pattern | Description | Supported Features |
|---|---|---|
media_player.jellyha_[username] |
Tracks and controls each user's active playback session | Transport: Play, Pause, Stop, Seek, Next Track, Previous Track Volume: Set Volume, Mute/Unmute Metadata: Title, Series/Season/Episode, Image, Duration, Position |
State Mapping:
idle— No active playback sessionplaying— Media is currently playingpaused— Media is paused
Key Attributes:
media_title— Current media titlemedia_series_title— TV series name (episodes only)media_season— Season number (episodes only)media_episode— Episode number (episodes only)media_content_type—tvshow,movie,music, orvideomedia_image_url— Poster image URLmedia_duration— Total duration in secondsmedia_position— Current position in secondssession_id— Active Jellyfin session IDdevice_name— Client device nameclient— Client application name
Example Usage:
# Pause playback
service: media_player.media_pause
target:
entity_id: media_player.jellyha_admin
# Seek to 5 minutes
service: media_player.media_seek
target:
entity_id: media_player.jellyha_admin
data:
seek_position: 300
# Set volume to 50%
service: media_player.volume_set
target:
entity_id: media_player.jellyha_admin
data:
volume_level: 0.5| Entity ID | Description | Supported Features |
|---|---|---|
media_player.jellyha_library_browser |
Browse and search your Jellyfin library | Browse Media, Play Media, Search Media |
This entity integrates with Home Assistant's Media Browser and allows you to explore your Jellyfin libraries directly from the Media panel.
JellyHA provides several services to control and manage your library.
| Service | Description | Parameters |
|---|---|---|
jellyha.play_on_chromecast |
Play an item on Chromecast with optimized transcoding. | entity_id (Req), item_id (Req) |
jellyha.refresh_library |
Force refresh library data from Jellyfin. | - |
jellyha.delete_item |
Delete an item from library/disk. |
item_id (Req) |
jellyha.mark_watched |
Mark an item as watched or unwatched. | item_id (Req), is_played (Req) |
jellyha.update_favorite |
Add or remove an item from favorites. | item_id (Req), is_favorite (Req) |
jellyha.session_control |
Control playback (Pause, Unpause, TogglePause, Stop). |
session_id (Req), command (Req) |
jellyha.session_seek |
Seek to position in ticks. Use 0 to rewind. |
session_id (Req), position_ticks (Req) |
jellyha.search |
Search for media and return Item IDs. | query (Opt), media_type (Opt), is_played (Opt), min_rating (Opt), season (Opt), episode (Opt) |
jellyha.get_recommendations |
Get similar items based on item ID. | item_id (Req), limit (Opt) |
jellyha.get_item |
Get full details for an item. | item_id (Req) |
JellyHA uses a WebSocket-first, API-fallback strategy for real-time session monitoring. This powers the active_sessions sensor and per-user now_playing sensors.
| Connection State | Update Method | Speed |
|---|---|---|
| WebSocket Connected | Push updates from Jellyfin | Instant (~100ms) |
| WebSocket Disconnected | API polling every 5 seconds | Near real-time |
How it works:
- On startup, JellyHA connects to the Jellyfin WebSocket and subscribes to session events
- While connected, session updates are pushed instantly — no polling required
- If WebSocket disconnects (network issue, server restart), it automatically falls back to API polling
- When WebSocket reconnects, polling stops and push updates resume
The sensor.jellyha_websocket sensor shows the current connection status (connected/disconnected).
JellyHA integrates directly with the Home Assistant Media Browser. You can explore your Jellyfin libraries, play media on supported players, and even stream directly to your browser, all without leaving Home Assistant.
- Go to Media in the sidebar.
- Select JellyHA.
- Browse your Movies, Series, and Music collections.
This automation finds a highly-rated movie you haven't watched yet and casts it.
The jellyha.search service enables powerful automations by allowing you to find content dynamically.
alias: Play Random Top 2025 Movie
description: Plays a random unwatched movie from 2025 with a rating above 7.
mode: restart
max_exceeded: silent
trigger:
- platform: event
event_type: call_service
event_data:
domain: automation
service: trigger
service_data:
entity_id: automation.play_random_top_2025_movie
action:
# 1. Search for candidates
- service: jellyha.search
data:
media_type: Movie
is_played: false
year: 2025
min_rating: 7
limit: 50
response_variable: search_result
# 2. Check if we found anything
- if:
- condition: template
value_template: "{{ search_result['items'] | count > 0 }}"
then:
# 3. Pick random item and play
- service: jellyha.play_on_chromecast
data:
entity_id: media_player.office_tv
item_id: "{{ (search_result['items'] | random)['id'] }}"
else:
# 4. Notify if nothing found
- service: notify.persistent_notification
data:
message: "No unwatched 2025 movies with rating > 7 found."This automation pauses playback automatically when the doorbell rings.
alias: Pause Movie on Doorbell
description: "Pauses Jellyfin when the doorbell rings"
trigger:
- trigger: state
entity_id: binary_sensor.doorbell # Replace with your actual doorbell entity
to: "on"
condition:
# Only run if something is actually playing
- condition: state
entity_id: sensor.jellyha_now_playing_admin # Replace with your user sensor
state: "playing"
actions:
- action: jellyha.session_control
data:
# Dynamically get the session_id from the sensor attributes
session_id: "{{ state_attr('sensor.jellyha_now_playing_admin', 'session_id') }}"
command: Pause
mode: singleThis automation turns off the lights when you start watching something.
alias: Movie Time - Lights Off
description: "Turn off living room lights when movie starts playing"
trigger:
- trigger: state
entity_id: sensor.jellyha_now_playing_admin # Replace with your user sensor
to: "playing"
conditions: []
actions:
- action: light.turn_off
target:
entity_id: light.living_room
mode: singleSends a notification to your phone when a new movie is added.
alias: Notify New Movie
description: "Send notification when a new movie is added"
trigger:
- trigger: state
entity_id: sensor.jellyha_unwatched_movies
conditions:
# Check if count increased (new item added)
- condition: template
value_template: "{{ trigger.to_state.state | int > trigger.from_state.state | int }}"
actions:
# 1. Fetch the single newest movie
- action: jellyha.search
data:
media_type: Movie
limit: 1
response_variable: new_items
# 2. Send notification
- action: notify.mobile_app_phone # Replace with your phone's notify service (check Developer Tools)
data:
title: New Movie Added
message: "{{ new_items['items'][0]['name'] }} ({{ new_items['items'][0]['year'] }}) - Rating: {{ new_items['items'][0]['rating'] }}/10 is now available!"
data:
image: "{{ new_items['items'][0]['image_url'] }}"
mode: singletype: vertical-stack
cards:
- type: markdown
content: >
# 🪼 JellyHA Sensors
**Version:** {{ states('sensor.jellyha_version') }} | **Status:** {{
states('sensor.jellyha_websocket') }}
- type: entities
title: Library Content
state_color: true
entities:
- entity: sensor.jellyha_library
name: Total Items
icon: mdi:video-vintage
secondary_info: last-changed
- type: divider
- entity: sensor.jellyha_unwatched_movies
name: Unwatched Movies
icon: mdi:movie-open
- entity: sensor.jellyha_watched_movies
name: Watched Movies
icon: mdi:movie-check
- type: divider
- entity: sensor.jellyha_unwatched_series
name: Unwatched Series
icon: mdi:video-outline
- entity: sensor.jellyha_watched_series
name: Watched Series
icon: mdi:video-check-outline
- entity: sensor.jellyha_unwatched_episodes
name: Unwatched Episodes
icon: mdi:video
- entity: sensor.jellyha_watched_episodes
name: Watched Episodes
icon: mdi:video-check
- type: horizontal-stack
cards:
- type: gauge
entity: sensor.jellyha_active_sessions
name: Active Sessions
min: 0
max: 10
severity:
green: 0
yellow: 3
red: 7
- type: tile
entity: sensor.jellyha_favorites
name: Favorites
icon: mdi:heart
- type: entities
title: Activity & System
entities:
- entity: sensor.jellyha_now_playing_admin
name: Admin
icon: mdi:account
- type: divider
- entity: sensor.jellyha_last_library_update
name: Last Library Update
- entity: sensor.jellyha_last_refresh
name: Last Refresh
- entity: sensor.jellyha_refresh_duration
name: Refresh DurationThis error means the dashboard cannot load the frontend code.
- Verify Installation: Ensure you have added the correct Dashboard Resource URL:
/jellyha/jellyha-cards.js. - Clear Cache: Restart Home Assistant and clear your browser cache (Ctrl + F5) or go into Incognito mode.
- Redownload: If installed via HACS, go to HACS → JellyHA → ⋮ → Redownload (select "main" version if specifically troubleshooting a new fix).
If the card shows "No recent media found" but you know you have items:
- Check Filters: Ensure "Filter Favorites" or "Filter Unwatched" are not enabled in the card configuration if your items don't match those criteria.
- Check Logs: Open the browser console (F12) to see if there are any specific errors.
- Verify Sensor: Check
sensor.jellyha_libraryin Developer Tools to ensure it has attributes (entry_id, etc.).
This usually indicates a duplicate command registration. Ensure you are running the latest version. We have implemented safeguards against this in v1.0.
This project was developed with the assistance of AI.
MIT
Personal Use Only This integration is provided as a neutral interface for your private media library. JellyHA does not provide, facilitate, or encourage the use of unauthorized or pirated content. By using this software, you agree that you are solely responsible for the legality of the media you host and stream.





