Skip to content

Link formats

Everything the client accepts, in one place. All schemes are case-insensitive.

Scheme Payload
vless:// vmess:// trojan:// ss:// socks:// Standard share links, as issued by any panel
wireguard:// · amneziawg:// · awg:// · wg:// base64 of a plain WireGuard .conf — the same text the official client takes — or base64 of xray-style JSON settings
hysteria2:// · hy2:// Accepted and stored, but not yet supported by xray-core — such a server will not connect

Base64 is read leniently — standard and URL-safe alphabets, with or without padding.

A #fragment sets the display name (percent-encoded). It may also carry a server description — see section 04a.

What “View config” shows

The client applies one simple rule: if the link carries base64, it shows the decoded content; otherwise it shows the link as it is. So wireguard://<base64> displays the readable .conf, while vless://uuid@host:443?… stays a link — there is nothing to decode. JSON payloads are pretty-printed.

Subscriptions

A subscription URL may return:

  • plain text — one link per line;

  • base64 of that same list;

  • JSON — a full xray config, or a container with several WireGuard/AmneziaWG servers:

{"type":"amneziawg","version":1,"servers":[
  {"name":"Germany","config":"<base64 of .conf>"}]}

type is accepted as amneziawg, awg, wireguard or wg. A broken entry is skipped rather than failing the whole subscription.

Encrypted header values

Header values can be sent in a closed form, so links and settings don't travel around in the open. Any subscription header may carry its value encrypted, using the same crypt1/ prefix as the deep links:

routing-update-url: crypt1/<base64>
routing: crypt1/<base64>
autorouting: crypt1/<base64>
s-dns: crypt1/<base64>
s-fragment: crypt1/<base64>
s-resolve: crypt1/<base64>
s-noise: crypt1/<base64>
new-url: crypt1/<base64>
s-siteurl: crypt1/<base64>

The client strips the prefix, decrypts the payload and then treats the result exactly as if it had arrived in the clear. Without the prefix nothing changes — existing subscriptions keep working untouched. Encryption is optional and per-header: a single response can freely mix encrypted and plain values.

The encryption is exactly the one used by smproxy://crypt1/… links — AES-256-GCM, nonce || ciphertext || tag, base64-encoded, under the same shared key. A panel that already issues those links needs no new code: encrypt the value, prefix it with crypt1/, and put it in the header.

To get an encrypted value without writing any code, use the public generator — no authentication needed. The response has two fields: link is the full ready-made link, and cryptedPart is just the encrypted payload, which is what goes into a header after the crypt1/ prefix.

POST https://provider.smproxy.io/public/crypto-link
{ "url": "https://example.com/routing.json" }

→ {
    "link": "smproxy://crypt1/AbCd…",
    "cryptedPart": "AbCd…"
  }

routing-update-url: crypt1/AbCd…
s-dns: crypt1/AbCd…

Encrypted link generator → — public, no sign-in needed. All tools: Link generators.

Both separators are accepted — crypt1/<base64> and crypt1:<base64> — but use the slash: it matches the deep links, so there is one format to remember.

This is obfuscation, not secrecy. The key ships inside every client, so anyone who takes the app apart can read these values. It keeps the profile URL out of plain sight — away from a casual glance at traffic, or from being pasted into a chat — and nothing more. Do not put anything genuinely sensitive behind it.

Two schemes are accepted: smproxy:// (current) and smartvpn:// (pre-rename, kept working for links already handed out). That applies to clickable links only — the OS hands a link to the app registered for its scheme. Inside the routing / autorouting headers any scheme word is accepted (section 07a).

Link Effect
smproxy://add?url=<encoded URL> Add a subscription
smproxy://add/<https://…> · add/<base64 URL> Same, path form
smproxy://crypt1/<base64> Add from an encrypted payload
smproxy://routing/add/<base64\|url> Import a routing profile, don't switch to it
smproxy://routing/onadd/<base64\|url> Import and activate
smproxy://autorouting/add\|onadd/<url> Same, plus keep it updated from that URL
smproxy://routing/off Turn routing off

The payload may also be passed as ?data=<base64>. For routing links the target may hold the profile JSON, its base64, or another smproxy:// link — all three resolve.