npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

scrypted-kasa

v1.3.1

Published

TP-Link Kasa plugin for Scrypted — cameras (video, two-way audio, spotlight, siren, status LED), plugs/outlets, wall switches, dimmers, and smart bulbs (on/off, brightness, color, color temperature).

Readme

scrypted-kasa

npm version License: MIT

Adds support for the TP-Link Kasa device family to Scrypted: cameras, plugs/outlets, switches/dimmers, and bulbs. Discovery is unified — one UDP/9999 sweep finds everything and the plugin routes each device to the right Scrypted interfaces.

Installation

In Scrypted:

  1. Open the Plugins page.
  2. Choose Install and enter scrypted-kasa.
  3. The plugin appears as Kasa Plugin in the device list — see Setup below.

Cameras

  • Reads the camera's proprietary multipart stream (HTTPS port 19443, /https/stream/mixed) and re-streams H.264 video + G.711 µ-law audio over local RTSP for Scrypted, HomeKit, the NVR, etc.
  • Streams talk audio back to the camera's speaker via the camera's separate uplink endpoint (HTTPS port 18443, /https/speaker/audio/g711block) — usable from HomeKit and any other Scrypted client that supports two-way audio.
  • Exposes the camera's spotlight (when present, e.g. KC420WS) as an OnOff child light device in the same room as the camera. Driven by the LINKIE2 control protocol on port 10443.
  • Exposes the camera's siren (when present) as an OnOff child switch device, also in the camera's room. Triggering it turns the siren on; the camera auto-stops after the duration configured in the Kasa app (default 30 s).
  • Exposes the camera's status LED as the camera's own OnOff interface, so HomeKit's per-camera "Link Status Indicator" toggle drives the LED.

Plugs / Switches / Dimmers / Bulbs (legacy IOT protocol)

Each device class is its own implementation, descended from a shared KasaIotDevice base that holds the relay protocol:

  • KasaPlug — plain plugs/outlets (HS100/HS103/HS105/HS107/HS110/KP100/...). OnOff, ScryptedDeviceType.Outlet.
  • KasaSwitch — plain wall switches (HS200/HS210/KS200/...). OnOff, ScryptedDeviceType.Switch.
  • KasaDimmer — dimmer plugs and switches (HS220 plug, KS230 3-way switch). OnOff + Brightness, ScryptedDeviceType.Light (dimmable devices are exposed as lights since they're almost always wired to a light fixture, matching the Kasa app's UX).
  • KasaBulb — smart bulbs (LB1xx, KL1xx). OnOff + Brightness, plus ColorSettingHsv for color bulbs and ColorSettingTemperature for variable-temperature bulbs.

Multi-outlet plug strips (HS300, KP303) aren't modeled yet — discovery skips them.

Stream protocol described in go2rtc's pkg/kasa; camera control protocols (LINKIE2, talk endpoint, status LED) modeled after the official Kasa iOS app's network traffic. The plug/bulb/switch protocol is the well-documented legacy "smarthome" TCP/9999 wire format.

Tested camera models: KD110, KC200, KC401, KC420WS, EC71.

Setup

Auto-discovery (recommended)

  1. Install the plugin.
  2. Open the plugin's page and click Discover Devices. Discovery runs only when you click the button — there are no background scans.
  3. Every LAN-visible Kasa device appears in the list — cameras, plugs, switches, dimmers, and bulbs are all discovered together.
  4. For each device you want to adopt, fill in the adoption form and click adopt:
    • Name — pre-filled with the device's alias or model; edit to taste.
    • Room — optional, picked from a dropdown of rooms already in use by other Scrypted devices, or type a new one.
    • Username / Password (cameras only) — your Kasa account email and password. After the first camera is configured these are pre-populated from any other Kasa camera in Scrypted.

Adopted devices get their IP, port, name, model, MAC, serial number, and firmware version populated automatically. The manufacturer is reported as TP-Link Kasa.

Discovery sends a single UDP/9999 burst on each connected /24:

  • A broadcast of the IOT.SMARTHOME get_sysinfo query.
  • A paced unicast of the same query at every IP on the subnet (~3 ms between sends). Newer firmwares (e.g. KC420WS cameras) drop broadcast probes but still answer when the packet is addressed directly. Pacing keeps the kernel/network from coalescing or dropping the burst.

