npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@get-coral/jellyfin

v1.6.5

Published

TypeScript client for the Jellyfin API — part of the Coral ecosystem

Readme

@get-coral/jellyfin

A fully typed TypeScript client for the Jellyfin API — part of the Coral ecosystem.

npm License: MIT Build

Modern, fetch-based Jellyfin API client with full TypeScript types. No dependencies. Works in Node.js, browsers, and edge runtimes (Cloudflare Workers, Vercel Edge, etc).


Install

pnpm add @get-coral/jellyfin
# or
npm install @get-coral/jellyfin

Quick start

import { createClient, getLibraryItems, fromJellyfin } from '@get-coral/jellyfin'

const client = createClient({
  url: 'http://192.168.1.10:8096',
  apiKey: 'your-api-key',
  userId: 'your-user-id',
})

const { Items } = await getLibraryItems(client, 'Movie', {
  limit: 24,
  sortBy: 'SortName',
  watchStatus: 'unwatched',
})

const movies = Items.map(item => fromJellyfin(client, item))

Client configuration

const client = createClient({
  url: string        // Jellyfin server URL (trailing slash stripped automatically)
  apiKey: string     // Jellyfin API key
  userId: string     // User ID (UUID)

  // Optional — for playback progress sync
  username?: string
  password?: string

  // Optional — how this client identifies itself in Jellyfin's active sessions
  clientName?: string  // default: 'Coral'
  deviceName?: string  // default: 'Coral Web'
  deviceId?: string    // default: 'coral-web'
  version?: string     // default: '1.0.0'
})

Set clientName to your app's name so it shows up correctly in Jellyfin's dashboard:

const client = createClient({
  url: process.env.JELLYFIN_URL,
  apiKey: process.env.JELLYFIN_API_KEY,
  userId: process.env.JELLYFIN_USER_ID,
  clientName: 'KAPOW!',
  deviceName: 'KAPOW! Web',
  deviceId: 'kapow-web',
})

API reference

Items

getItem(client, itemId)
// → JellyfinItem — single item with full metadata including cast, studios, tags

searchItems(client, query, types?)
// → JellyfinItem[] — search across media types (default: Movie, Series)

getFeaturedItem(client, type?)
// → JellyfinItem | null — random item with backdrop, useful for hero sections

getContinueWatching(client, limit?)
// → JellyfinItem[] — in-progress items

getLatestMedia(client, type?, limit?)
// → JellyfinItem[] — recently added

getFavoriteItems(client, type?, limit?)
// → JellyfinItem[] — items marked as favourite

getMostPlayed(client, type?, limit?)
// → JellyfinItem[] — sorted by play count

getLibraryItems(client, type, options?)
// → JellyfinResponse<JellyfinItem> — paginated library with full filtering

getWatchHistory(client, options?)
// → JellyfinResponse<JellyfinItem> — played items sorted by date watched

getSimilarItems(client, itemId, limit?)
// → JellyfinItem[] — similar items

setFavorite(client, itemId, isFavorite)
// → { IsFavorite: boolean }

setPlayed(client, itemId, played)
// → { Played: boolean }

deleteItem(client, id)
// → void

updateItemName(client, id, name)
// → void

getLibraryItems options

{
  sortBy?: string           // default: 'SortName'
  sortOrder?: 'Ascending' | 'Descending'
  limit?: number            // default: 24
  startIndex?: number       // for pagination
  genre?: string
  watchStatus?: 'watched' | 'unwatched' | 'inprogress'
  officialRatings?: string  // e.g. 'PG,PG-13'
  minCommunityRating?: number
  minPremiereDate?: string  // ISO date string
  maxPremiereDate?: string
}

Shows

getEpisodesForSeries(client, seriesId)
// → JellyfinItem[] — all episodes sorted by season/episode number

getNextUpForSeries(client, seriesId, limit?)
// → JellyfinItem[] — next unwatched episodes

Collections

getCollections(client)
// → JellyfinItem[] — all BoxSet collections

getCollectionItems(client, collectionId)
// → JellyfinItem[] — items in a collection

createCollection(client, name, itemIds?)
// → { Id: string }

addItemsToCollection(client, collectionId, itemIds)
removeItemsFromCollection(client, collectionId, itemIds)

Playback

createPlaybackSession(client, itemId, options?)
// → JellyfinPlaybackSession
// Resolves the best stream URL, detects direct play vs transcode,
// and extracts subtitle tracks. Requires username + password in config.

{
  streamUrl: string
  canSyncProgress: boolean
  playMethod: 'DirectPlay' | 'Transcode'
  playSessionId?: string
  mediaSourceId?: string
  sessionId?: string
  subtitleTracks: SubtitleTrack[]
}

syncPlaybackState(client, input)
// Reports playback position back to Jellyfin (progress, pause, stop, played)

URL builders

These return strings — useful when you need to pass URLs to an <img> or video player directly.

imageUrl(client, itemId, type?, width?)
// type: 'Primary' | 'Backdrop' | 'Thumb' | 'Logo' | 'Banner'
// default: 'Primary', width: 400

personImageUrl(client, personId, width?)
streamUrl(client, itemId, options?)
transcodeUrl(client, itemId, options?)
subtitleUrl(client, itemId, mediaSourceId, streamIndex)

Mapper

Converts raw JellyfinItem objects into a normalised MediaItem shape. Useful for building UIs that don't want to deal with Jellyfin's raw API format.

fromJellyfin(client, item)
// → MediaItem — normalised shape with resolved image URLs and stream URL

fromJellyfinDetailed(client, item)
// → DetailedMediaItem — includes cast, studios, tags

isResumable(item)
// → boolean — true if item has a resume position and hasn't been fully watched

Admin

getSystemInfo(client)       // → JellyfinSystemInfo
getItemCounts(client)       // → JellyfinItemCounts
getActiveSessions(client)   // → JellyfinActiveSession[]

getUsers(client)
getUserById(client, userId)
createUser(client, name, password)
deleteUser(client, userId)
updateUserPolicy(client, userId, policy)

getVirtualFolders(client)   // → JellyfinVirtualFolder[]
scanAllLibraries(client)
scanLibrary(client, itemId)

Error handling

All functions throw a JellyfinError on non-OK responses:

import { JellyfinError } from '@get-coral/jellyfin'

try {
  const item = await getItem(client, 'bad-id')
} catch (err) {
  if (err instanceof JellyfinError) {
    console.error(err.message) // 'Jellyfin API error on /Users/.../Items/bad-id: 404 Not Found'
    console.error(err.status)  // 404
  }
}

Types

All types are exported from the package root:

import type {
  JellyfinItem,
  JellyfinClientConfig,
  MediaItem,
  DetailedMediaItem,
  JellyfinPlaybackSession,
  // ... and more
} from '@get-coral/jellyfin'

Part of the Coral ecosystem

This package is built and maintained as part of Coral — a reef of independent Docker modules that extend Jellyfin with modern UX.

| Module | Description | |--------|-------------| | 🎬 Aurora | High-end cinematic Jellyfin frontend | | 🎤 KAPOW! | Karaoke queue manager for bars & events | | 📖 Fathom | Modern reading app from your NAS |


Contributing

Issues and PRs welcome. See CONTRIBUTING.md for guidelines.

License

MIT © ElianCodes