python-plexapi: unofficial Python bindings for driving a Plex Media Server
Python bindings for the Plex API.
At a glance
- What is it?
- python-plexapi is a BSD-3-Clause licensed Python library that wraps the Plex HTTP API so a script can browse libraries, run scans, mark media played, list connected clients and drive playback, including Sonos speakers through the Plex Pass service. It suits a self-hosted Plex user writing automation, and it is the wrong tool if you need Plex's own supported client, since it is explicitly unofficial.
- Who is it for?
- python-plexapi fits a self-hosted Plex user who wants to script the server, whether to mark episodes watched, collect watch history, or push a specific album to a speaker, since the library exposes the same operations the Plex web client performs and the README shows each one in a few lines.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The goal was to match the Plex web client, feature by feature
The README describes the library as unofficial Python bindings for the Plex API, with the goal of matching all capabilities of the official Plex Web Client. The named features cover most of what a person does in that interface: navigating local or remote shared libraries, performing library actions such as scan, analyze and empty trash, remote control and playing media on connected clients including controlling Sonos speakers, and listening in on all Plex Server notifications. The unofficial status is the honest framing, and it matters in one specific way, which is that when Plex changes its API the library has to follow, and there is no vendor commitment behind that. The repository is not archived, the last push was on 2026-10-15, and the release history shows 4.18.3 on 2026-09-28 after 4.18.2 in July.
Two ways in, and the difference is the account you hold
There are two types of authentication, and the README explains when each applies. If you are on a separate network or using Plex Users, you log into MyPlex to get a PlexServer instance, and the server name you pass is the name shown in the top left of the Plex web client, not a hostname and port.
from plexapi.myplex import MyPlexAccount
account = MyPlexAccount('<USERNAME>', '<PASSWORD>')
plex = account.resource('<SERVERNAME>').connect() # returns a PlexServer instanceIf you would rather not log into MyPlex and already know the auth token string, you construct the PlexServer object directly with the base URL and the token.
from plexapi.server import PlexServer
baseurl = 'http://plexserver:32400'
token = '2ffLuB84dqLswk9skLos'
plex = PlexServer(baseurl, token)The token route is the normal one for a local server, and it is also the route the test suite uses, with the base URL and credentials supplied through environment variables rather than hardcoded.
The library API mirrors the web client, so scripts read like clicks
The usage examples in the README are short enough to show the shape of the whole API. A section is a named library, and search takes keyword arguments.
# Example 1: List all unwatched movies.
movies = plex.library.section('Movies')
for video in movies.search(unwatched=True):
print(video.title)Marking a whole show as watched is a single call on the show object, and listing connected clients iterates over plex.clients(). Playing a specific title on a specific device takes the item and a client by name, with the note that the client must be on the same network as the server. A search across the whole server accepts a plain string, and a library search can take filters, for instance a director, which is how you find every movie by the same person. Episodes expose their media parts through iterParts(), playlists are enumerated from the server, and a rating is applied with a numeric value.
# Example 2: Mark all Game of Thrones episodes as played.
plex.library.section('TV Shows').get('Game of Thrones').markPlayed()Sonos playback goes out to Plex's own service and back
Controlling Sonos speakers is the one part of the API with a dependency outside your network. The README lists three requirements: an active Plex Pass subscription, a Sonos account linked to the Plex account, and Plex remote access enabled. The calls route through the sonos.plex.tv service and back via the Plex server's remote access, and the README notes that actual media playback is local unless networking restrictions stop the Sonos speakers from connecting to the Plex server directly. The API shape is a player object obtained from the account, with methods for playing media, pausing, setting volume and skipping, alongside a listing of available speakers and groups.
account = MyPlexAccount(token)
server = PlexServer(baseurl, token)
for speaker in account.sonos_speakers():
print(speaker.title)
speaker = account.sonos_speaker("Kitchen")
album = server.library.section('Music').get('Stevie Wonder').album('Innervisions')
speaker.playMedia(album)
speaker.pause()
speaker.setVolume(10)
speaker.skipNext()For local playback, which is what most self-hosted users want, the same client mechanism applies to any device Plex sees, such as a phone or a television.
Install is one pip command, and the extras are genuinely optional
The installation section is short, and the package name on PyPI differs from the repository name, which is worth knowing before you go looking for it.
pip install plexapiThere are two extras, each pulling in what one feature needs. The alert extra installs the dependencies required for plexapi.alert, which is the websocket client for the server notifications, and the jwt extra installs the dependencies for Plex JWT authentication.
pip install plexapi[alert] # Install with dependencies required for plexapi.alert
pip install plexapi[jwt] # Install with dependencies required for Plex JWT authenticationThe core package depends only on requests, and pyproject.toml requires Python 3.10 or later. The version is read dynamically from plexapi.const.__version__, so the installed version and the repository version cannot drift apart, and the README points to the Read the Docs documentation and a Discord server for support.
The test suite wants a real server, and the tooling builds one
The running tests section explains that the test suite is not a set of mocks. It uses a script in the tools/ directory, plex-bootstraptest.py, which creates a proper instance using the official Docker image, and it requires the new server to be added to a shared user whose username is defined in the environment variable SHARED_USERNAME. To skip the Docker path and reuse an existing server, the script takes --no-docker with username, password and server-name arguments. Most of the tests also need environment variables: PLEXAPI_AUTH_SERVER_BASEURL with the URL of the Plex instance without a trailing slash, and PLEXAPI_AUTH_MYPLEX_USERNAME and PLEXAPI_AUTH_MYPLEX_PASSWORD for the MyPlex account.
py.test tests -rxXs -The pytest configuration in pyproject.toml registers markers for tests that need a client, that require one to run, that run anonymously and that run authenticated, so the suite can be selected by what the environment provides rather than by editing the tests.
Editorial conclusion
python-plexapi fits a self-hosted Plex user who wants to script the server, whether to mark episodes watched, collect watch history, or push a specific album to a speaker, since the library exposes the same operations the Plex web client performs and the README shows each one in a few lines. It is a poor fit if your server is a hosted Plex Pass account you do not control, since a local PlexServer instance and its token are assumed, and a poor fit if you need a supported client, because the project states plainly that these bindings are unofficial. Verify first whether your Plex server has remote access enabled and whether you are on the same network as the server, since client-driven playback and Sonos control both depend on that path working.
Frequently asked questions
How do I install python-plexapi?
Run pip install plexapi. Two extras are available, pip install plexapi[alert] for the websocket notification dependencies and pip install plexapi[jwt] for Plex JWT authentication. The core package needs only requests and Python 3.10 or later.
How do I connect to a Plex server?
You can log into MyPlex with MyPlexAccount and call account.resource with the server name, then connect, which returns a PlexServer instance. If you already have the auth token, construct PlexServer directly with the base URL and the token.
Can python-plexapi control Sonos speakers?
Yes, with an active Plex Pass subscription, a Sonos account linked to the Plex account and Plex remote access enabled. The calls route through the sonos.plex.tv service, and the player object supports playMedia, pause, setVolume and skipNext.
Do the tests need a real Plex server?
Yes. The tooling in tools/ uses the official Docker image to create a proper instance, or you can pass --no-docker to reuse an existing server. The tests also read PLEXAPI_AUTH_SERVER_BASEURL, PLEXAPI_AUTH_MYPLEX_USERNAME and PLEXAPI_AUTH_MYPLEX_PASSWORD from the environment.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pushingkarmaorg-python-plexapi)Was this useful?