API client and CLI for the ASUS ROG Strix GS-BE18000 router
Project description
bs-be18000
A Python client and CLI for the ASUS ROG Strix GS-BE18000 router's web API.
Background
This router has no published public API. Like all AsusWRT-powered routers, it exposes the same HTTP(S) JSON API that its own web UI uses to talk to it. The login flow and hook query mechanism below have been confirmed against a real GS-BE18000 (firmware nonce-based login, packet-captured to verify the exact request/response shapes):
- Login is a nonce/cnonce challenge, not plain base64(user:pass):
POST get_Nonce.cgiwith{"id": <random>}to get anonce, thenPOST login_v2.cgiwithlogin_authorization = sha256("user:nonce:password:cnonce")plus a handful of other form fields. On success the session token comes back as aSet-Cookie: asus_token=...header (not a JSON body) —httpx's cookie jar picks this up automatically. - Reading state is
GET appGet.cgi?hook=<fn1>(<args1>);<fn2>(<args2>);...— e.g.nvram_get(productid);nvram_get(firmver);get_clientlist();. Confirmed working:nvram_getfor NVRAM values andget_clientlistfor connected devices. Notenvram_getonly ever takes one variable per call — fetching several means chaining severalnvram_get(...)calls in one request, not comma-joining variable names into a single call. - Settings/actions go through
POST applyapp.cgiwithrc_service=<name>— this part is still based on general AsusWRT convention rather than a packet capture (we haven't triggered a real settings change to confirm it), so treatrun_service/reboot/restart_wirelessas less-verified than the read path above.
The handful of high-level convenience methods (get_device_info, get_wan_status,
get_clients) use NVRAM keys that are either confirmed above or have been stable across AsusWRT
firmware for years, and have been verified end-to-end against a real GS-BE18000. Note that
WanStatus.state is the raw wan0_state_t NVRAM code (e.g. "2"), not decoded into a label —
cross-reference it against the WAN status shown in the router's own web UI if you need to know
what a given code means, since guessing at that mapping risked getting it wrong. If a value comes
back empty on your unit, open the router's web UI, watch the Network tab while it loads the
relevant page, and adjust the key/hook name accordingly — or just
call query_hooks/get_nvram directly with the right name.
Install
For development (installs into the project's own .venv):
uv sync
To use the bs-be18000 CLI as a standalone command from anywhere (installs to ~/.local/bin
via uv tool, in editable mode so it tracks source changes):
make install # or: uv tool install --editable .
Library usage
from bs_be18000 import RouterClient
with RouterClient("192.168.1.1", "admin", "hunter2") as router:
print(router.get_device_info())
print(router.get_wan_status())
for client in router.get_clients():
print(client)
Escape hatches for anything not wrapped above:
router.get_nvram("wl0_ssid", "wl1_ssid")
router.query_hooks([("nvram_get", "productid"), ("get_clientlist", "")])
router.run_service("restart_qos")
CLI usage
Credentials resolve from flags, then environment variables, then an interactive password prompt — nothing is ever written to disk. Set all three env vars once per shell session and every command below just works, with no re-entering the password each time:
export BS_BE18000_HOST=192.168.1.1
export BS_BE18000_USERNAME=admin
export BS_BE18000_PASSWORD=hunter2 # leading space keeps it out of shell history
# (bash/zsh with HISTCONTROL=ignorespace or
# HIST_IGNORE_SPACE set)
bs-be18000 device info
bs-be18000 wan status
bs-be18000 clients list
bs-be18000 nvram get productid firmver
bs-be18000 system reboot
bs-be18000 --json device info # machine-readable output
Run bs-be18000 --help or bs-be18000 <command> --help for the full command tree.
Development
uv run pytest # unit tests, router HTTP calls mocked with respx
uv run ruff check .
uv run mypy src tests
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bs_be18000-0.1.0.tar.gz.
File metadata
- Download URL: bs_be18000-0.1.0.tar.gz
- Upload date:
- Size: 30.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d72213ec087b14cf2bd049f39f0253d96d234cc98b690c32bd4a35f3871872c
|
|
| MD5 |
da6f9c7e71f18b0cbe64c168296d609f
|
|
| BLAKE2b-256 |
ce04de6d83f92fa8b93b5af11f322e0968b1571f060b5c87618d2944c284d791
|
Provenance
The following attestation bundles were made for bs_be18000-0.1.0.tar.gz:
Publisher:
publish.yml on baconismycopilot/bs-be18000
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bs_be18000-0.1.0.tar.gz -
Subject digest:
9d72213ec087b14cf2bd049f39f0253d96d234cc98b690c32bd4a35f3871872c - Sigstore transparency entry: 2153733676
- Sigstore integration time:
-
Permalink:
baconismycopilot/bs-be18000@ef51b90c708f5b1473efddda9b42f2e04a31c95c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/baconismycopilot
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ef51b90c708f5b1473efddda9b42f2e04a31c95c -
Trigger Event:
push
-
Statement type:
File details
Details for the file bs_be18000-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bs_be18000-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3a35d03ee6bc8710638df681b5d868b368a6cadb9da01e73c4fc76a7934e2d0
|
|
| MD5 |
b5af2a4cabb77a4788f65060ac53198a
|
|
| BLAKE2b-256 |
fc716ad00e31a2c07e7f5e2d8a3cdaeaf6b3a20b1de60c49ee94db2d07c83121
|
Provenance
The following attestation bundles were made for bs_be18000-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on baconismycopilot/bs-be18000
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bs_be18000-0.1.0-py3-none-any.whl -
Subject digest:
a3a35d03ee6bc8710638df681b5d868b368a6cadb9da01e73c4fc76a7934e2d0 - Sigstore transparency entry: 2153733837
- Sigstore integration time:
-
Permalink:
baconismycopilot/bs-be18000@ef51b90c708f5b1473efddda9b42f2e04a31c95c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/baconismycopilot
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ef51b90c708f5b1473efddda9b42f2e04a31c95c -
Trigger Event:
push
-
Statement type: