Skip to main content

Denon HEOS

Control a HEOS whole-home audio network — Denon and Marantz HEOS-enabled speakers and receivers, plus the standalone HEOS components (HEOS Amp, HEOS Link, HEOS Drive) — over the HEOS CLI protocol. One thing to understand up front: a single network connection sees every HEOS player on the LAN. You point this driver at the IP of any one HEOS speaker or amp, and through that one connection you can browse, play, and control all of them. Each player is then addressed by its HEOS player id (the pid).

The driver covers playback transport, volume and mute, queue management, music-source browsing and search, presets, physical inputs, and live push events (now-playing, state changes). It also backs the on-screen HEOS source view that end users see on a touchpanel, with dedicated browse panels for Pandora, SiriusXM, and Amazon Music.

How HEOS addressing works

This is the one concept that makes everything else fall into place:

  • The connection is to one HEOS device's IP on TCP port 1255. That device is just the gateway — it relays to the whole HEOS network.
  • A player (one speaker, amp, or AVR zone) is identified by its pid — a long numeric id HEOS assigns, e.g. 1234567890. Almost every command takes a player_id argument, and that argument is the pid.
  • A music source (Pandora, SiriusXM, the local USB/DLNA library, etc.) is identified by a small numeric source id (sid). Browse and play-from-service commands take a source_id argument.

