Clash Subscription Formats Explained: YAML Config, Base64 Links & Converting Between Them
Subscription link not recognized? Learn the differences between Clash YAML, Base64 node lists and other formats, and how conversion works.
Subscription link not recognized? Learn the differences between Clash YAML, Base64 node lists and other formats, and how conversion works.
Paste a subscription link into a browser, and what comes back isn't always the same kind of content. Most troubleshooting starts from a wrong assumption — that whatever format comes back, the client "should" understand it — without first checking which of the formats it actually is. Subscription content in circulation today generally falls into three categories, each requiring completely different handling.
Telling them apart is straightforward: open the subscription link in a browser or with curl and look at the first line of the response. If it's YAML key-value pairs like port:, mixed-port:, or proxies:, it's a native Clash config. If it's a long string with no line breaks, made up of letters, numbers, and trailing equals signs, it's almost certainly Base64. If every line starts with a protocol name followed by ://, it's a plain-text node list.
Tip: Many panels offer multiple subscription formats from the same source — usually distinguished only by a URL parameter or path suffix (e.g. ?clash=1 or /clash). Before manually converting an unrecognized subscription, check whether the panel's dashboard already offers a Clash-specific link — it's usually far less work.
A subscription the Clash core can use directly generally has this skeleton:
port: 7890
socks-port: 7891
mode: rule
log-level: info
proxies:
- name: "hk-01"
type: ss
server: example.com
port: 443
cipher: aes-256-gcm
password: "your-password"
proxy-groups:
- name: "auto"
type: url-test
proxies:
- hk-01
url: "http://www.gstatic.com/generate_204"
interval: 300
rules:
- DOMAIN-SUFFIX,google.com,auto
- GEOIP,CN,DIRECT
- MATCH,auto
Here, proxies describes the connection parameters for each node, proxy-groups organizes nodes into policy groups (automatic latency testing, manual selection, load balancing, and so on), and rules determines which policy group traffic is routed to under which conditions. All three sections matter — if a subscription's YAML only includes proxies without the other two, most clients will auto-generate a default policy group and rule set, though the exact behavior varies by client. It's worth opening the config viewer after import to confirm what was generated.
If you're using the Clash Meta (mihomo) core, you may also see extended fields inside proxies such as tfo, smux, or reality-opts — newer protocol parameters that the original Clash core doesn't recognize. Importing these into the original core will either throw an error or silently skip the affected nodes, which is itself a good signal for whether you need to switch cores.
A Base64-format subscription is essentially just "a bunch of share links packed into one block of text" so the client can pull updates in one request — it's encoding, not encryption. Once decoded, common node links look roughly like this:
ss://[email protected]:443#hk-01
vmess://eyJ2IjoiMiIsInBzIjoiaGstMDIiLCJhZGQiOiJleGFtcGxlLmNvbSIsInBvcnQiOiI0NDMi...}
trojan://[email protected]:443?sni=example.com#hk-03
The logic for converting each entry is fixed:
Doing this by hand for a single node is fine, but subscriptions typically contain dozens or hundreds of nodes — manually editing each one isn't realistic. In practice, this batch conversion almost always relies on a subscription conversion service, covered in the next section.
Turning a Base64/plain-text subscription into YAML that Clash can read generally comes down to two approaches, each with its own trade-offs.
Some Android clients include format detection built into "New Config" or "Import Subscription": after pasting the link, the client first tries to parse it as Clash YAML, and if that fails, automatically decodes it as Base64 and converts each entry into a local config. This approach doesn't depend on a third-party service — all data is processed locally on the device, making it the cleanest option from a privacy standpoint. However, the conversion quality depends on how well the client itself supports the relevant protocol fields; newer transport-layer parameters (some hysteria2 obfuscation options, for instance) may convert incompletely or get dropped entirely.
The other approach is to hand the original subscription link to a conversion service, which decodes and rewrites the format server-side, then gives you a generated Clash YAML link to subscribe to in your client. These services usually support customizable parameters, commonly including:
The advantage of this approach is stronger conversion capability and reusable templates — useful when you need consistent naming across multiple subscription sources, or need to merge and deduplicate them. The trade-off is that the original subscription link (which contains account credentials) passes through a third-party server, creating a privacy exposure. When choosing a service, check whether it publishes a clear logging policy; the more cautious option is to self-host an open-source conversion service, so the relay step stays under your own control.
Note: Subscription links typically carry a unique user identifier (a token, or a username/password). Once routed through a third-party conversion service, that's effectively exposing your account credentials to that service. If you don't know anything about a conversion service's background, prefer built-in client conversion or a locally deployed conversion tool over handing your raw subscription to an uncontrolled third party.
A subscription importing successfully after conversion doesn't guarantee the nodes will actually connect. The following scenarios come up fairly often in practice.
If the converted subscription has fewer nodes than the original, it's usually because the conversion service or client doesn't support a particular protocol field and silently skips the whole node, rather than throwing an error. To diagnose this, check the total node count from decoding the original Base64, then compare it against the number of proxies entries in the generated YAML. If there's genuinely a gap, check whether the missing nodes use a less common protocol (some experimental transport-layer combinations, for example) — switching conversion templates or updating to a core version that supports that protocol usually fixes it.
If you're using a remote rule template (specified via the config parameter), the node-filtering rules for each policy group are hard-coded to match keywords in node names. If a new node's name doesn't match the template's keyword pattern (for example, if the template only picks up nodes starting with "HK|SG|JP"), it won't automatically land in the corresponding policy group. Check the filter regex in the template, or simply drop the remote template and let the conversion service fall back to its default "all nodes in one auto-test group" policy.
Some protocols — especially Trojan and VMess over WebSocket+TLS — are sensitive to the SNI and skip-cert-verify fields. If the conversion service fails to correctly parse the sni or allowInsecure parameter from the original share link, the resulting node will time out or fail the TLS handshake. In this case, open the generated YAML manually, compare it against the parameters in the original share link, and fill in or fix the servername and skip-cert-verify fields.
A converted subscription link is essentially a "live proxy request" — every time the client refreshes it, the conversion service re-fetches the original subscription and re-converts it on the spot. If the original subscription enforces a refresh-rate limit (commonly once every few hours), refreshing too often will get flagged as abnormal traffic by the original panel and rejected, which in turn causes the conversion service to return an empty node list. Set the client's subscription refresh interval to somewhere between 6 and 12 hours, and avoid manually hitting refresh repeatedly.
Subscription format conversion might look like a small formatting problem, but underneath it involves the path node information travels through multiple parties. Understanding exactly whose server each piece of data passes through, and in what form it's exposed, is worth more of your time than just getting the link to "work."