TypeScript SDK for
PlexandPlex Media ServerAPIs with full type safety, payload response simplification and comprehensive coverage
- π Secure Authentication: Full support for Plex.tv authentication
- π― Type Safety: Complete TypeScript definitions for all API responses
- π Modern ESM: Built as a modern ES module with tree-shaking support
- π¦ Lightweight: Minified bundle with zero runtime dependencies
- π§ͺ Well Tested: Comprehensive test suite with 97%+ coverage
- π¬ Media Server Integration: Direct access to your Plex Media Server
- π Search Capabilities: Powerful search across movies, TV shows, and more
npm install plex-sdkyarn add plex-sdkpnpm add plex-sdkgit clone [email protected]:nass600/plex-sdk.git
cd plex-sdk
npm install
npm run buildThis SDK simplifies Plex API responses by automatically extracting the relevant data from the nested MediaContainer structure. Instead of dealing with complex nested objects, you get clean, direct access to the data you need.
Before (Raw Plex API):
{
"MediaContainer": {
"size": 1,
"Directory": [
{
"title": "Movies",
"type": "movie",
"key": "/library/sections/1"
}
]
}
}After (Simplified SDK Response):
;[
{
title: 'Movies',
type: 'movie',
key: '/library/sections/1',
},
]The SDK handles the MediaContainer extraction automatically, so you can focus on working with your data directly.
First, you need to get your Plex token. You can find it by:
- Open your Plex web app in your browser
- Open Developer Tools (F12 or right-click β Inspect)
- Go to the Network tab
- Refresh the page or navigate to any section
- Look for requests to plex.tv - the token will be in the request headers as
X-Plex-Token - Copy the token value (it's a long string of letters and numbers)
Alternatively, you can find it in your Plex app settings or by examining the network requests in any Plex client.
import { PlexClient } from 'plex-sdk'
const client = new PlexClient('your-plex-token-here', {
device: 'My App',
product: 'My Plex App',
version: '1.0.0',
})The SDK provides two ways to connect to your Plex Media Server:
First, you can explore all available resources to see what's available:
const resources = await client.getResources()
// Display all resources with their types
resources.forEach(resource => {
console.log(`${resource.name}: ${resource.provides?.join(', ')}`)
})
// Filter to find only servers
const servers = resources.filter(resource => resource.provides?.includes('server'))
// Query any resource
const hubs = servers[0].hubs.all()Once you know your server name, you can connect directly:
// Connect by server name using the first connection available
const server = await client.getServer('My Plex Server')
// Or filtering by connection preferences
const server = await client.getServer('My Plex Server', {
local: true, // Prefer local connections
secure: true, // Prefer secure connections
relay: false, // Avoid relay connections
})
// Query any resource
const hubs = server.hubs.all()The SDK supports advanced connection filtering with both exact matching and regex patterns:
// Exact matching (existing behavior)
const server = await client.getServer('My Plex Server', {
address: '192.168.1.100',
protocol: 'https',
local: true,
})
// Regex pattern matching (new feature)
const server = await client.getServer('My Plex Server', {
address: /192\.168\.1\.\d+/, // Match any IP in 192.168.1.x range
protocol: /^https?$/, // Match http or https
port: /^324\d+$/, // Match ports starting with 324
})
// Mixed exact and regex matching
const server = await client.getServer('My Plex Server', {
local: true, // Exact boolean match
address: /192\.168\.\d+\.\d+/, // Regex for local network IPs
protocol: 'https', // Exact protocol match
})
// Partial string matching with regex
const server = await client.getServer('My Plex Server', {
address: /example\.com/, // Match any address containing 'example.com'
uri: /https:\/\/.*\.local/, // Match HTTPS URIs ending with '.local'
})Available filter properties:
address- Server address (supports regex patterns)protocol- Connection protocol (http/https)port- Port numberuri- Full connection URIlocal- Whether connection is localrelay- Whether connection uses relayIPv6- Whether connection uses IPv6
Here's a comprehensive example showing how to search for a specific movie:
import { PlexClient, SearchType } from 'plex-sdk'
async function searchForMovie(movieTitle: string) {
// 1. Initialize the Plex client with your token
const client = new PlexClient('your-plex-token-here', {
device: 'Movie Search App',
product: 'Plex Movie Finder',
version: '1.0.0',
})
try {
// 2. Connect directly to your server by name
const server = await client.getServer('My Plex Server')
console.log(`β
Connected to server: ${server.name}`)
// 5. Search for the movie
const searchResults = await server.library.search({
query: movieTitle, // The query text will be normalized internally
searchTypes: [SearchType.MOVIES],
})
if (searchResults.length === 0) {
console.log(`β No movies found for "${movieTitle}"`)
return null
}
// 6. Display results
console.log(`π¬ Found ${searchResults.length} movie(s) for "${movieTitle}":`)
searchResults.forEach((movie, index) => {
console.log(`\n${index + 1}. ${movie.title} (${movie.year})`)
console.log(` Rating: ${movie.rating}/5`)
console.log(` Duration: ${Math.round(movie.duration / 60000)} minutes`)
console.log(` Summary: ${movie.summary?.substring(0, 100)}...`)
if (movie.Role && movie.Role.length > 0) {
console.log(
` Cast: ${movie.Role.slice(0, 3)
.map(role => role.tag)
.join(', ')}`
)
}
})
return searchResults[0] // Return the first result
} catch (error) {
console.error('β Error searching for movie:', error)
throw error
}
}
// Usage
searchForMovie('The Dark Knight')
.then(movie => {
if (movie) {
console.log(`\nπ Successfully found: ${movie.title}`)
}
})
.catch(error => {
console.error('Failed to search for movie:', error)
})async function browseLibrary() {
const client = new PlexClient('your-plex-token-here', {
device: 'Library Browser',
product: 'Plex Library Explorer',
version: '1.0.0',
})
const server = await client.getServer('My Plex Server')
// Get all libraries
const libraries = await server.library.all()
console.log('π Available libraries:')
libraries.forEach(lib => {
console.log(` - ${lib.title} (${lib.type})`)
})
// Get all movies from the first library
if (libraries.length > 0) {
const movies = await server.library.allItems(libraries[0].key)
console.log(`\n㪠Movies in ${libraries[0].title}:`)
movies.slice(0, 5).forEach(movie => {
console.log(` - ${movie.title} (${movie.year})`)
})
}
}async function getMovieDetails(movieId: string) {
const client = new PlexClient('your-plex-token-here', {
device: 'Movie Details App',
product: 'Plex Movie Info',
version: '1.0.0',
})
const server = await client.getServer('My Plex Server')
// Get detailed metadata for a specific movie
const movie = await server.metadata.one(movieId)
console.log(`π¬ ${movie.title} (${movie.year})`)
console.log(`π ${movie.summary}`)
console.log(`β Rating: ${movie.rating}/5`)
console.log(`β±οΈ Duration: ${Math.round(movie.duration / 60000)} minutes`)
if (movie.Director) {
console.log(`π Director: ${movie.Director.map(d => d.tag).join(', ')}`)
}
if (movie.Role) {
console.log(
`π₯ Cast: ${movie.Role.slice(0, 5)
.map(role => role.tag)
.join(', ')}`
)
}
if (movie.Genre) {
console.log(`π Genres: ${movie.Genre.map(g => g.tag).join(', ')}`)
}
}async function browseHubs() {
const client = new PlexClient('your-plex-token-here', {
device: 'Hub Browser',
product: 'Plex Hub Explorer',
version: '1.0.0',
})
const server = await client.getServer('My Plex Server')
// Get all hubs
const hubs = await server.hubs.all()
console.log('π Available hubs:')
hubs.forEach(hub => {
console.log(` - ${hub.title} (${hub.type})`)
})
}The main client for interacting with Plex.tv services.
const client = new PlexClient(token: string, {
device?: string, // Device name (default: 'Node.js')
product?: string, // Product name (default: 'Plex SDK')
version?: string, // Version string (default: '1.0')
platform?: string, // Platform name (default: 'Node.js')
clientIdentifier?: string // Client identifier (default: 'plex-sdk')
})getResources(): Promise<PlexResource[]>- Get available Plex serversgetServer(resourceName: string, connectionsFilter?: PlexConnectionFilter): Promise<PlexServer>- Create a server instance with advanced filtering
Represents a connection to a Plex Media Server.
name: string- Server namehubs: Hubs- Access to server hubslibrary: Library- Access to media librarymetadata: Metadata- Access to metadata
search(query: string): Promise<SearchResult[]>- Search across all media
Provides access to the media library.
all(): Promise<Directory[]>- Get all librariesallItems(sectionId: string, params?: QueryParams): Promise<Metadata[]>- Get all items from a librarysearch(params: SearchParams): Promise<SearchResult[]>- Search within libraries
interface SearchParams {
query: string // Search query (required)
searchTypes: SearchType[] // Types to search (MOVIES, TV, etc.)
}type PlexConnectionFilter = Partial<{
[K in keyof PlexConnection]: PlexConnection[K] | RegExp
}>
// Example usage:
const filter: PlexConnectionFilter = {
address: /192\.168\.1\.\d+/, // Regex pattern
protocol: 'https', // Exact match
local: true, // Boolean match
port: /^324\d+$/, // Regex pattern
}The SDK provides comprehensive error handling:
try {
const server = await client.getServer('My Plex Server')
} catch (error) {
if (error.message.includes('Server not found')) {
console.error('β Plex server not found - check your server name')
} else if (error.message.includes('Network error')) {
console.error('β Network connection failed - check your internet connection')
} else if (error.message.includes('Unauthorized')) {
console.error('β Invalid token - check your Plex token')
} else {
console.error('β Unexpected error:', error.message)
}
}Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
We use SemVer for versioning. For the versions available, see the tags on this repository.
See CHANGELOG file for more details.
This project is licensed under the MIT License - see the LICENSE file for details