Check what the subscription returns before converting it

A “subscription link” simply means a client fetches content from a URL; it does not guarantee that the content is a Clash config. The same HTTPS URL might return a complete YAML config, a Base64-encoded list of nodes, SIP008 JSON, or even a login page. If an import fails, inspect the response body first—changing the file extension over and over is unlikely to help.

Keep three layers distinct: the subscription URL is the access point; YAML, JSON, and Base64 describe the content structure or encoding; and Shadowsocks, Trojan, and VLESS are proxy protocols used by nodes. Decoding Base64 does not change a Shadowsocks node into another protocol, nor does it create routing rules.

Content typeHow to identify itHow to import into Clash
Full YAML configCommon keys: proxies:, proxy-groups:, and rules:Check compatibility with the target core, then import it as a config
Node-only YAMLMostly contains proxies:, with no proxy groups or rulesUse it as a node source or add the missing config sections
Base64 node subscriptionEncoded text; decoding often reveals multiple links such as ss://Parse the nodes, then generate a YAML config
SIP008 JSONCommon fields include version and serversMap the Shadowsocks server fields to proxy nodes
HTML or invalid JSONLogin prompts, access denied messages, or quota errorsFix subscription access first; conversion cannot resolve the issue

Clash YAML: how nodes, proxy groups, and rules work together

Clash-family cores use YAML for runtime configuration. Nodes connect to remote servers; proxy groups organize nodes into manual selection, automatic latency testing, or failover options; and rules match destinations in order, routing traffic to the selected policy. Listening ports, DNS, and TUN are local network access settings.

A complete config is more than a list of nodes

Having nodes under proxies does not mean traffic will use them. If the final rule is still MATCH,DIRECT, connections that do not match an earlier rule go directly out. If a rule references a proxy group that does not exist, the config may fail to load. Subscription conversion must handle both node names and policy references—it cannot just concatenate a few text snippets.

Here is a direct-connection example to illustrate the structure; it contains no remote proxy nodes. The listening port is set to 7890 and is available only on the local machine. All traffic goes to “Exit selection,” whose only option is DIRECT. This config cannot be used to test whether a remote node works.

mixed-port: 7890
allow-lan: false
mode: rule
log-level: info

proxies: []

proxy-groups:
  - name: "Exit selection"
    type: select
    proxies:
      - DIRECT

rules:
  - MATCH,Exit selection

YAML syntax and core support are separate checks

  • Use spaces, not tabs, for indentation. Keep indentation consistent at each level; this example uses two spaces.
  • Quote node names, passwords, and strings containing special characters to prevent them from being interpreted as other data types.
  • A successful YAML parse only confirms valid syntax. The target core must also support the protocol type, transport parameters, and proxy group options.
  • Traditional Clash and Clash Meta (now called mihomo) support different features. For nodes such as VLESS and Hysteria2, check the target core's documentation—don't assume compatibility based on the client name alone.

Base64 subscriptions: decoding restores text, not routing rules

A typical Base64 subscription encodes multiple share links as a block of text, usually one link per line. Decoding may reveal ss://, trojan://, vmess://, or vless:// links. Each uses its own field format, so a converter must identify and parse them individually.

There may also be two layers of encoding: an outer Base64 layer for the subscription list and an inner layer within individual share links. For example, some Shadowsocks links encode their authentication data, while common VMess links use Base64 to carry JSON. Decoding only the outer layer may not make all node details readable.

Inspect subscription content locally

Save the subscription response as subscription.txt, then decode it locally. The command below works with common standard Base64 text. The output contains node credentials, so keep it in a private directory and never upload it to a public repository.

# Linux:GNU coreutils
base64 --decode subscription.txt > nodes.txt

# macOS
base64 -D -i subscription.txt -o nodes.txt

If a tool reports invalid encoding, first check whether the downloaded content is HTML, uses URL-safe characters, omits padding, or has extra wrapping. Don't assume every error means the subscription is broken. Some converters handle these variants, but support depends on the implementation.

SIP008: JSON subscriptions for Shadowsocks servers

SIP008 is a subscription convention in the Shadowsocks ecosystem—not a general-purpose proxy protocol or a Clash config. Its JSON describes nodes in an array of servers, commonly with fields for server address, port, encryption method, and password. The standard structure can carry multiple Shadowsocks servers, but it does not provide Clash proxy groups or routing rules.

The example below uses a reserved example domain to illustrate the fields; the password is also for demonstration only and does not connect to a real service. When converting an actual subscription, preserve the original authentication values provided by the service.

{
  "version": 1,
  "servers": [
    {
      "id": "80a3cf64-dcec-4ca9-bd7b-b69b9763ca15",
      "remarks": "Example SS node",
      "server": "edge.example.com",
      "server_port": 443,
      "password": "demo-password-not-for-use",
      "method": "aes-128-gcm"
    }
  ]
}

Mapping SIP008 fields to Clash

  • remarks is usually used as the Clash node's name. Deduplicate any repeated names and update the corresponding proxy group references.
  • Keep server as the server address and map server_port to port.
  • Map method to cipher, keep password as the authentication password, and set type: ss.
  • If the source includes plugin and plugin_opts, check that the target core supports the plugin and parameter format. Do not copy them directly as Clash fields.

Some servers return custom JSON or legacy arrays that do not fully match this structure. Even if a converter claims “SIP008 support,” it may not handle every variant. If it reports “no usable nodes,” check the response's top-level structure and required fields instead of repeating the same import steps.

