Skip to main content

remnawave-client

Sync and async client for the Remnawave API, generated from the panel's OpenAPI specification.

pip install remnawave-client

Requires Python 3.11 or newer.

Versions

The first three numbers of the library version are the panel version it was generated from; a fourth one counts the library's own releases on top of it. 1.2.3 is the first release for panel 1.2.3, 1.2.3.1 and 1.2.3.2 bring fixes and features of the library itself while the API stays the same.

A release exists for every minor version of the panel from 2.0 onwards. Pin the panel version you run and let the fourth number float, so library fixes still arrive:

pip install "remnawave-client==1.2.3.*"

Quick start

from remnawave import Remnawave

with Remnawave("https://panel.example.com", token) as rw:
    user = rw.users.get_user_by_username("zen")
    print(user.username, user.status, user.expire_at)

    for u in rw.users.iter_users():
        print(u.username)

The async client mirrors it:

import asyncio

from remnawave import AsyncRemnawave

async def main() -> None:
    async with AsyncRemnawave("https://panel.example.com", token) as rw:
        stats = await rw.system.get_stats()
        nodes = await rw.nodes.get_nodes()
        async for user in rw.users.iter_users():
            print(user.username)

asyncio.run(main())

More in examples/: pagination, partial updates, error handling, webhooks and swapping out the client's parts.

Background jobs

Some checks run as panel jobs: one request starts the job and returns a jobId, another polls its status. wait_* does both and returns the result:

result = rw.connections.wait_connections_by_user(user_id, timeout=120)
for node in result.nodes:
    print(node.node_name, [ip.ip for ip in node.ips])

A job the panel reports as failed raises JobFailedError; one still running after timeout seconds raises JobTimeoutError. The underlying start and poll methods stay available.

Errors

Everything the library raises inherits from RemnawaveError. Below it the hierarchy splits by cause: ApiError for anything the panel answered with, TransportError when the request never got a reply, SerializationError when the payload did not match the schema.

from remnawave.exceptions import NotFoundError

try:
    rw.users.get_user_by_id(42)
except NotFoundError as error:
    print(error.status, error.error_code)  # 404 'A025'

error_code is the panel's own code and is more specific than the HTTP status — branch on it when you need to tell cases apart.

Webhooks

from remnawave.webhooks import SIGNATURE_HEADER, WebhookReceiver

hooks = WebhookReceiver(secret=os.environ["WEBHOOK_SECRET_HEADER"])
event = hooks.receive(request.body, request.headers[SIGNATURE_HEADER])

if event.scope == "user":
    print(event.event, event.data.username)

Pass the raw request body: the signature covers those exact bytes, so re-serialising parsed JSON breaks verification.

Redis streams

With EXPORT_TO_STREAM_ENABLED=true the panel exports per-user traffic, subscription requests and node connections to Redis streams. Install the streams extra and read them through a consumer group on the panel's Redis:

pip install "remnawave-client[streams]"
from redis import Redis
from remnawave.streams.redis import RedisStreams

streams = RedisStreams(Redis(), group="billing")
usage = streams.user_usage()

for entry in usage:
    for record in entry.message.records:
        print(entry.message.node_id, record.user_id, record.total_bytes)
    usage.ack(entry)

user_usage(), subscription_requests() and node_connections() each return a consumer of one stream; AsyncRedisStreams does the same over a redis.asyncio.Redis. Every service needs a group of its own: consumers sharing a group split the messages between them. Several workers of one service share a group and pass distinct names; a single worker can leave the default. The group is created on the first read and starts at the end of the stream (start_id="0" reads what the panel still keeps). Delivery is at-least-once: an entry stays pending until acknowledged and is delivered again after a restart. A message that does not parse raises StreamMessageError; acknowledge its entry_id to skip it. With auto_ack=True a batch is acknowledged when the next read() starts, so iterating acknowledges whatever the loop body got through; the batch in hand when the process dies comes back after a restart. The panel trims the streams (EXPORT_TO_STREAM_MAXLEN, one hour for node connections), so a consumer that falls behind loses entries.

Without a consumer, USER_USAGE.parse(fields) from remnawave.streams.stream turns the fields of one stream entry into a message.

Regenerating

src/remnawave/_generated/ is machine-written and must not be edited by hand. Regenerating it against the version the package declares takes no arguments:

python -m tools.codegen

To move the project onto a newer panel release, drop its specification into specs/ and pass the version once:

python -m tools.codegen <version>

Where the specification is wrong or awkward, overlay.yaml patches it before generation: type names, forced field types, fields kept out of repr. Editing the generated code directly would be lost on the next run; editing the vendored specification would be lost on the next update.

Metadata

Release files for remnawave-client 3.4.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for remnawave-client 3.4.6
File Size Uploaded Provenance
remnawave_client-3.4.6.tar.gz 49.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for remnawave-client 3.4.6
File Interpreter ABI Platform
remnawave_client-3.4.6-py3-none-any.whl Python 3 none any Details

Total release size: 121.4 kB

Release files / remnawave_client-3.4.6.tar.gz

Download URL remnawave_client-3.4.6.tar.gz
Size 49.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2118ad49b499bbe090ac1d236d801dccc02ed3dbb1bff7749af89e108c1b4d02
BLAKE2b-256 checksum
How to use checksums
1eb6a87d27c0356ee59b3afffd0c8152b09389ea0dd9432c2b2409d62ba4582b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / remnawave_client-3.4.6-py3-none-any.whl

Download URL remnawave_client-3.4.6-py3-none-any.whl
Size 71.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9bb454200d7cbe76145ca5388b82d7bb818086a9c5abbcc0dd22dea1b61e02ae
BLAKE2b-256 checksum
How to use checksums
23ef225ea6a3ef670ecd59abd9cf5d389dbc0015da074fdaa7837431dab2e0cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for remnawave-client 3.4.6

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page