Getting started


The library is fully async and methods that perform IO need to be run inside an async coroutine. Code examples assume you are following them inside asyncio REPL:

    $ python -m asyncio

Or the code is running inside an async function:

import asyncio
from kasa import Discover

async def main():
    dev = await Discover.discover_single("",username="",password="pw")
    await dev.turn_on()
    await dev.update()

if __name__ == "__main__":

All of your code needs to run inside the same event loop so only call once.

The main entry point for the API is discover() and discover_single() which return Device objects. Most newer devices require your TP-Link cloud username and password, but this can be omitted for older devices.

>>> from kasa import Discover

discover() returns a dict[str,Device] of devices on your network:

>>> devices = await"", password="great_password")
>>> for dev in devices.values():
>>>     await dev.update()
>>>     print(

discover_single() returns a single device by hostname:

>>> dev = await Discover.discover_single("", username="", password="great_password")
>>> await dev.update()
>>> dev.alias
Living Room Bulb
>>> dev.model
>>> dev.rssi
>>> dev.mac

You can update devices by calling different methods (e.g., set_-prefixed ones). Note, that these do not update the internal state, but you need to call update() to query the device again. back to the device.

>>> await dev.set_alias("Dining Room")
>>> await dev.update()
>>> dev.alias
Dining Room

Different groups of functionality are supported by modules which you can access via modules with a typed key from Module.

Modules will only be available on the device if they are supported but some individual features of a module may not be available for your device. You can check the availability using is_-prefixed properties like is_color.

>>> from kasa import Module
>>> Module.Light in dev.modules
>>> light = dev.modules[Module.Light]
>>> light.brightness
>>> await light.set_brightness(50)
>>> await dev.update()
>>> light.brightness
>>> light.is_color
>>> if light.is_color:
>>>     print(light.hsv)
HSV(hue=0, saturation=100, value=50)

You can test if a module is supported by using get to access it.

>>> if effect := dev.modules.get(Module.LightEffect):
>>>     print(effect.effect)
>>>     print(effect.effect_list)
>>> if effect := dev.modules.get(Module.LightEffect):
>>>     await effect.set_effect("Party")
>>>     await dev.update()
>>>     print(effect.effect)
['Off', 'Party', 'Relax']

Individual pieces of functionality are also exposed via features which you can access via features and will only be present if they are supported.

Features are similar to modules in that they provide functionality that may or may not be present.

Whereas modules group functionality into a common interface, features expose a single function that may or may not be part of a module.

The advantage of features is that they have a simple common interface of id, name, value and set_value so no need to learn the module API.

They are useful if you want write code that dynamically adapts as new features are added to the API.

>>> if auto_update := dev.features.get("auto_update_enabled"):
>>>     print(auto_update.value)
>>> if auto_update:
>>>     await auto_update.set_value(True)
>>>     await dev.update()
>>>     print(auto_update.value)
>>> for feat in dev.features.values():
>>>     print(f"{}: {feat.value}")
Device ID: 0000000000000000000000000000000000000000
State: True
Signal Level: 2
RSSI: -52
Overheated: False
Brightness: 50
Cloud connection: True
HSV: HSV(hue=0, saturation=100, value=50)
Color temperature: 2700
Auto update enabled: True
Update available: False
Current firmware version: 1.1.6 Build 240130 Rel.173828
Available firmware version: 1.1.6 Build 240130 Rel.173828
Light effect: Party
Light preset: Light preset 1
Smooth transition on: 2
Smooth transition off: 2
Device time: 2024-02-23 02:40:15+01:00