If a device is on a different VLAN/broadcast domain or a non-/24 subnet, use the manual setup below.

Manual setup

  1. Install the plugin.
  2. Use Add Device to create a new device. The Add form takes:
    • Type — Camera, Plug, Switch, Dimmer, or Bulb.
    • Name — required.
    • Room — optional, with the same dropdown of existing rooms as the discovery flow.
  3. After creation, open the device's settings and fill in:
    • IP Address of the device on your LAN
    • Port (default 19443 for cameras, 9999 for everything else)
    • For cameras: Username + Password (your Kasa account email + password)

How it works

Receive (camera → Scrypted)

  • The plugin opens a single HTTPS connection to the camera on port 19443 and parses the multipart/x-mixed-replace body, splitting it into video parts (video/x-h264, annex-b) and audio parts (audio/g711u).
  • It scans the first H.264 frames for SPS (NAL 7) and PPS (NAL 8) and inlines them into the locally served SDP as sprop-parameter-sets + profile-level-id. This lets short -timeout consumers (HomeKit, browser players) pick up the codec immediately.
  • It then runs ffmpeg in codec-copy mode, re-packetizing the raw H.264 and G.711 µ-law streams as RTP into a local RTSP server that Scrypted reads from.

Talk (Scrypted → camera speaker)

  • When a client engages two-way audio, the plugin opens a long-lived chunked POST to https://<ip>:18443/https/speaker/audio/g711block and ffmpeg-transcodes the client's audio to 8 kHz mono G.711 µ-law.
  • Each 20 ms (160 byte) audio block is wrapped in a multipart/x-mixed-replace part with Content-Type: audio/g711u and streamed to the camera. Empty audio/heartbeat parts are sent every 3 s during silence to keep the connection alive — same pattern the Kasa app uses.

Spotlight / control plane

  • The Kasa app talks to the camera's "LINKIE2" RPC on port 10443 for non-streaming features. Wire format: HTTPS POST /data/LINKIE2.json, body application/x-www-form- urlencoded with a single content=<base64(xor_ab(json))> field. The XOR-AB autokey cipher is the same one used by Kasa's UDP/9999 discovery protocol.
  • On adoption (and whenever credentials change) the plugin probes three LINKIE2 endpoints serially:
    • smartlife.cam.ipcamera.dayNight.get_force_lamp_state — if it returns on/off, a child OnOff light device named " Spotlight" is registered in the camera's room.
    • smartlife.cam.ipcamera.siren.get_state — same pattern; produces a " Siren" switch child device.
    • smartlife.cam.ipcamera.led.get_status — drives the camera's own OnOff so HomeKit can bind its CameraOperatingModeIndicator (a.k.a. "Status Light") characteristic to it. Enable Link Status Indicator in the HomeKit plugin's per-camera settings to activate the binding.
  • Toggling any of the three calls the matching set_* method with {"value": "on"|"off"}.

Notes / limitations

  • Authentication uses the cloud account password. All three endpoints take Basic auth with the plain Kasa email as the username; the password format differs by endpoint — receive uses base64(plaintext), talk and LINKIE2 use md5_hex(plaintext). The plugin uses each in the right place.
  • LINKIE2 requests must include a User-Agent: Kasa/... header and the Authorization header on the very first request — the camera silently drops requests that don't look enough like the official app.
  • The camera presents a self-signed TLS certificate; certificate verification is disabled.
  • Auto-discovery sweeps the local /24 only. Larger subnets (e.g. /23) are skipped to avoid flooding.

Development

git clone https://github.com/sv-tools/scrypted-kasa-plugin.git
cd scrypted-kasa-plugin
npm install

Common scripts:

| Command | Purpose | |---|---| | npm run build | Webpack bundle into out/main.nodejs.js (+ plugin.zip) | | npm run fmt | Format src/**/*.ts with prettier | | npm run fmt:check | Verify formatting — what CI runs | | npm run lint | ESLint | | npm run lint:fix | ESLint with auto-fix | | npm run scrypted-deploy <host> | Build and deploy to a Scrypted server |

CI on every PR runs fmt:check, lint, and build. Releases publish to npm automatically when a v* tag is pushed (e.g. git tag v1.2.3 && git push --tags). The publish workflow signs the package with npm provenance via GitHub OIDC.

License

MIT — see LICENSE.