Skip to main content

Overview

PlexClient extends MediaClient to provide integration with Plex Media Server. It supports library browsing, video streaming (direct play and transcoding), and playlist-based favorites.

Constructor

import { PlexClient } from './services/PlexClient';

const client = new PlexClient(config);
config
ServerConfig
required
Server configuration with Plex server details

Authentication

authenticate

Authenticates with a Plex server using an X-Plex-Token.
authenticate(username: string, password: string): Promise<ServerConfig>
username
string
required
Username (can be any value, used for display)
password
string
required
X-Plex-Token from Plex account settings
url
string
Server URL
username
string
Username or ‘Plex User’ if not provided
userId
string
Server’s MachineIdentifier (used for playlist URIs)
token
string
X-Plex-Token for API requests
serverType
'plex'
Always returns ‘plex’

Example

const config: ServerConfig = {
  url: 'https://plex.example.com:32400',
  username: '',
  token: '',
  userId: '',
  serverType: 'plex'
};

const client = new PlexClient(config);
const authConfig = await client.authenticate(
  'MyPlexUser',
  'YOUR_X_PLEX_TOKEN'
);

console.log(authConfig.userId); // MachineIdentifier
To get your X-Plex-Token, visit your Plex account settings or check the Plex documentation.

Library Management

getLibraries

Fetches all library sections from the Plex server.
getLibraries(): Promise<EmbyLibrary[]>
return
Promise<EmbyLibrary[]>
Array of library objects with Id (section key), Name (title), and CollectionType (type)

Example

const libraries = await client.getLibraries();

libraries.forEach(lib => {
  console.log(`${lib.Name} - Type: ${lib.CollectionType}`);
});

Video Retrieval

getVideos

Fetches videos from a Plex library with filtering and pagination.
getVideos(
  parentId: string | undefined,
  libraryName: string,
  feedType: FeedType,
  skip: number,
  limit: number,
  orientationMode: OrientationMode
): Promise<VideoResponse>
parentId
string | undefined
required
Library section key (required for standard feeds, undefined for favorites)
libraryName
string
required
Name of the library for playlist lookups
feedType
FeedType
required
  • 'latest': Sorted by addedAt descending
  • 'random': Random shuffle
  • 'favorites': Items from Tok playlist
skip
number
required
Starting index for pagination
limit
number
required
Not directly used (batch size: 50 for latest, 80 for random)
orientationMode
OrientationMode
required
  • 'vertical': Only videos with height >= width * 0.8
  • 'horizontal': Only videos with width > height
  • 'both': No filtering
items
EmbyItem[]
Array of video items mapped from Plex format
nextStartIndex
number
Index for the next page
totalCount
number
Total number of items in the library

Example

const response = await client.getVideos(
  '1', // Library section key
  'Movies',
  'random',
  0,
  15,
  'horizontal'
);

console.log(`Found ${response.totalCount} total videos`);
response.items.forEach(video => {
  console.log(`${video.Name} (${video.ProductionYear})`);
});

Media URLs

getVideoUrl

Generates streaming URL for a video with fallback to transcoding.
getVideoUrl(item: EmbyItem): string
item
EmbyItem
required
Video item (with Plex-specific _PlexKey field for direct play)
return
string
Direct play URL if available, otherwise HLS transcode URL

getImageUrl

Generates URL for video thumbnail using Plex’s photo transcoder.
getImageUrl(
  itemId: string,
  tag?: string,
  type?: 'Primary' | 'Backdrop'
): string
itemId
string
required
Plex ratingKey
tag
string
Not used for Plex (included for interface compatibility)
type
'Primary' | 'Backdrop'
Not used for Plex (always fetches thumb)
return
string
Transcoded thumbnail URL at 800x1200

Example

const videoUrl = client.getVideoUrl(video);
const thumbnailUrl = client.getImageUrl(video.Id);

// Video URL will be direct play if available:
// https://plex.example.com/library/parts/12345/file.mp4?X-Plex-Token=...
// Or HLS transcode:
// https://plex.example.com/video/:/transcode/universal/start?...

Favorites Management

PlexClient uses playlists named Tok-{LibraryName} to store favorites.

getFavorites

Retrieves all favorited item IDs for a library.
getFavorites(libraryName: string): Promise<Set<string>>
libraryName
string
required
Name of the library
return
Promise<Set<string>>
Set of ratingKeys in the Tok playlist (empty set if playlist doesn’t exist)

toggleFavorite

Adds or removes an item from the favorites playlist.
toggleFavorite(
  itemId: string,
  isFavorite: boolean,
  libraryName: string
): Promise<void>
itemId
string
required
Plex ratingKey of the video
isFavorite
boolean
required
Current status: true = currently favorited (will remove), false = not favorited (will add)
libraryName
string
required
Library name for playlist lookup/creation

Example

// Load favorites
const favoriteIds = await client.getFavorites('Movies');

// Check if video is favorited
const isFavorite = favoriteIds.has(video.Id);

// Toggle favorite (add if not favorited, remove if favorited)
await client.toggleFavorite(video.Id, isFavorite, 'Movies');

// Playlist is auto-created on first favorite if it doesn't exist

Complete Usage Example

import { ClientFactory } from './services/clientFactory';

// Authenticate with X-Plex-Token
const config = await ClientFactory.authenticate(
  'plex',
  'https://192.168.1.100:32400',
  'PlexUser',
  'YOUR_X_PLEX_TOKEN'
);

const client = ClientFactory.create(config);

// Get libraries
const libraries = await client.getLibraries();
const tvLib = libraries.find(l => l.CollectionType === 'show');

// Load random horizontal videos
const { items } = await client.getVideos(
  tvLib.Id,
  tvLib.Name,
  'random',
  0,
  15,
  'horizontal'
);

// Check favorites
const favoriteIds = await client.getFavorites(tvLib.Name);

items.forEach(video => {
  const url = client.getVideoUrl(video);
  const thumb = client.getImageUrl(video.Id);
  const isFav = favoriteIds.has(video.Id);
  
  console.log(`${video.Name} - Favorite: ${isFav}`);
  console.log(`Stream: ${url}`);
  console.log(`Thumb: ${thumb}`);
});

Implementation Details

Headers

All requests include:
  • Accept: application/json
  • X-Plex-Token: {token}

Plex Item Mapping

Plex metadata is mapped to EmbyItem format:
  • ratingKeyId
  • titleName
  • typeType
  • summaryOverview
  • yearProductionYear
  • Media[0].widthWidth
  • Media[0].heightHeight
  • durationRunTimeTicks (converted: duration * 10000)
  • thumb → Stored in _PlexThumb (internal)
  • Media[0].Part[0].key → Stored in _PlexKey (internal)

Playlist URIs

When managing favorites, items are referenced using:
server://{MachineIdentifier}/com.plexapp.plugins.library/library/metadata/{ratingKey}

Orientation Filtering

Same as EmbyClient:
  • Vertical: height >= width * 0.8
  • Horizontal: width > height
  • Both: No filtering

See Also

Build docs developers (and LLMs) love