Subscription conversion: from the raw response to a complete YAML config

Use the source provider's target format when available

If the subscription page offers a dedicated Clash or mihomo option, use it first. This usually removes an intermediate conversion step and preserves the node parameters set by the service. The same subscription URL may return different formats depending on request parameters or the User-Agent, so the browser response may not match what the client fetches.

When conversion is needed, follow these five steps

  1. Identify the target core. Check the client's About or core information page to see whether it runs traditional Clash or mihomo. Menu paths vary by client, so follow what's actually shown; don't use the app's shell name as a substitute for the core name.
  2. Identify the source format. Inspect the response's opening lines and structure to distinguish YAML, Base64, SIP008, and error pages. Keep the original file for comparison, and don't overwrite the config currently in use.
  3. Choose where to run the converter. Prefer a trusted local tool or a service you host yourself. A web form does not mean processing happens locally; if it submits the subscription URL to a backend, that backend can access the subscription content.
  4. Choose an output template. Check whether the output is a complete config or a provider file containing only nodes. Make sure proxy groups, rules, and DNS settings meet your needs; don't blindly apply a template designed for another core.
  5. Save, validate, and test. Save the output as a YAML file and test it with the target core before importing it into the client. Keep the old config until you've confirmed that connections and updates work as expected.

The “Clash” and “Clash Meta” targets in a converter may support different serialization features. Choosing a traditional target may discard newer protocols or transport parameters; choosing mihomo does not make those new fields readable by a traditional core. Match the output format to the core actually in use.

Before importing: check fields, validate the config, and test a real connection

“File generated successfully” does not mean “connection successful.” Check three layers: first syntax and config references, then the node handshake, and finally rule matching and access to the destination site. This helps distinguish parse errors from authentication and routing problems.

Test the config with the target core

If mihomo's command-line program is installed, use it to test the converted config. converted.yaml is the name of the output file saved locally; if it isn't in the current directory, use its actual file path.

mihomo -t -f ./converted.yaml

Config tests may need to read external providers or rule resources, and results can vary by runtime environment. Passing a test only means this check found no issue that prevents loading. It does not confirm server authentication or guarantee access to every site.

Check parameters that are easy to lose

  • Address and port: Make sure server and port are present. Port 443 does not by itself mean TLS is enabled.
  • Authentication fields: Check required protocol details such as the password, UUID, and encryption method. Make sure escaping and URL decoding are handled correctly.
  • TLS and transport: Check fields such as SNI, certificate verification, ALPN, WebSocket path, and Host. Don't disable certificate verification to cover up incorrect parameters.
  • Node references: Every name referenced by a proxy group must exist. If you rename a node, update its references too.
  • Local listening port: The 7890 in the example is a local proxy port, not the remote server port. If another process is using it, coordinate changes to the client and app proxy settings.

After importing, manually select a node and check the connection log for the destination, matched rule, and selected proxy. If the log shows DIRECT, first check whether the rules route traffic to a proxy group. If a node is selected but the handshake fails, check the protocol parameters and server connectivity.

Keep subscriptions up to date: manage full configs and proxy-providers separately

A one-time conversion saved as local YAML is usually just a snapshot. If the service adds nodes, rotates passwords, or removes routes, the local file won't update by itself. The client or core can fetch new content only if a working remote update path is configured.

There are two common approaches: have the client periodically update the full remote config, or keep proxy groups and rules in the main config while updating nodes through proxy-providers. The latter suits users who want to keep local routing logic fixed, but requires correctly configuring the provider, the proxy groups' use references, and the update interval.

Don't use an arbitrary subscription URL as a provider

A standard YAML node provider usually needs to return node data organized under proxies:. Full configs, Base64 lists, and SIP008 JSON are not interchangeable without conversion. mihomo provider support varies by core implementation; check the documentation and test results before using other formats.

For example, an update interval of 3600 seconds means the client attempts an update every hour; it does not guarantee that every request succeeds. If the URL expires, the network is unreachable, or the conversion service fails, check the update log and local cache. An enabled timer alone does not mean the nodes are up to date.

Common issues: import errors, missing nodes, and credential safety

YAML parse error? Here's what to check first

Check whether the file starts with HTML, a JSON error, or undecoded text. Then use the reported line number to inspect indentation, quotes, and colons. An HTTP 200 response can still contain a login page; the status code alone does not prove you received a config.

Are fewer nodes after conversion expected?

Don't assume so. First check region or name filters, then whether the target format supports every protocol, and finally duplicate-name handling, plugin parameters, and parse error logs. A lower node count may be the result of intentional filtering or limited converter support; compare it with the source data.

Can a single node link be used as a subscription?

A single share link usually describes one node and does not include a remote update mechanism. Some clients let you add a single node, but that is not the same as importing a complete config. To use rule-based routing, you still need to add the node to a proxy group and configure rules.

What should I do if I shared my subscription URL with a third party?

Reset or revoke the subscription token in the service dashboard, update the saved URL in your clients, and remove sensitive content from public posts. Deleting a local conversion file cannot revoke access that has already been exposed. Whether you also need to rotate node passwords depends on how the service handles credentials.

The process comes down to four checks: identify the input format, choose output for the matching core, test the active config, and protect subscription credentials. Get these right before adjusting routing templates or update methods, and troubleshooting will be more focused.