roku-smarthome
Control Roku Smart Home plugs and bulbs from Python. Read status, switch power, set brightness and color temperature, from a command line or as a library you drop into your own project.
Roku publishes no API for its Smart Home line, and the only integrations are Alexa and Google Assistant. This package talks to the same backend that Roku's own web app at my.roku.com/smarthome uses, with your own account session. No reverse-engineered mobile app login, no email verification codes, no soldering. Log in once and it stays logged in.
Not affiliated with or endorsed by Roku.
Developed and tested against the Roku Indoor Smart Plug SE (PS1000X) and the Roku Smart Bulb (BS1000X). Cameras show up in the device list with online state; video is out of scope.
What it can do
- List every device on your Roku Smart Home account with its state: power, online, brightness, color temperature
- Turn plugs and bulbs on and off
- Set bulb brightness (0 to 100) and white color temperature (2700K to 6500K on the tested bulb)
- Set RGB color on color bulbs (implemented from Roku's web app, untested on hardware; see notes)
- Send any other command a device advertises, via a generic escape hatch
- Keep itself logged in: Roku renews the session on every request and this client saves the renewed cookie, so the login never expires as long as you use it at least once a year
Install
pip install roku-smarthome
Or clone this repo and pip install . to build the exact package that's published to PyPI.
Requirements
- Python 3.9+
requestsandwebsockets(installed automatically by pip)
Setup
1. Copy your session cookie (once)
- Sign in at https://my.roku.com/smarthome in a desktop browser.
- Open DevTools (F12) and go to the Network tab. Type
leavesin the filter box and reload the page. - Click the
leavesrequest. In Headers, scroll down to Request Headers and copy the entire value of theCookieheader. (Right-click the request > Copy > "Copy as cURL" also works; the value is on the-H 'Cookie: ...'line.)
2. Save it
roku-smarthome login
Paste the cookie value when prompted. It's verified against your account and saved to a per-user file (%USERPROFILE%\.config\roku-smarthome\cookies.json on Windows, ~/.config/roku-smarthome/cookies.json on macOS/Linux). Set ROKU_SMARTHOME_COOKIES or pass --cookies PATH to use a different location.
Keep that file private. It is a working login to your Roku account. Don't share it, and don't paste the cookie into chat windows or bug reports. It's stored outside the project folder, so it can't be committed by accident.
3. Run
roku-smarthome status
Command line
roku-smarthome status # list devices and state
roku-smarthome on "Living room lamp"
roku-smarthome off "Living room lamp"
roku-smarthome toggle "Living room lamp"
roku-smarthome brightness "Bedroom bulb" 40 # 0-100
roku-smarthome temp "Bedroom bulb" 3000 # Kelvin
roku-smarthome rgb "Color bulb" 255 80 0 # color bulbs only, untested
roku-smarthome json # raw device list, for piping elsewhere
roku-smarthome --cookies PATH status # use a different cookie file
Device names are matched case-insensitively against the names in the Roku Smart Home app.
Use it as a library
from roku_smarthome import RokuSmartHome
rk = RokuSmartHome() # uses the default cookie file
for d in rk.devices():
print(d.name, d.type, d.power, d.online, d.brightness, d.color_temp)
lamp = rk.get("Living room lamp")
lamp.turn_on()
lamp.turn_off()
lamp.toggle()
print(lamp.is_on)
bulb = rk.get("Bedroom bulb")
bulb.set_brightness(40)
bulb.set_color_temp(3000)
bulb.set_color_rgb(255, 80, 0) # color bulbs only, untested
bulb.refresh() # re-fetch state from Roku
print(bulb.brightness, bulb.color_temp)
# anything else the device advertises in supportedCommands
bulb.send("color", {"colorType": "temperature", "temperature": 4000})
Device attributes: id, name, type (plug, light, camera), model, local_ip, power ("on"/"off"), online, brightness, color_temp, color_type, color_rgb, supported_commands, and raw (the untouched JSON).
Exceptions: SessionExpired (saved cookie no longer works; run login again), DeviceNotFound, and UnsupportedCommand (raised instead of silently sending a command the device doesn't list).
Keeping it logged in
Every request to Roku's API comes back with a re-issued session cookie carrying a fresh 365-day expiry. This client merges that cookie back into its file on every call. In practice: if anything uses this library at least once a year, the login is permanent. A daily cron entry like
0 9 * * * /path/to/venv/bin/roku-smarthome status > /dev/null
is enough on a machine that would otherwise sit idle.
Roku's sign-in page emails a verification code on every new login, which is why this package deliberately does not try to automate the email/password flow. Copying the cookie once is simpler and more reliable.
How it works
GET https://my.roku.com/smarthome/api/v1/leavesreturns every device ("leaf") with its current state.- Commands go over a websocket at
wss://aspen-sockets.aspen.msc.roku.com/v1/socketas{"id": ..., "type": "send_command", "payload": {"leafId": ..., "leafType": "device", "command": {"command": ..., "parameters": {...}}}}. - Known commands:
power {"power": "on"|"off"},brightness {"level": 0-100},color {"colorType": "temperature", "temperature": K},color {"colorType": "rgb", "rgb": [r, g, b]}. - Authentication is the
ks.sessioncookie from the browser, sent on both the REST call and the websocket handshake.
The Roku Smart Home line is Wyze hardware sold under the Roku brand, but the devices are registered to Roku's cloud, not Wyze's, so Wyze libraries can't log in to them. The earlier community effort (a 2022 fork of wyzeapy that reproduced the Roku mobile app's AWS Cognito login) stopped working when Roku removed that endpoint.
Notes and limitations
- Cloud only. The plugs have a local API on port 88 but it's encrypted with a key that only the Roku/Wyze login flow hands out. Local control would mean flashing ESPHome or Tasmota onto the ESP32 inside, which requires opening the device.
- Unofficial. Roku could change or remove these endpoints at any time. If
statusstarts failing with something other thanSESSION EXPIRED, that's probably what happened; please open an issue with the error (and the cookie value removed). - Cameras are listed with name and online state only. Streams, events and settings are visible in the API but not implemented here.
- RGB color is implemented but untested. I don't own a color bulb. The parameter shape (
{"colorType": "rgb", "rgb": [r, g, b]}, each 0 to 255) is taken directly from Roku's web app, so it should work. If you have a color bulb, please confirm in an issue either way. - Commands are fire-and-forget over the websocket. Call
refresh()if you need to confirm the new state.
Project layout
src/roku_smarthome/
__init__.py package entry, exports RokuSmartHome and Device
client.py the library: cookie handling, device list, commands
cli.py the command line
pyproject.toml packaging / build config
LICENSE MIT
Clone and pip install . to build exactly what's published to PyPI.
A note on how this was built
This started as "can I read my smart plug from Python," went through a dead 2022 library, a Windows DNS bug, and a login endpoint Roku had deleted, before landing on the web app's own API. Watching the network traffic on my.roku.com/smarthome showed that the device list included plugs and bulbs even though the page only displays cameras; from there the websocket command format came out of the web app's JavaScript, was confirmed on real hardware, and testing showed that Roku renews the session cookie on every request, which is what makes this usable long-term without any login automation.
I used AI assistance throughout: for digging through the minified web app, for the client and CLI code, and for this README. The testing on real devices, the decisions about what to build and what to leave out, and the packaging are mine.
Acknowledgements
Thanks to the people in the Home Assistant community thread who mapped the original Wyze/Roku relationship and the 2022 mobile-app login, and to wyze-sdk and wyzeapy for showing what the underlying hardware speaks.
Metadata
Release files for roku-smarthome 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| roku_smarthome-0.1.0.tar.gz | 14.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| roku_smarthome-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.3 kB
Release files / roku_smarthome-0.1.0.tar.gz
| Download URL | roku_smarthome-0.1.0.tar.gz |
|---|---|
| Size | 14.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e8b24a0f5e6b55fb33b6c6150dfd990b279cae109353bfd4b78bcdd24066639
|
|
BLAKE2b-256 checksum How to use checksums |
bd8f023e48a3e958c27d1056e2a0d79b760c1e9bf18cd809da58ad835f82bb55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.0
|
Release files / roku_smarthome-0.1.0-py3-none-any.whl
| Download URL | roku_smarthome-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4c70e2b835e2544aa4279a0144590e6118bb316be97ccca4b784d2a3acf4cfb8
|
|
BLAKE2b-256 checksum How to use checksums |
f766062c2fed8550c022a4fe264d76fae9095760abff051761d04a4ac9564c76
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.0
|