lgtv2mqtt

August 16, 2026 ยท View on GitHub

mqtt-smarthome NPM version CI License

Interface between LG webOS Smart TVs and MQTT ๐Ÿ“บ

Works with current TVs (2023+ firmware, wss:// on port 3001) as well as older models (ws:// on port 3000). Built on lgtv2.

Getting started

TV configuration

  • Enable LG Connect Apps (older models: Settings โ†’ Network; newer models: Settings โ†’ General โ†’ Devices โ†’ External Devices โ†’ LG Connect Apps / Mobile Device Connection).
  • For turning the TV on via Wake-on-LAN enable Mobile TV On / Turn on via Wi-Fi (Settings โ†’ General โ†’ Devices/Network) โ€” 2025+ models: Settings โ†’ Support โ†’ IP control settings โ†’ Wake on LAN. Wired connections are the most reliable.

Install and run

npm install -g lgtv2mqtt
lgtv2mqtt --tv 192.168.1.20 --mac aa:bb:cc:dd:ee:ff --mqtt-url mqtt://192.168.1.2

On first start the TV shows a pairing prompt โ€” accept it. The key is stored in ~/.lgtv2/ (override with --key-dir or LGTV2_KEY_DIR).

lgtv2mqtt --help lists all options; every option can also be set via an environment variable (LGTV2MQTT_TV, LGTV2MQTT_MAC, LGTV2MQTT_MQTT_URL, LGTV2MQTT_NAME, ...).

optiondefaultdescription
-t, --tvlgwebostvhostname or IP of the TV
--tv-portautopin 3001 (wss) or 3000 (ws); by default 3001 is tried first, then 3000
--tv-urlcomplete websocket URL (overrides --tv/--tv-port), e.g. behind a port forward
-m, --macMAC address of the TV, needed for set/power true (Wake-on-LAN)
--wol-address255.255.255.255broadcast address for the magic packets (use your subnet broadcast if the TV does not react)
--verify-certofflg (must be an LG TV), tofu (pin first seen certificate) or a SHA-256 fingerprint
--key-dir~/.lgtv2where the pairing key is stored
--raw-set / --no-raw-setonallow raw SSAP requests via set/<service>/<method> (see below)
-u, --mqtt-urlmqtt://localhostbroker URL, see MQTT.js
--mqtt-username, --mqtt-passwordbroker credentials
-n, --namelgtvinstance name, used as topic prefix
-v, --verbosityinfoerror, warn, info, debug

Docker

docker run -d --name lgtv2mqtt --network host -v lgtv2mqtt-data:/data \
  -e LGTV2MQTT_TV=192.168.1.20 -e LGTV2MQTT_MAC=aa:bb:cc:dd:ee:ff -e LGTV2MQTT_MQTT_URL=mqtt://192.168.1.2 \
  ghcr.io/hobbyquaker/lgtv2mqtt

--network host is needed for Wake-on-LAN broadcasts. The pairing key lives in /data.

Run as a systemd service

sudo lgtv2mqtt --install --name tv-living --tv 192.168.1.20 --mac aa:bb:cc:dd:ee:ff --mqtt-url mqtt://192.168.1.2

--install creates a system user lgtv2mqtt, writes the given options to /etc/lgtv2mqtt/<name>.env (LGTV2MQTT_* variables โ€” edit and systemctl restart lgtv2mqtt@<name> to change), installs the template unit /etc/systemd/system/lgtv2mqtt@.service and enables + starts lgtv2mqtt@<name>. The instance name is the --name option, i.e. the MQTT topic prefix. A pairing key that the invoking user already has in ~/.lgtv2/ is copied to /var/lib/lgtv2mqtt/<name>/; otherwise accept the prompt on the TV after the start (journalctl -u lgtv2mqtt@<name> -f).

Several TVs: run --install once per TV with a different --name โ€” each becomes its own instance lgtv2mqtt@<name> with its own config, key and topic prefix, all sharing one template unit and one system user:

sudo lgtv2mqtt --install --name tv-living  --tv 192.168.1.20 --mac ... --mqtt-url mqtt://broker
sudo lgtv2mqtt --install --name tv-bedroom --tv 192.168.1.21 --mac ... --mqtt-url mqtt://broker
systemctl status 'lgtv2mqtt@*'

sudo lgtv2mqtt --uninstall --name tv-bedroom removes one instance (the template unit goes with the last one; pairing keys are kept).

Topics

Topics and payloads follow the mqtt-smarthome architecture. set topics accept plain values or JSON {"val": ...}.

Published by lgtv2mqtt

topicpayload
lgtv/connected0 (lgtv2mqtt down), 1 (MQTT only), 2 (MQTT and TV connected). Retained.
lgtv/status/poweron, standby, screen_off, screen_saver, off. off is also set when the TV goes away.
lgtv/status/volume0..100
lgtv/status/mute1 / 0
lgtv/status/foregroundAppapp id, e.g. netflix, com.webos.app.livetv, com.webos.app.hdmi2
lgtv/status/currentChannelJSON {"val": <channelNumber>, "lgtv": {...}}, only while live TV is in the foreground
lgtv/status/playStateplaying, paused, loaded, stopped, ... of the foreground media app (newer firmware only)

Subscribed by lgtv2mqtt

topicpayload
lgtv/set/powertrue/1/on โ†’ Wake-on-LAN (needs --mac), false/0/off โ†’ turn off
lgtv/set/screentrue/false โ†’ screen on/off (audio keeps playing)
lgtv/set/volume0..100
lgtv/set/mutetrue/1/on or false/0/off
lgtv/set/toastmessage string, or JSON {"message": "...", "icon": "https://host/logo.png"} (icon: http(s) URL or local file, max 512 kB; or raw iconData base64 + iconExtension)
lgtv/set/launchapp id, or JSON {"id": "netflix", "contentId": "..."}
lgtv/set/youtubeYouTube video id
lgtv/set/buttonLEFT RIGHT UP DOWN ENTER BACK EXIT HOME MENU INFO DASH ASTERISK CC PLAY PAUSE STOP REWIND FASTFORWARD RED GREEN YELLOW BLUE VOLUMEUP VOLUMEDOWN MUTE CHANNELUP CHANNELDOWN 0-9
lgtv/set/move, lgtv/set/dragJSON {"dx": 100, "dy": 0} โ€” pointer movement
lgtv/set/scrollJSON {"dx": 0, "dy": 1}
lgtv/set/clickany
lgtv/set/<service>/<method>raw SSAP request, e.g. lgtv/set/media.controls/pause, lgtv/set/system/turnOff, lgtv/set/tv/switchInput {"inputId": "HDMI_2"}. Optional JSON payload. Disable with --no-raw-set.

Useful raw requests: media.controls/play|pause|stop|rewind|fastForward, tv/channelUp, tv/channelDown, tv/openChannel {"channelNumber": "1"}, tv/switchInput {"inputId": "HDMI_1"}, com.webos.service.apiadapter/audio/changeSoundOutput {"output": "external_arc"}, system.launcher/close {"id": "netflix"}. The full list is in the lgtv2 README.

Notes

  • The raw passthrough is an unrestricted remote control API: protect your broker with authentication/ACLs or disable it with --no-raw-set.
  • A TV in deep standby does not answer network requests at all; only Wake-on-LAN (set/power true) brings it back. After set/power false the connection drops a few seconds later and status/power becomes off.
  • The TV's TLS certificate is issued by LG's private CA and cannot be verified against public roots; by default it is not verified. --verify-cert lg checks that the certificate is LG's fleet-wide TV certificate, --verify-cert tofu pins whatever certificate is seen first.

License

MIT ยฉ Sebastian Raff