Start by separating subscription URLs, node links, and configuration files
A “subscription” is not a single file format. What users paste into a client is usually an HTTPS URL. The client requests that URL, and the server then returns Base64 text, Clash YAML, JSON, or another structured response. The URL is only the access point; the response format determines whether the client can parse it. That is why the same subscription URL may look like a plain string in a browser yet produce “unsupported format,” “configuration parse failed,” or an empty node list in different clients.
Another easily confused concept is the single-node link. Content beginning with ss://, trojan://, vmess://, or vless:// usually describes one proxy node, while a subscription response may combine dozens of node links into one list. A native Clash configuration goes further by adding proxy groups, rules, DNS, listening ports, and other fields. It is no longer just a collection of nodes, but a complete configuration that can directly drive the proxy core.
| Content type | Common characteristics | Primary use | Can rules be preserved directly? |
|---|---|---|---|
| Subscription URL | https:// URL, possibly with authentication parameters |
Periodically fetch remote content | Depends on the format returned by the server |
| Single-node URI | ss://, trojan://, and others |
Share one node’s connection parameters | No |
| Base64 node list | Usually one URI per line after decoding | Distribute nodes in bulk | Usually not |
| Clash YAML | Contains proxies, proxy-groups, and rules |
Load into Clash or a compatible core | Yes |
| sing-box JSON | Contains inbounds, outbounds, and route |
Load into sing-box and related clients | Yes, but the field model differs |
What Clash YAML and common node links each contain
A Clash configuration contains four categories of information
A basic Clash configuration usually stores listener settings, nodes, proxy groups, and routing rules together. Traditional Clash commonly uses 7890 for the local mixed port and 9090 for the controller port; these are only common defaults, and clients may use different ports. Nodes are stored under proxies, selection, health checks, and failover logic under proxy-groups, and domain or network handling order under rules.
mixed-port: 7890
mode: rule
proxies:
- name: "Tokyo-01"
type: trojan
server: edge.example.net
port: 443
password: "example-password"
sni: edge.example.net
proxy-groups:
- name: "Node Selection"
type: select
proxies:
- "Tokyo-01"
- DIRECT
rules:
- DOMAIN-SUFFIX,example.org,Node Selection
- GEOIP,CN,DIRECT
- MATCH,Node Selection
This example shows why converting Clash into node links usually loses information. A Trojan URI can hold connection parameters such as the server, port, password, and SNI, but it has no standard place for the full proxy-groups and rules sections. If a converter outputs only single-node URIs, proxy-group selection logic, health-check intervals, and rule order are discarded.
Node URIs are not interchangeable either
- Shadowsocks:
ss://primarily describes the encryption method, password, host, and port; plugin parameters usually appear in the query string. - Trojan:
trojan://primarily describes the password, server, port, TLS hostname, and optional transport parameters. - VMess: A common sharing format encodes a JSON object inside
vmess://; different generators may handle field names and defaults differently. - VLESS:
vless://commonly carries details such assecurity,type,sni, andflowin query parameters. - Hysteria2 and TUIC: Support depends on the client core version and available fields. Older Clash cores generally cannot recognize them completely, while mihomo supports a broader range.
When converting, do not check only the protocol name. Also verify transport settings, TLS, Reality, WebSocket paths, gRPC service names, UDP options, and the client fingerprint. Two links using the same protocol may still time out if their extension fields differ—even when the import appears to succeed.
How subscription converters work in practice
Subscription conversion is not simply a matter of changing a file extension. The converter first retrieves the source subscription, determines whether it is YAML, JSON, a Base64 node list, or plain-text URIs, then parses each input into a common internal node model. It applies filtering, renaming, and sorting before serializing the result according to the target client’s field rules. When the target is a complete Clash configuration, it must also apply proxy-group and rule templates.
- Fetch the source: Send an HTTP request to the subscription URL and handle redirects, compressed responses, and character encoding.
- Identify the input format: Inspect response headers, text structure, and protocol prefixes instead of relying only on the URL filename.
- Parse node parameters: Normalize server, port, authentication, TLS, and transport-layer fields into a common structure.
- Filter the results: Include or exclude entries based on node names, regional keywords, or regular expressions.
- Apply a template: Generate proxy groups, health-check groups, rule providers, and default fallback rules.
- Output the target format: Generate Clash YAML, a collection of single links, or another structure readable by the target client.
Why the node count changes after conversion
A lower count does not necessarily indicate a network problem. A converter may skip unsupported protocols, nodes missing required fields, or duplicate names. For example, if a source subscription has 86 nodes, 8 use protocols unsupported by the target core, 3 lack ports, and 2 are merged during deduplication, an output of 73 nodes is expected. The safest check is to compare the “read,” “skipped,” and “output” totals in the conversion log.
A higher count commonly results from template expansion or merged subscriptions. Two sources with 40 and 35 nodes may produce 75 nodes after merging, while proxy groups show more references because the same node can appear in “Manual Selection,” “Auto Test,” and “Failover” groups. The number of proxy-group references is not the actual node count.
The client User-Agent can change the response
Some subscription services return different formats based on the request’s User-Agent. A client identifying itself as Clash may receive YAML, while a regular browser may receive Base64 text or a management page. It is therefore common for browser content to differ from what the client downloads. During troubleshooting, check the response status code and parse errors in the client log instead of judging by the browser page alone.
Converting other formats into a Clash configuration
Node links alone still need proxy groups and rules
When converting a set of ss://, trojan://, or vless:// links into Clash YAML, the first step only generates proxies. Without proxy-groups, users cannot select groups in the interface; without rules, rule mode has no traffic destinations. A minimal usable template usually includes at least one manual selection group, one LAN direct rule, and one final MATCH rule.
Rules must remain ordered from specific to general. DOMAIN,api.example.com,DIRECT should come before DOMAIN-SUFFIX,example.com,Node Selection, while MATCH must be last. If a conversion tool reorders the rules, a domain that should connect directly may match the suffix rule first.
Confirm whether the target core is traditional Clash or mihomo
“Clash format” itself has capability differences. The fields common in traditional Clash configurations do not represent all of mihomo’s features; mihomo adds or extends fields for rule providers, DNS, TUN, Sniffer, and newer protocols. Importing a mihomo configuration into an older core may fail on an unknown proxy type or field, or silently ignore optional settings.
| Check item | What to verify after conversion | Common symptoms |
|---|---|---|
| Protocol support | Does the target core recognize the node type? |
Import fails or nodes do not appear |
| TLS parameters | Are sni, certificate verification, and the fingerprint preserved? |
Handshake failure or connection timeout |
| Transport layer | WebSocket path, request headers, and gRPC service name | The port is reachable but the proxy does not work |
| Proxy-group references | Do group entries exactly match node names? | Configuration validation says a proxy cannot be found |
| Rule providers | Remote URL, behavior type, and update interval | Rule-set download fails |
| DNS and TUN | Are address ranges, listening ports, and network-interface settings conflicting? | Domains cannot be resolved after TUN is enabled |
What is lost when exporting Clash YAML to another format
When a complete YAML file is exported as a collection of single links, global settings are lost first. mixed-port: 7890, LAN access, run mode, the external controller, DNS, and TUN settings do not belong in a single-node URI. Next to go are relationships between nodes, including selection groups, load-balancing groups, health-check groups, and their test URLs, intervals, and tolerances.
Rules also cannot be naturally attached to node URIs. Domain routing, IP ranges, process-name rules, rule providers, and final fallback behavior must be configured again in the target client. If the target is another complete configuration format, such as sing-box JSON, a converter can attempt to map these structures, but the routing semantics are not one-to-one and still require manual review.
Names and character encoding may change too
- Spaces, Chinese characters, and symbols in URL fragments require percent-encoding; incorrect encoding can truncate a name.
- Base64 may use the standard character set or the URL-safe character set. Mishandling padding can make the entire record impossible to decode.
- Duplicate node names are difficult to distinguish in Clash proxy groups, so converters usually append a number, which also changes group references.
- Names containing colons, hash signs, or leading or trailing spaces in YAML should be quoted; otherwise they may be interpreted as syntax.
Deployment options for a self-hosted subscription converter
The main reason to self-host is to parse subscription content in an environment you control. It can run on a local machine, home server, or private cloud host. Whatever the implementation, treat the “conversion API” and “management interface” as separate concerns: the former handles source URLs and output formats, while the latter manages templates, filters, and runtime logs.
Run it locally for single-user maintenance
A local service can listen only on the loopback address, such as 127.0.0.1:25500, preventing other devices on the same LAN from connecting directly. The client subscription URL points to the local interface, and the converter fetches the remote subscription. This avoids submitting the source URL to a public website, but automatic client updates fail when the computer sleeps or the service stops.
Restrict access when deploying to a server
A server makes updates convenient across multiple devices, but enable HTTPS, API authentication, request-size limits, and access-log rotation. If the conversion API accepts arbitrary URLs, also prevent it from accessing internal network addresses. At minimum, reject loopback, link-local, and private-network destinations, and restrict the final address after redirects.
Caching also requires care. If the upstream subscription updates every six hours, set the conversion cache to 15–60 minutes to avoid repeating the request every time a client starts. However, cache files contain complete node credentials, so storage permissions and expiration cleanup must be configured together. Do not log complete query strings; keep only the request time, output type, status code, and a redacted task identifier.
Put templates under version control
After a conversion service upgrade, default proxy-group names or field behavior may change. Give each template an explicit version, such as clash-template-2026-05.yaml, and validate changes in a test configuration before replacing the production template. Storing node subscriptions separately from rule templates prevents upstream updates from overwriting local routing logic.
Five checks after conversion
- Run a syntax check: Import the file into the client without enabling it immediately. Confirm that YAML indentation, duplicate names, and proxy-group references produce no errors.
- Verify node counts: Record the source, skipped, and output totals, paying particular attention to unsupported protocols and missing required fields.
- Test one node: Choose a known-working node for a latency test, then open an HTTPS page to confirm that TLS and transport parameters work. A latency value such as
80 msor200 msalone is not a substitute for a real connection test. - Check rule matches: Open the client’s connection log and visit domains expected to use a direct connection and a proxy, confirming that the matched rules and proxy groups follow the template design.
- Verify DNS and TUN: Test the system proxy first, then enable TUN if needed. If the system proxy works but TUN does not, check DNS hijacking, virtual-interface permissions, and routing conflicts instead of immediately blaming node conversion.
In desktop clients, configuration entry names vary by version. Commonly, go to “Configuration” → “Subscriptions” to update the remote file, then open “Proxies” to choose a proxy group; some clients place the update interval under “Settings” → “Preferences.” After updating, confirm that the active configuration has actually switched to the new file so you are not still testing an old cache.
Common conversion failures and troubleshooting order
The subscription URL opens, but the client reports a parse error
First confirm that the response is in a format the client needs. A normal page in a browser only proves that the HTTP request succeeded; if the response is a login page, quota notice, or HTML error page, Clash still cannot parse it. Then check the status code, the domain after redirects, and the beginning of the content. Tabs in YAML, incorrect indentation, or an unclosed quote can also prevent the entire configuration from loading.
The file imports, but every node times out
When every node times out, check the conversion parameters before replacing nodes one by one. Verify the server address, port, TLS sni, WebSocket path, gRPC service name, and Reality public key. If the source format uses extension parameters the target format cannot express, the converter may produce nodes that look complete but cannot connect.
Existing rules and groups disappear after an update
This usually means a “node subscription” was used to overwrite the local file as if it were a “complete configuration.” Instead, load remote nodes through a proxy provider, or apply a fixed local template during conversion. Keep changing node data separate from template-managed rules and groups so upstream updates do not rewrite the local routing structure.
Node names look correct, but proxy groups are empty
Check whether the proxy group lists node names statically or references a provider. Static names must match exactly, including spaces, capitalization, and any number appended by the converter. With regex filtering, also confirm whether a region name changed during renaming. For example, if “Hong Kong” is renamed to “香港”, a filter that matches only Hong Kong will return no results.
Practical advice for choosing a conversion method
If the subscription provider already offers a Clash- or mihomo-specific URL, use that format directly to minimize intermediate mappings. Add a conversion step only when the source and target are incompatible, multiple sources must be merged, or custom groups and rules are genuinely needed. The longer the conversion chain, the more caches, templates, and field mappings must be checked during troubleshooting.
For a temporary migration of a few nodes, convert single links locally. For long-term use with multiple subscriptions, create a fixed template and record the converter version. For automatic updates across devices, deploy a private service with authentication. Whatever the method, the real standard is not whether a file was generated, but whether it loads correctly, preserves node parameters, matches rules properly, and can be verified repeatedly during updates.