You discover the pids with the get_players command (it returns every player's name, model, and pid) and the source ids with the get_music_sources command. You do not type these by guessing — you read them off the network.

What's controlled

  • Transport: play, pause, stop, next, previous
  • Volume: absolute set (0100), step up/down, mute on/off/toggle
  • Now-playing metadata and live play-state push events
  • Queue: read, clear, jump to a queue item
  • Music-source browsing and search, container (album/playlist) and track playback
  • Station/stream playback, favorites presets, and physical input selection
  • Direct URL playback (play any reachable stream URL on a player)

Prerequisites

  • At least one HEOS-enabled device on the LAN, already set up through the HEOS mobile app.
  • The GEM server and the HEOS devices on the same subnet/VLAN — HEOS discovers its own players over multicast, so a player on a different VLAN won't appear in get_players.
  • HEOS account credentials (the same email/password used in the HEOS app). These are only needed for streaming-service browse and playback; local-library and basic transport work without an account, but most installs will want the account signed in.

Setup

There are two ways to deploy this driver. Pick based on what you need.

Pattern A — one gateway device, many players

Best when macros or the AI assistant drive many players from one place, passing the pid each time.

Open Devices

  1. Go to System → Devices → Add Device and choose the Denon HEOS driver.
  2. Set HEOS Device IP to the LAN IP of any one HEOS speaker/amp. Leave Port at 1255.
  3. Enter the HEOS Account Username and HEOS Account Password if you want streaming services. The password is stored encrypted.
  4. Save. On connect the driver signs in to the HEOS account, turns on push-event subscription, and is ready. Run the get_players command to list every player and its pid.
  5. From then on, send commands with the target player's pid in the player_id argument — for example a macro step running set_volume with player_id = the kitchen speaker's pid and volume = 40.

Pattern B — one device pinned to a single player

Best when you want a player to behave like a normal GEM zone/source — a volume slider, the source view, on/off macros — without supplying the pid on every command.

  1. Create a HEOS device exactly as in Pattern A (point it at that room's speaker IP).
  2. Open Attributes for the device and add an attribute named player_id set to that player's pid. (Optionally add source_id set to the default music source id you want its source view to open on.)
  3. Save and reload the device. Now every command this device sends automatically targets that one player — you can leave the player_id argument off, bind the device as an AV zone's Volume Device, and use the HEOS source view.
important
Why the player_id attribute matters

Volume, mute, and transport commands address the player by its pid. If a command runs with no pid — neither passed in its player_id argument nor present as a player_id attribute on the device — HEOS rejects it because it can't tell which player you mean. Setting the player_id attribute (Pattern B) fills that in for every command automatically; otherwise (Pattern A) you must supply it per command.

Using HEOS as an on-screen source

To give a room a HEOS streaming source with the browse / now-playing UI:

  1. Make sure the source's HEOS device carries a player_id attribute (the target player's pid) and a source_id attribute (the music source to open on) — see Pattern B. The source view reads both off the device and will warn if either is missing.
  2. Open AV Sources and create a source. Set Device to that HEOS device.
  3. Set Component to heos for the generic HEOS browser, or to pandora, siriusxm, or amazon_music for a service-specific panel (those panels render their HEOS variant because the source's device uses this driver).
  4. Mark it Global source if every room should be able to pick it. Save.

The source view then shows now-playing (track, artist, album art) and a browse surface for the chosen service, and it tracks live changes via the driver's push events. See AV Sources for the full source editor.

note

HEOS players are their own audio output — a HEOS source isn't routed through a matrix the way a shared cable box is. So a HEOS source is normally a Global streaming source, and its routing macros (if any) just start playback on the player rather than switching a matrix input.

Music source ids

The exact ids depend on what's enabled on the HEOS account, so always confirm with get_music_sources. Common HEOS source ids:

Sourcesource_id
Pandora1
SiriusXM8
Amazon Music13
Local music (USB / DLNA / network library)(varies — read from get_music_sources)

Pandora (1) and SiriusXM (8) are confirmed by the dedicated source-view panels; the rest can shift per account and firmware, which is why get_music_sources is the authority.

Attribute reference

Device

AttributeRequiredTypeDefaultDescription
ipyesstringLAN IP of any HEOS-enabled speaker/amp (the gateway).
portnoint1255HEOS CLI port. Leave at the default.
usernamenostringHEOS account email. Needed for streaming-service playback.
passwordnostring (encrypted)HEOS account password. Stored encrypted.
player_idnostringPins this device to one player (its pid). Set it to drive that player without passing player_id on every command, and to enable the source view / AV-zone volume binding.
source_idnostringDefault music source id the source view opens on.

heos_player_id / heos_source_id are accepted as alternate names for player_id / source_id if you have older rows using them; prefer the short names on new installs.

Commands

Every command below that names a player_id argument takes the target player's pid (or omit it when the device has a player_id attribute set — Pattern B).

Discovery and status

CommandArgsDescription
get_playersList every HEOS player on the network with name, model, and pid. Start here.
get_player_infoplayer_idDetailed info for one player.
get_play_stateplayer_idCurrent transport state.
get_now_playingplayer_idCurrent track/station metadata.
get_volumeplayer_idCurrent volume.
get_mute_statusplayer_idCurrent mute state.
get_play_modeplayer_idShuffle / repeat mode.
get_music_sourcesList available music sources with their source ids.
get_source_infosource_idDetail for one music source.
get_search_criteriasource_idSearch fields a source supports (get_source_search_criteria is an alias).

Transport

CommandArgsDescription
playplayer_idResume / start playback.
pauseplayer_idPause.
stopplayer_idStop.
nextplayer_idSkip to next track.
previousplayer_idPrevious track.
set_play_statestate, player_idSet transport directly (play / pause / stop).

Volume and mute

CommandArgsDescription
set_volumeplayer_id, volumeAbsolute volume 0100.
volume_upplayer_id, step_amountRaise volume by step_amount.
volume_downplayer_id, step_amountLower volume by step_amount.
mute_onplayer_idMute.
mute_offplayer_idUnmute.
mute_toggleplayer_idToggle mute.

Browse, search, and play

CommandArgsDescription
browse_sourcesource_id, start, endBrowse a music source's top level over a result range.
browse_source_containersource_id, container_id, start, endBrowse inside a container (album, playlist, genre) by its cid.
searchsource_id, search, criteria, start, endSearch a source; criteria is a search-criteria id from get_search_criteria.
play_containersource_id, player_id, container_idReplace the queue with a container and play.
play_trackplayer_id, source_id, container_id, media_idReplace the queue with one track (its mid) and play.
play_stationplayer_id, source_id, container_id, media_id, station_namePlay a station / radio stream.
play_urlplayer_id, urlPlay any reachable stream URL on the player.
play_inputinput_name, player_idSwitch the player to a physical input (e.g. an aux_in / line input).
play_presetplayer_id, preset_positionPlay a saved HEOS favorite by its 1-based preset slot.
set_service_optionsource_id, option, media_idApply a service option (thumbs-up, add-to-favorites, etc.).

Queue

CommandArgsDescription
get_queueplayer_id, start, endRead the play queue over a range.
queue_containersource_id, player_id, container_idAdd a container to the queue (don't replace).
queue_tracksource_id, player_id, container_id, media_idAdd one track to the queue.
play_queue_itemplayer_id, song_idJump to and play a queue item by its qid.
clear_queueplayer_idEmpty the queue.

Account and system

CommandArgsDescription
sign_inusername, passwordSign in to the HEOS account (the driver also does this automatically).
sign_outSign out of the HEOS account.
check_accountReport the signed-in account state.
subscribe_eventsenableTurn push-event subscription on/off (driver enables on connect).
heartbeatHEOS keepalive ping.
rebootReboot the HEOS device. Use with care — it drops the connection until it comes back.
prettify_jsonenableToggle pretty-printed responses (diagnostic).
passthroughcommandSend a raw HEOS CLI path (everything after heos://) — an escape hatch for commands not listed above.

Behavior and limitations

  • One connection, whole network. All players share the single TCP session to the gateway device. Don't create a second HEOS device pointed at a different speaker just to reach more players — the one connection already sees them all. (Creating a second device pinned to a specific player via its player_id attribute, per Pattern B, is fine and intended.)
  • Automatic sign-in and event re-arm. On every connect the driver signs in to the HEOS account and re-enables push-event subscription, and it re-signs in roughly once an hour. If a command comes back reporting the account isn't logged in, the driver re-runs sign-in on the spot. So streaming access self-heals after a network blip.
  • Push events. Now-playing changes are delivered live (briefly debounced so a burst of metadata updates settles into one). Play-state, queue-change, and now-playing-progress events are received but not all surfaced as separate notifications — the source view re-requests now-playing when it sees a change.
  • Auto-reconnect. The connection persists and reconnects automatically with backoff if the gateway speaker drops off the network or reboots.
  • No automatic zone discovery. Unlike some multi-room drivers, this one does not create a GEM zone per player on its own. You decide which players become zones/sources and configure them (Pattern B) or drive them by pid (Pattern A).

Troubleshooting

SymptomCheck
get_players returns fewer players than you haveThe missing players are on a different VLAN/subnet. HEOS discovery is multicast within one subnet — put the GEM host and the speakers on the same network.
Volume / transport commands do nothingThe command ran with no pid. Either pass the target player's pid in the player_id argument, or set a player_id attribute on the device (Pattern B).
Streaming returns "user not logged in"The HEOS account username/password is missing or wrong. It's the same login used in the HEOS mobile app. The driver retries sign-in automatically once credentials are correct.
No now-playing or live updatesThe push subscription didn't arm. Reload the device — the driver re-enables event subscription on every connect.
Source view warns about a missing player or source idThe source's HEOS device has no player_id and/or source_id attribute. Add both (Pattern B), then reload.
A station won't startConfirm the source is enabled on the HEOS account and that you're using a current source_id from get_music_sources — service ids can change per account/firmware.
  • Denon Receiver — Denon AVRs over the Telnet control protocol (a HEOS controller connected to the same receiver can lock out that Telnet session, so watch for it).
  • Marantz Receiver — the Marantz sibling of the receiver driver.
  • Sonos — the other major multi-room audio integration, for comparison of patterns.
  • AV Sources — set the Component and Device for the HEOS source view.
  • AV Zones — bind a player (Pattern B) as a zone's Volume Device.
  • Attributes — where you add the player_id / source_id attributes.