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
Metadata
Release files for bs-be18000 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 | Provenance | |
|---|---|---|---|---|
| bs_be18000-0.1.0.tar.gz | 30.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bs_be18000-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.9 kB
Release files / bs_be18000-0.1.0.tar.gz
| Download URL | bs_be18000-0.1.0.tar.gz |
|---|---|
| Size | 30.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9d72213ec087b14cf2bd049f39f0253d96d234cc98b690c32bd4a35f3871872c
|
|
BLAKE2b-256 checksum How to use checksums |
ce04de6d83f92fa8b93b5af11f322e0968b1571f060b5c87618d2944c284d791
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency logRelease files / bs_be18000-0.1.0-py3-none-any.whl
| Download URL | bs_be18000-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a3a35d03ee6bc8710638df681b5d868b368a6cadb9da01e73c4fc76a7934e2d0
|
|
BLAKE2b-256 checksum How to use checksums |
fc716ad00e31a2c07e7f5e2d8a3cdaeaf6b3a20b1de60c49ee94db2d07c83121
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency logSecurity for bs-be18000 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for bs_be18000-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.