How it works
What is a VPN subscription link: the vless:// and hy2:// URL formats explained
Modern proxy clients — v2rayN, v2RayTun, sing-box, Streisand, Hiddify, NekoBox — do not ask for a server, a port and a password in separate fields. You paste one URL, the client fetches it, and a list of servers appears. That URL is a subscription link, and what it returns is a plain text list of connection URIs. It is worth knowing exactly what is inside one before you paste it into a form or send it to someone.
What a subscription link actually is
There are two different objects, and they get confused constantly. A connection URI (vless://…, hy2://…) describes one server: address, port, credential, transport settings. A subscription URL is an ordinary HTTPS endpoint that, when fetched, returns a list of such URIs.
The subscription exists because the list changes. Servers get replaced, IP addresses rotate, a location is added or removed. Distributing one stable URL and letting clients re-read it is simpler than asking every user to re-import a dozen configs by hand.
Reading a vless:// URI, field by field
A typical Reality link looks like this (wrapped here for reading, always one line in practice):
vless://0f7a9c3e-…-b21d@203.0.113.10:443?encryption=none&security=reality&type=tcp&flow=xtls-rprx-vision&sni=www.example.com&fp=chrome&pbk=Xk9…&sid=1a2b3c4d&spx=%2F#DE-01
It is a standard URI, so the parts follow the usual rules: userinfo before the @, host and port, a query string, a fragment after the #.
0f7a9c3e-…— the UUID identifying the client. This is the credential. Anyone holding it can connect as you.203.0.113.10:443— server address (IP or hostname) and port.encryption— a field VLESS requires to be present. In the overwhelming majority of links the value isnone, which is not a misconfiguration: VLESS adds no encryption of its own and leaves that to the TLS layer underneath. Recent Xray builds also define native VLESS encryption values here, so a link carrying something other thannoneis not automatically broken either.security=reality— how the outer layer is built:none,tls, orreality. See how VLESS Reality works.type=tcp— the transport. Common values aretcp(renamedrawin newer Xray, which still accepts the old name),ws,grpcandxhttp; WebSocket and gRPC addpath,hostorserviceNameparameters.flow=xtls-rprx-vision— Vision flow control, used with the raw/TCP transport plus TLS or Reality. After the handshake it stops re-wrapping the inner records, which softens the nested-TLS pattern a plain tunnel produces.sni=www.example.com— the server name sent in the TLS ClientHello. With Reality this is the borrowed site, and it has to be one the server has on its list.fp=chrome— uTLS fingerprint. Shapes the ClientHello to match a real browser build (chrome,firefox,safari,ios,random).pbk=…— the server's Reality X25519 public key. Without the matching key the client cannot authenticate itself to the server.sid=…— Reality short ID, a hex string the server has on its list. An empty value is valid if the server allows it.spx=%2F— spiderX, the initial path for Reality's crawler behaviour on the client side. In practice it is almost always/and changing it does nothing you will notice.#DE-01— the display label only. Clients show it in the server list; it has no effect on the connection.
One failure mode is worth spelling out. sni, pbk and sid all have to agree with the server configuration. If any of them is stale, the server does not reject you with an error — it treats you as an outsider and hands the connection to the real borrowed site. The client reports a successful TLS session, and no proxied traffic moves through it.
Separately: if you see allowInsecure=1 in a TLS link, certificate verification is switched off. On a server with a real certificate there is no good reason for that.
Reading a hy2:// URI, field by field
Hysteria2 uses its own scheme, written either hysteria2:// or the short form hy2://. The grammar is the same, but the fields differ because the protocol does — QUIC over UDP rather than TLS over TCP.
hy2://s3cret-auth-string@203.0.113.20:443/?sni=example.com&obfs=salamander&obfs-password=…&insecure=0#DE-hy2
- The userinfo part is the authentication string, not a UUID. If it contains reserved characters they have to be percent-encoded.
sni— the name presented during the QUIC/TLS handshake.obfs=salamanderwithobfs-password— an obfuscation layer over the QUIC packets, keyed from that password. With it the datagrams stop parsing as QUIC at all. Without it the connection is ordinary QUIC, which by itself is unremarkable on the modern internet — but its handshake and traffic shape do not have to resemble a browser doing HTTP/3. Both ends must use the same password.pinSHA256— pins a certificate fingerprint. Used when the server runs a self-signed certificate.insecure=1— disables certificate checks. Same warning as above.- The fragment is again just a label.
Two things the URI does not settle. Bandwidth is one: Hysteria2's Brutal congestion control uses the up and down rates you declare, and those live in the client's own settings — leave them empty and it falls back to BBR instead. Port hopping is the other: the scheme has no agreed field for it, so clients express a range or a list in their own way, and it is worth reading your client's documentation rather than guessing. Which of the two protocols to prefer on a given network is covered in VLESS Reality vs Hysteria2.
What the subscription URL returns
Fetch a subscription URL with curl and you will get one of a few things. There is no standard here — these are conventions that spread from one panel to the next.
- Plain text — one URI per line, nothing else.
- Base64 — the same plain text, base64-encoded. The most common form. Panels differ on the standard versus URL-safe alphabet and on whether padding is kept, so clients are expected to accept either.
- sing-box JSON — a full config with outbounds, routing rules and DNS.
- Clash / mihomo YAML — proxies, proxy groups and rules.
Which one you get often depends on who is asking. Many panels inspect the User-Agent header and return the format that client understands, or accept a query parameter such as ?target=. This is why the same URL can produce different bodies in a browser, in curl and in the app.
Servers also attach informational headers that clients read to display quota and expiry:
subscription-userinfo: upload=…; download=…; total=…; expire=…— bytes used, bytes allowed, and a Unix timestamp for expiry. By conventiontotal=0means no quota andexpire=0means no expiry date, though not every panel is consistent about it.profile-update-interval— how many hours the client should wait before re-fetching.profile-title— the name shown for the whole subscription.profile-web-page-url— a link back to the account page.
Why clients poll the link
A client does not keep a live connection to the subscription endpoint. It re-fetches on a schedule — typically at launch, then on an interval it chooses itself or takes from profile-update-interval — and rebuilds its server list from the response.
- 1The client sends a plain
GETto the subscription URL with its own User-Agent. - 2The server picks a format based on that header and returns the body.
- 3The client base64-decodes it if needed and splits it into individual URIs.
- 4The stored server list is replaced. Many clients try to keep your current selection by matching the fragment label — which is why operators keep labels stable.
- 5Response headers are parsed for traffic counters and expiry, and shown in the UI.
Two practical consequences. First, the fetch is an ordinary HTTPS request from your device to the subscription host, so unless the client routes it through the tunnel, that host sees your real IP address and your client's User-Agent. Second, when a fetch fails, most clients silently keep the last good list. Nothing appears wrong until the server-side keys rotate, at which point the connection stops working for a reason that has nothing to do with the server you are looking at.
What leaks if you share one
Sharing a subscription link is not like sharing a streaming password, where the other person at least has to log in. It is closer to handing over a private key.
- Full access, no revocation on your side. Whoever has the URL can connect as you, on any number of devices, until the operator issues a new one.
- A QR screenshot is the link. Codes in screenshots and photos are machine-readable. Cropping the URL out of a screenshot but leaving the QR in changes nothing.
- Online converters see everything. Pasting a subscription URL into a third-party format converter or QR generator hands that site your credential and your full server list. There is no way to un-share it afterwards.
- An individual vless:// exposes the node. Address, port, SNI and Reality public key are all in the link, so anyone holding it can probe that specific server directly.
- The label may carry your account name. Panels often write an email address or username into the fragment, so a screenshot of the server list can identify the account.
- The operator can see the fetches. Subscription requests carry an IP, a User-Agent and a timestamp, and panels commonly log them. A link pulled from two continents in the same hour is the usual way sharing gets noticed, and shared use draws on the same quota and connection limits as your own.
A useful habit: when asking for support, mask the UUID and the subscription token. Support almost never needs the credential — the server label, the client name and the error text are enough. The same reasoning that keeps API keys out of git repositories, issue trackers and group chats applies here without modification.
Rotating a link that got out
There is no password reset for a subscription. Rotation means the operator issues a new value and the old one stops being accepted.
The detail people miss: rotating the subscription URL and rotating the credentials inside it are two separate operations. If only the URL changes, the UUIDs and auth strings from the old response usually stay valid on the servers, so a vless:// link someone already copied keeps working. If a config leaked rather than the subscription address, ask for the client identity on the inbound to be reissued, not just a new URL.
- 1Ask the operator to reissue both the subscription token and the client credentials.
- 2Re-import the new URL in every client you use — old entries do not update themselves.
- 3Delete the stale profiles rather than leaving them disabled, so you do not re-enable one later by accident.
- 4Verify from each device that traffic actually flows on the new profile before removing the old one.
When the link does not work
- Update fails while disconnected. If the subscription host is unreachable on your current network, the client cannot refresh. Update from a different network, or from a client that can fetch through an existing connection.
- Zero servers after an update. Usually a format mismatch — the panel returned YAML or JSON to a client expecting base64, often because it did not recognize the User-Agent.
- Connects but nothing loads. On Reality, this is the parameter mismatch described above. Refresh the subscription instead of editing
sni,pbkorsidby hand. - Handshake fails on one device only. Check the system clock. Certificate validity windows and the timestamps inside modern handshakes both depend on it, and a device that is hours out of sync fails in ways the error message does not explain.
- Old servers keep coming back. Some clients merge instead of replacing. Remove the subscription and add it again.
What a subscription link does not do
Worth restating plainly: none of this makes you anonymous. A subscription link configures where your traffic leaves the network — it changes your visible IP address and encrypts the hop to the server. It does nothing about accounts you are signed into, browser fingerprinting, or identifiers your operating system sends on its own. That distinction is covered in does a VPN make you anonymous.
Is a subscription link the same thing as a password?
Functionally yes, with fewer protections. It authenticates by possession alone: no username, no second factor, no expiry unless the operator sets one. Anyone who obtains the URL has your access until it is reissued.
What is the difference between a vless:// link and a subscription URL?
A vless:// URI describes one server, fully contained in the link itself, and it never changes on its own. A subscription URL is an endpoint that returns a list of such URIs, so the list can be updated centrally when servers change.
Can I use the same subscription on my phone and my laptop?
Technically nothing stops you, and most services expect it. Whether it is allowed, and how many simultaneous connections you get, is set by the operator. The link itself carries no device binding.
Is it safe to paste my link into an online config converter?
No. The converter receives your credential and the address of every server you use, and you have no way to withdraw that afterwards. If you need a different format, use a client that supports it or run a converter yourself.
Why does my client keep re-downloading the subscription?
Because the contents change. Server addresses rotate, nodes are added or removed, and keys are reissued. The client also reads traffic and expiry counters from the response headers, which is why those numbers only move after an update.