This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 2.0.1 instead.
x3ui
Typed Python client for the 3x-ui panel API, generated from OpenAPI.
Unofficial project. Not affiliated with the 3x-ui developers.
Installation
pip install x3ui
Requires Python 3.9+.
Quick start
from x3ui import AuthenticatedClient
from x3ui.api.inbounds import get_panel_api_inbounds_list
client = AuthenticatedClient(base_url="https://panel.example.com:2053", token="YOUR_API_TOKEN")
result = get_panel_api_inbounds_list.sync(client=client)
print(result.success, result.obj)
Base URL must include the port and the panel's base path if you configured one, for example https://panel.example.com:2053/mypath.
Authentication
The panel supports two schemes.
API token (recommended)
Create a token in the panel UI under Settings, or through the API, then pass it to AuthenticatedClient. Requests are sent with an Authorization: Bearer <token> header.
from x3ui import AuthenticatedClient
client = AuthenticatedClient(base_url="https://panel.example.com:2053", token="YOUR_API_TOKEN")
Creating a token programmatically:
from x3ui.api.api_tokens import post_panel_api_setting_api_tokens_create
from x3ui.models.post_panel_api_setting_api_tokens_create_body import PostPanelApiSettingApiTokensCreateBody
body = PostPanelApiSettingApiTokensCreateBody(name="automation", scope="admin", expires_at=0)
result = post_panel_api_setting_api_tokens_create.sync(client=client, body=body)
expires_at is a Unix timestamp; 0 means no expiry.
Session cookie
from x3ui import Client
from x3ui.api.authentication import post_login
from x3ui.models.post_login_body import PostLoginBody
client = Client(base_url="https://panel.example.com:2053")
response = post_login.sync_detailed(
client=client,
body=PostLoginBody(username="admin", password="admin", two_factor_code=""),
)
client = client.with_cookies({"3x-ui": response.cookies.get("3x-ui")})
Pass an empty string as two_factor_code when 2FA is disabled. The session cookie is not stored automatically: Client is immutable, so with_cookies returns a new instance that you need to keep and reuse.
Common operations
List all clients
from x3ui.api.clients import get_panel_api_clients_list
result = get_panel_api_clients_list.sync(client=client)
For large panels use get_panel_api_clients_list_paged instead.
Look up a client by email
from x3ui.api.clients import get_panel_api_clients_get_email
result = get_panel_api_clients_get_email.sync("user@example.com", client=client)
The email is the client identifier in 3x-ui, not a real address.
Get traffic for a client
from x3ui.api.clients import get_panel_api_clients_traffic_email
result = get_panel_api_clients_traffic_email.sync("user@example.com", client=client)
Get subscription links for a client
from x3ui.api.clients import get_panel_api_clients_links_email
result = get_panel_api_clients_links_email.sync("user@example.com", client=client)
Reset a client's traffic counter
from x3ui.api.clients import post_panel_api_clients_reset_traffic_email
result = post_panel_api_clients_reset_traffic_email.sync("user@example.com", client=client)
Delete a client
from x3ui.api.clients import post_panel_api_clients_del_email
result = post_panel_api_clients_del_email.sync("user@example.com", client=client, keep_traffic=0)
Pass keep_traffic=1 to keep the accumulated traffic statistics after removal.
List clients that are currently online
from x3ui.api.clients import post_panel_api_clients_onlines
result = post_panel_api_clients_onlines.sync(client=client)
Get a single inbound
from x3ui.api.inbounds import get_panel_api_inbounds_get_id
result = get_panel_api_inbounds_get_id.sync(1, client=client)
Server status
from x3ui.api.server import get_panel_api_server_status
result = get_panel_api_server_status.sync(client=client)
Returns CPU, memory, uptime, network counters and Xray state.
Async usage
Every endpoint module exposes asyncio and asyncio_detailed alongside the sync variants. Import them under an alias to avoid shadowing the standard library module:
import asyncio as aio
from x3ui import AuthenticatedClient
from x3ui.api.clients import get_panel_api_clients_list
async def main():
client = AuthenticatedClient(base_url="https://panel.example.com:2053", token="YOUR_API_TOKEN")
result = await get_panel_api_clients_list.asyncio(client=client)
print(result.obj)
aio.run(main())
Detailed responses
The plain sync and asyncio functions return the parsed model, or None when the status code is undocumented. Use the _detailed variants when you need the status code, headers or raw bytes:
from x3ui.api.server import get_panel_api_server_status
response = get_panel_api_server_status.sync_detailed(client=client)
print(response.status_code)
print(response.headers)
print(response.parsed)
print(response.content)
Error handling
By default, undocumented status codes yield None. To raise instead:
client = AuthenticatedClient(
base_url="https://panel.example.com:2053",
token="YOUR_API_TOKEN",
raise_on_unexpected_status=True,
)
The raised exception is x3ui.errors.UnexpectedStatus, which carries status_code and content. Network timeouts surface as httpx.TimeoutException.
Client configuration
import httpx
client = AuthenticatedClient(
base_url="https://panel.example.com:2053",
token="YOUR_API_TOKEN",
timeout=httpx.Timeout(30.0),
verify_ssl=False,
follow_redirects=True,
headers={"User-Agent": "my-bot/1.0"},
)
verify_ssl=False disables certificate verification. Only use it against panels with self-signed certificates, never in production. To pin a custom CA, pass a path to the certificate file instead.
For anything not exposed directly, reach the underlying httpx client:
raw = client.get_httpx_client()
Endpoint groups
Endpoints live under x3ui.api.<group>, mirroring the tags in the specification:
| Group | Contents |
|---|---|
authentication |
login, logout, CSRF token, 2FA |
clients |
CRUD, traffic, groups, IP limits, HWIDs, bulk operations |
inbounds |
CRUD, enable/disable, fallbacks, traffic resets, import/export |
server |
status, Xray control, certificates, metrics, database |
settings |
panel settings |
xray_settings |
Xray core configuration |
nodes |
multi-node management |
hosts |
host entries |
backup |
backup and restore |
api_tokens |
token management |
subscription_server |
subscription service |
subscription_balancers |
subscription balancers |
web_socket |
websocket endpoints |
Module names follow the pattern <method>_<path>, so POST /panel/api/clients/add becomes x3ui.api.clients.post_panel_api_clients_add.
Known limitations
Response payloads arrive as {success, msg, obj} where obj is typed Any, because the upstream specification does not describe it. You get typed envelopes but untyped payloads.
Some request bodies are empty models for the same reason. Where a body model has no fields, the corresponding operation cannot be fully expressed through this client yet.
Do not run Python from inside the installed package directory. The package contains a types.py module that shadows the standard library types and causes a circular import.
Regenerating
The client is generated from openapi.json in this repository:
pip install openapi-python-client
openapi-python-client generate --path openapi.json --meta none --output-path x3ui --overwrite
Generated against 3x-ui version X.Y.Z. Endpoints may differ on other panel versions.
Contributing
Improvements to openapi.json are the most valuable contribution: adding operationId values produces readable function names, and describing obj schemas makes responses properly typed. Open an issue or a pull request.
License
MIT
Release files for x3ui 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| x3ui-0.1.1.tar.gz | 147.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| x3ui-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 679.7 kB
Release files / x3ui-0.1.1.tar.gz
| Download URL | x3ui-0.1.1.tar.gz |
|---|---|
| Size | 147.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
69e3fd642a79b3a31e53f0cb6bc05fca4f0647822816bed5f85f821fd16565a0
|
|
BLAKE2b-256 checksum How to use checksums |
3c73a2262f2bcf8639fdabbc8bf69b14f52eafe1c65974f664163bb34e33121f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 25, 2026.
Transparency logRelease files / x3ui-0.1.1-py3-none-any.whl
| Download URL | x3ui-0.1.1-py3-none-any.whl |
|---|---|
| Size | 531.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
03f00cf522d7f8d87c724b46a254122661cd752c9911e08ea3272f7a6ef8365c
|
|
BLAKE2b-256 checksum How to use checksums |
18d382f8785f4466e65d6406908fe47993dbff14fffaa9cca8bf550e789df8cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 25, 2026.
Transparency log