Skip to main content

Control UniFi Access Point LEDs via the internal REST API.

Project description

Socket Python Docker UniFi OS UniFi Network

image

Control UniFi Access Point LEDs via internal API — perfect for night mode scheduling and automation.

UniFi has never implemented a proper night mode scheduler for Access Points — despite users requesting it for years. This project fills that gap with a lightweight, reliable Python-based API that sends PUT requests to the internal REST API of the AP. Tested on U7 Pro and U6+.

[!NOTE]
Modern UniFi APs (U6/U7 series) support LED override ON/OFF only.
Color and brightness overrides are ignored by firmware.

Features

  • Turn device LEDs on or off programmatically
  • Auto-Discovery — finds all UniFi APs and checks LED toggle compatibility easily
  • Webhook API Server — built-in HTTP server explicitly designed to integrate with Node-RED, Home Assistant, etc.
  • Device Groups — create custom zones like upstairs or downstairs using groups.json
  • CLI Color & Brightness — supported on older models via --color and --brightness
  • Auto-config — device config is fetched live on every run, so payloads are never stale
  • Per-device payloads — each AP gets its own config files (led_on_{id}.json / led_off_{id}.json)
  • Multiple device support — control several APs with one command or webhook
  • LED status — check the current LED state without making changes
  • Dry-run mode — preview payloads before sending
  • Cross-platform config.env file works on Linux, macOS, and Windows
  • Works with UniFi OS and legacy controllers
  • Simple command-line interface with --help support
  • Suitable for cron jobs, automation, and Docker
  • Published Docker image on GitHub Container Registry

Why this does NOT use SSH

Many existing UniFi LED control solutions rely on SSH access to the access point and manual modification of LED-related settings or scripts.

⚠️ SSH-based approaches have been observed to cause firmware corruption and device instability, sometimes requiring recovery via TFTP.

UniFi access points are not designed for persistent or repeated SSH access. Running SSH-based automation can:

  • Increase CPU and memory usage on the AP
  • Interfere with UniFi's internal configuration management
  • Cause device instability, reprovisioning loops, or unexpected reboots
  • Break silently after firmware updates

This project avoids SSH entirely and instead uses the same internal REST API mechanism the UniFi controller itself uses to manage device configuration. As a result, it is significantly more stable, safer, and closer to how UniFi intended devices to be managed. This makes it suitable for long-term automation, cron jobs, and unattended operation.

Requirements

  • Python 3.9+
  • aiohttp library (installed automatically)
  • A UniFi Controller with API access
  • A local UniFi user account (no 2FA)

Installation

With PyPI (Recommended)

pip install unifi-led-api

This gives you access to the global unifi-led command.

From Source / Development

  1. Clone this repository:

    git clone https://github.com/elNino0916/unifi-led-api.git
    cd unifi-led-api
    
  2. Install dependencies:

    pip install -e ".[dev]"
    

With Docker

docker pull ghcr.io/elnino0916/unifi-led-api:main

Or build locally:

docker build -t unifi-led-api .

Configuration

  1. Copy the example env file and fill in your values:
    cp .env.example .env
    
  2. Edit .env with your controller IP, credentials, and device ID(s).

That's it — you're ready to go. The tool fetches your device config automatically on every run.

Finding your device ID

Your device ID is in the UniFi controller URL when viewing a device:

https://<controller-ip>/network/default/devices/properties/device/<DEVICE_ID>/general

[!TIP] If you enter a wrong device ID, the error message will list all available devices with their names and IDs.

Environment variables

