Skip to main content

Plex Media Server

Local-LAN driver for Plex Media Server. Controls playback on registered Plex clients (Apple TV, Roku, Shield, smart TVs, web/desktop apps), reports what is currently playing per client, and exposes server-side library discovery to macros.

One Plex Media Server is the GEM device. Each GEM zone maps to one Plex client (player) by its machineIdentifier.

Prerequisites​

  • Plex Media Server >= 1.20 running on the LAN, signed in to a Plex account.
  • A long-lived X-Plex-Token for the Plex account. To get it:
    1. Sign in to the Plex web UI (https://app.plex.tv).
    2. Open any media item.
    3. Click the three-dot menu → Get Info → View XML.
    4. The URL contains a X-Plex-Token=... query parameter — copy that value.
  • Each player you want to control (Apple TV, Roku, Shield, etc.) must be signed in to the same Plex account and reachable from the server on the LAN. Plex players only stay reachable from the server while the app is in the foreground.

Setup​

Open Devices

  1. Add the device — go to System → Devices → Add Device and create a device with the driver plex_media_server.
  2. Fill in attributes:
    • ip — LAN address of the Plex Media Server (e.g. 192.168.1.42).
    • token — paste the X-Plex-Token from the prerequisites. Stored encrypted.
    • port — defaults to 32400. Use 32443 if you have enforced HTTPS remote access.
    • protocol — http (default) or https.
  3. Enumerate clients — open the device and run the get_clients command. It returns the players currently reachable on the LAN; each entry's machineIdentifier is the value you put in a zone's address.
  4. Create one zone per client. Add a zone, set address to that client's machineIdentifier, and leave the AV subsystem the zone editor pre-selects (Plex clients are media players). Make sure each target player is awake and in the foreground when you enumerate, or it will not appear in the client list.
  5. (Optional) Run get_libraries to list the Plex libraries (Movies, TV, Music, Photos, …) — useful when authoring macros that pick content by section.
Zones are not created automatically

This driver does not create zones for you. Add one zone per Plex client by hand and set its address to the client's machineIdentifier. Only zones bound to this device whose address matches a live client receive playback state.

Attributes​

Device​

NameRequiredDescription
ipYesLAN address of the Plex Media Server.
tokenYesLong-lived X-Plex-Token (stored encrypted). Treat as a password.
portNoTCP port for the Plex server. Default 32400.
protocolNohttp (default) or https.
status_intervalNoHow often (ms) /status/sessions is polled. Default 5000; a blank, zero, negative or unusably large value uses the default.
request_timeoutNoHow long (ms) to wait for each reply from the server. Default 10000; a blank, zero, negative or unparseable value uses the default.
client_identifierNoUUID the driver presents as X-Plex-Client-Identifier. Auto-generated on first connect and persisted.

Zone​

NameRequiredDescription
addressYesPlex client machineIdentifier (UUID). Enumerate via get_clients. Surrounding spaces are ignored.

The driver writes the following zone attributes when polling sessions:

AttributeValues
stateplaying, paused, buffering, stopped, idle, offline
now_playingComposed string: Show — Season — Episode for TV; Artist — Album — Track for music.
media_typemovie, episode, track, clip, photo, unknown

idle means the client is reachable but nothing is playing; offline means it is not currently registered with the server (backgrounded or powered off). now_playing is cleared when the client goes idle or offline. These attributes are what you key automation triggers and on-screen tiles off — e.g. trigger a macro when a TV zone's state becomes playing.

Commands​

CommandArgsNotes
playaddressResume playback on the target client.
pauseaddressPause playback.
stopaddressStop and clear the now-playing queue.
skip_nextaddressAdvance to the next item.
skip_previousaddressGo to the previous item.
seekaddress, offsetSeek to absolute position in milliseconds. A blank or non-numeric offset is rejected, not treated as 0 — it will not restart the title from the beginning.
set_volumeaddress, levelVolume 0-100. A blank or non-numeric level is rejected, not treated as 0 — it will not silence the player. Only supported on clients that report volume capability (notably not Apple TV / Roku, which expose only mute via the audio platform).
get_clients—List players currently registered with the server.
get_sessions—List currently playing sessions across all clients.
get_libraries—List Plex libraries (Movies, TV, Music, Photos, …).
get_server_info—Read the server identity / capabilities document.

Zone address format​

address is the Plex client machineIdentifier — a UUID returned by get_clients (the machineIdentifier field of each Server entry).

Plex Web (the browser player) generates a new machineIdentifier per browser session, so it is not a useful target for long-term zone mappings. For permanent zones, target dedicated players (Apple TV, Roku, Shield, Plex desktop, smart TV apps).

Known limitations​

  • Server unreachable at startup. If the server does not answer when the device connects (powered off, still booting, wrong token), the driver tries again after 30 seconds, doubling the wait up to every 5 minutes, and starts polling as soon as the server answers. A reload restarts the cycle.
  • Unexpected replies. If the server's address answers with a page that is not Plex JSON (a proxy error page, a different service on that port), get_clients, get_sessions, get_libraries and get_server_info return an error saying the reply was not JSON, and zone state is left as it was rather than being reset to idle / offline.
  • Local LAN only. The driver does not support Plex's plex.tv cloud relay; the server must be reachable directly on the LAN.
  • Player visibility. Plex players drop off the server's known-clients list within ~60 seconds of being backgrounded, and the zone's state goes to offline. Before sending a command the driver re-checks the client list, so brief backgrounding is tolerated; if the client still is not registered the command fails with plex client not currently registered with the server. (A client that was just seen but has since gone away can instead surface a transient plex http 404.)
  • Volume capability varies by player platform. set_volume returns an ack even on platforms that ignore it (many streaming players, e.g. Apple TV and Roku, expose only mute) — confirm by ear or via get_sessions.
  • Content browsing and queue management are not built into this driver. It controls transport (play / pause / stop / skip / seek / volume) and reports what is playing; it does not browse libraries or load a specific title onto a player. Macros can enumerate libraries with get_libraries, but selecting and starting a particular item is not exposed.
  • No Plex source view. Plex can be chosen as the backing Device when you create an AV Source, but there is no Plex-specific on-screen browse / now-playing panel — the dedicated source views (sonos, spotify, roku, …) do not include Plex. Leave the AV Source's Component unset.
  • No login / 2FA flow — the integrator must provide a pre-minted X-Plex-Token. If the token is rotated in the Plex UI, update the token attribute.

Troubleshooting​

SymptomCheck
Every request returns 401 UnauthorizedToken expired or was rotated in the Plex web UI. Re-mint and update the token attribute.
get_clients returns an empty listPlex players only stay reachable while the app is in the foreground. Wake each player up and re-run get_clients.
Command fails with plex client not currently registered with the serverThe target client is backgrounded/offline, or its identifier changed (Plex Web mints a new one every session). Wake the player, re-run get_clients, and update the zone address if the identifier changed.
now_playing stays empty even while audio is heardThe session is being initiated by a player that has not yet contacted the server — give it 5–10 seconds, then re-check (the driver polls every status_interval ms, default 5000).
Wrong HTTP schemeIf you enforce HTTPS remote access, set protocol=https and port=32443. Self-signed certs are accepted.
  • Zones — creating the per-client zones and setting address.
  • Subsystems — the AV subsystem these client zones live under.
  • Devices — the device editor, secure attributes, and Reload.
  • Commands — the command tester used to run get_clients / get_libraries.
  • AV Sources — binding the device as an AV Source's backing device.