3x-ui3x-ui

Subscription

Run the 3x-ui subscription server — base64/JSON/Clash formats, ports and paths, TLS, response headers, and custom templates.

A subscription is a single URL that returns all of a client's configurations. Client apps refresh it periodically, so when you change an inbound, clients pick up the change automatically. The subscription server runs as a separate server from the panel.

Enable and configure

The subscription server is on by default (subEnable). Configure it in the panel's subscription settings:

SettingDefaultMeaning
subPort2096Listen port (separate from the panel).
subListen(all)Bind address.
subPath/sub/Base path for raw subscription URLs.
subDomain(none)Public host; if set, the server only answers for that Host.
subCertFile / subKeyFile(none)TLS cert + key — when set, the server serves HTTPS.
subEncrypttrueBase64-encode the raw subscription body.
subUpdates12Suggested refresh interval (hours) sent to clients.

A subscription URL looks like:

https://<sub-host>:<sub-port>/sub/<sub-id>

where <sub-id> is the client's Sub ID.

The same Sub ID is served in several formats on different paths — the Base64 list at subPath and the JSON (Xray-json) config at the JSON path. Build the URLs and preview both bodies here:

Subscription & sub-JSON builder

Build the subscription URLs and preview both body formats — the Base64 link list and the JSON (Xray-json) config.

Base64 subscription URL
https://sub.example.com:2096/sub/user-1
JSON subscription URL
https://sub.example.com:2096/json/user-1

Clients in this subscription

Subscription links (decoded body)
vless://11111111-2222-3333-4444-555555555555@a.example.com:443?type=tcp&security=reality&sni=www.microsoft.com#HK-01
Base64 body
dmxlc3M6Ly8xMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTVAYS5leGFtcGxlLmNvbTo0NDM/dHlwZT10Y3Amc2VjdXJpdHk9cmVhbGl0eSZzbmk9d3d3Lm1pY3Jvc29mdC5jb20jSEstMDE=
JSON subscription (preview)
{
  "remarks": "HK-01",
  "dns": {
    "tag": "dns_out",
    "queryStrategy": "UseIP",
    "servers": [
      {
        "address": "8.8.8.8",
        "skipFallback": false
      }
    ]
  },
  "inbounds": [
    {
      "port": 10808,
      "protocol": "mixed",
      "settings": {
        "auth": "noauth",
        "udp": true,
        "userLevel": 8
      },
      "sniffing": {
        "destOverride": [
          "http",
          "tls",
          "quic",
          "fakedns"
        ],
        "enabled": true
      },
      "tag": "mixed"
    },
    {
      "port": 10809,
      "protocol": "http",
      "settings": {
        "userLevel": 8
      },
      "tag": "http"
    }
  ],
  "log": {
    "loglevel": "warning"
  },
  "policy": {
    "levels": {
      "8": {
        "connIdle": 300,
        "downlinkOnly": 1,
        "handshake": 4,
        "uplinkOnly": 1
      }
    },
    "system": {
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  },
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  },
  "stats": {},
  "outbounds": [
    {
      "protocol": "vless",
      "tag": "proxy",
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "tcpSettings": {
          "header": {
            "type": "none"
          }
        },
        "realitySettings": {
          "fingerprint": "chrome",
          "serverName": "www.microsoft.com"
        }
      },
      "settings": {
        "address": "a.example.com",
        "port": 443,
        "id": "11111111-2222-3333-4444-555555555555",
        "encryption": "none",
        "level": 8
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {
        "domainStrategy": "AsIs",
        "redirect": "",
        "noises": []
      }
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {
        "response": {
          "type": "http"
        }
      }
    }
  ]
}

Output formats

The format is chosen by path, each with its own enable toggle:

FormatPathEnabled byOutput
Raw links/sub/always (if on)A list of vless://, vmess://, … links (base64-encoded when subEncrypt is on).
JSON/json/subJsonEnableFull Xray client config(s).
Clash / Mihomo/clash/subClashEnableYAML profile.

Only enabled inbounds using VLESS, VMess, Trojan, Shadowsocks, or Hysteria2 appear in a subscription, ordered by their sub-sort index. Requesting /sub/ with an Accept: text/html header (or ?html=1) returns a human-readable info page instead of the raw body.

Base64 vs JSON

The Base64 body is just the newline-joined share links, standard-base64 encoded (toggle with subEncrypt). The JSON body wraps each client in a complete Xray client config — a fixed skeleton (local mixed/HTTP inbounds, DNS, routing, policy) plus a proxy outbound pointing at the inbound. 3x-ui emits a single config object for one client and an array for several, uses the flat outbound settings form (address/port/id, level: 8), and strips sockopt from streamSettings.

Response headers

Subscriptions return standard headers that compatible apps read:

  • Subscription-Userinfoupload, download, total (bytes; total=0 means unlimited) and expire (Unix seconds).
  • Profile-Update-Interval — refresh interval in hours (subUpdates).
  • Profile-Title, Support-Url, Profile-Web-Page-Url, Announce — optional branding shown by some clients.

Custom page templates

Point subThemeDir at a folder containing a custom info-page template to brand the HTML subscription page. The per-client remark on each link is fully templated — see Share links → remark variables.

Put the subscription server behind TLS (set subCertFile/subKeyFile, or a reverse proxy) so subscription contents aren't exposed in transit.

On this page