Variable Required Default Description
UNIFI_USER Yes Local UniFi username (no 2FA)
UNIFI_PASS Yes UniFi password
UNIFI_CONTROLLER Yes Controller URL (e.g. https://192.168.1.1)
UNIFI_DEVICE_ID Yes Device ID (comma-separated for multiple)
UNIFI_SITE No default UniFi site name
UNIFI_VERIFY_SSL No false Set to true for valid SSL certs
UNIFI_TIMEOUT No 10 HTTP request timeout in seconds

Targeting Devices and Groups

You can define devices in the .env file via a comma-separated list:

UNIFI_DEVICE_ID=device_id_1,device_id_2,device_id_3

Each device gets its own per-device config files and all are updated in a single run.

Using Device Groups: Create a groups.json file in the root directory (see groups.json.example) to group IDs by name:

{
  "upstairs": ["device_id_1", "device_id_2"],
  "downstairs": ["device_id_3"]
}

You can then run commands targeting only that group by placing the global --group argument before the sub-command:

unifi-led --group upstairs led on

Specific Device Overrides: Similarly, you can override the target device list entirely by passing the global --device argument before the sub-command:

unifi-led --device device_id_3 led off

Usage

Interactive Setup

The easiest way to configure the project is with the built-in interactive wizard. It will prompt for your credentials, discover all connected devices, and let you select which ones to control.

unifi-led setup

Once completed, a .env file will be generated automatically in your current directory.

Commands Overview

unifi-led --help
unifi-led led --help
unifi-led status --help
unifi-led discover --help
unifi-led serve --help
unifi-led setup --help
unifi-led fetch-config --help

Turn LED On

unifi-led led on

For older supported access points, you can also pass a hex color and brightness percentage:

unifi-led led on --color "#0000ff" --brightness 50

Turn LED Off

unifi-led led off

[!NOTE] Every led on/off command automatically fetches the latest device config before pushing. This means config files are always up-to-date — no manual regeneration needed after firmware updates or config changes.

Preview payload (dry-run)

unifi-led led on --dry-run

Shows the JSON payload that would be sent, without actually making any changes. Useful for debugging and first-time verification.

Auto-Discovery

unifi-led discover

Finds all devices connected to the UniFi controller and lists their names, MAC addresses, models, and device IDs. It also includes a compatibility check table to show you if your firmware natively supports LED toggling.

Check LED status

unifi-led status

Displays the current led_override state for each targeted device. No changes are made.

Webhook API Server

Start a lightweight HTTP server to listen for webhooks. This is perfect for integrating UniFi LEDs with Node-RED, Home Assistant, or other platforms without invoking the CLI every time.

unifi-led serve --port 8080

You can then control devices with HTTP GET or POST requests:

  • Turns on LEDs for .env configured devices: http://localhost:8080/led/on
  • Using query parameters for groups and overrides: http://localhost:8080/led/off?group=upstairs or http://localhost:8080/led/on?device=id1,id2
  • Using color and brightness: http://localhost:8080/led/on?color=%23ff0000&brightness=100

Preview config without changing LEDs

unifi-led fetch-config

This fetches the device config and generates the JSON payload files without making any changes. Useful for inspecting what will be sent.

Cron Example

Turn off LEDs every night at 10 PM:

0 22 * * * cd /path/to/my/env_folder && unifi-led led off

Turn on LEDs every morning at 7 AM:

0 7 * * * cd /path/to/my/env_folder && unifi-led led on

[!TIP] The .env file is loaded automatically — no extra setup needed in cron.

Docker

# Turn LEDs off
docker run --rm --env-file .env ghcr.io/elnino0916/unifi-led-api:main led off

# Turn LEDs on
docker run --rm --env-file .env ghcr.io/elnino0916/unifi-led-api:main led on

# Check LED status
docker run --rm --env-file .env ghcr.io/elnino0916/unifi-led-api:main status

# Preview payload (dry-run)
docker run --rm --env-file .env ghcr.io/elnino0916/unifi-led-api:main led on --dry-run

# Preview config
docker run --rm --env-file .env -v $(pwd):/app ghcr.io/elnino0916/unifi-led-api:main fetch-config

Docker cron example:

0 22 * * * docker run --rm --env-file /path/to/.env ghcr.io/elnino0916/unifi-led-api:main led off
0 7  * * * docker run --rm --env-file /path/to/.env ghcr.io/elnino0916/unifi-led-api:main led on

Docker Compose (automated scheduling)

A docker-compose.yml is included that uses ofelia for cron-based scheduling:

docker compose up -d

By default, LEDs turn off at 22:00 and on at 07:00. Customize the schedules via environment variables:

CRON_LED_OFF="0 0 23 * * *" CRON_LED_ON="0 0 6 * * *" docker compose up -d

LED Payload Files

Config files are generated per-device as led_on_{device_id}.json and led_off_{device_id}.json.

These are auto-generated on every run from your live device config. You generally don't need to touch them, but they're written to disk so you can inspect exactly what gets sent.

If customizing manually:

  • led_override: "on" or "off"
  • led_override_color: LED color in hex format (e.g., "#0000ff") (Only older APs)
  • led_override_color_brightness: Brightness percentage (e.g., "100") (Only on some newer APs if it even works in the first place.)

[!CAUTION]
Do NOT modify anything in the JSON files except the LED fields.
Changing other values can break your device configuration.

Troubleshooting

Authentication Issues

  • Ensure you're using a local UniFi account, not a Ubiquiti cloud account
  • The account should not have 2FA enabled
  • Check that the controller URL is correct and accessible

SSL Certificate Errors

If you're using a self-signed certificate, set UNIFI_VERIFY_SSL=false

CSRF Token Errors

The API automatically handles CSRF tokens. If you encounter issues, ensure your controller is running a compatible version.

License

This project is provided under the MIT License.

Disclaimer

This project is an unofficial tool and is not affiliated with, endorsed by, or supported by Ubiquiti Inc. or any of its subsidiaries in any way. This software interacts with internal and undocumented UniFi controller and access point APIs, which are subject to change without notice. As a result, functionality may break at any time due to firmware updates, controller updates, configuration changes, or other modifications made by Ubiquiti. Use this tool only if you understand what it does and have verified it in a safe or non-production environment first. If you are unsure whether this tool is appropriate for your setup, do not use it.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unifi_led_api-0.2.2.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unifi_led_api-0.2.2-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file unifi_led_api-0.2.2.tar.gz.

File metadata

  • Download URL: unifi_led_api-0.2.2.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for unifi_led_api-0.2.2.tar.gz
Algorithm Hash digest
SHA256 a75c157bb2bf78ea41c4f4207bb0c9f80b1680be9ef2ff48922a9e1a4f029062
MD5 e96e08e0735301236cd2aaf48f511f7c
BLAKE2b-256 ce480596ef6725f2a4592364cbaff6c7688581b64d90637134c7c30fa91eec0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for unifi_led_api-0.2.2.tar.gz:

Publisher: publish.yml on elNino0916/unifi-led-api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file unifi_led_api-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: unifi_led_api-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 18.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for unifi_led_api-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1c8bc11a41c52ee121abca73ec3dcb077d92a39045449e50202dd06a8f1f6caa
MD5 08b9955a3b02fa59c149090e25f4ae40
BLAKE2b-256 02d674dd4d408a9c963180ccd9e468dcb99356eb6b97e5b726b6952571296e70

See more details on using hashes here.

Provenance

The following attestation bundles were made for unifi_led_api-0.2.2-py3-none-any.whl:

Publisher: publish.yml on elNino0916/unifi-led-api

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page