Subscription URLs and Config Formats: Separate the Download Link from Its Contents
A subscription URL is an entry point for retrieving a config, not a file format in itself. When a client requests the same HTTPS URL, the response might be Clash YAML, a Base64-encoded proxy list, or sing-box JSON. Some services return different content based on URL parameters, account settings, or the request's User-Agent header. So a link opening in a browser doesn't mean it can be imported directly into your client.
Troubleshoot in three stages: check whether the request succeeded, identify the response format, and confirm the target core supports its protocols and fields. An HTTP 200 only means the server returned a response; that response could still be a login page, a traffic-expiration notice, or an error in JSON. Pass one of these to a config parser and you'll often get an import failure, zero proxies, or a missing-field error.
What Each of the Three Common Formats Contains
| Format | Typical structure | Usually includes |
|---|---|---|
| Clash YAML | proxies、proxy-groups、rules | Proxies, proxy groups, and routing rules; a full config can also include DNS and listener settings |
| Base64 proxy list | Decodes to one protocol share link per line | Proxy connection details; usually no complete DNS, rules, or TUN settings |
| sing-box JSON | inbounds、outbounds、route | Inbound, outbound, and routing; a full config can also include modules such as DNS |
Clash YAML: A Full Config Is Not the Same as a Proxy Provider
A full Clash config can define proxies, proxy groups, and rules. Here's a structure-only example that routes traffic directly, with a mixed proxy port at 7890 listening only on localhost. It shows where fields go; it does not provide a remote proxy connection. If another local process is using that port, change it first.
mixed-port: 7890
allow-lan: false
mode: rule
proxies: []
proxy-groups:
- name: Manual Select
type: select
proxies:
- DIRECT
rules:
- MATCH,Manual Select
Some YAML files contain only a top-level proxies key and are intended to serve as a node source for proxy-providers. They're not full runtime configs: the main config must reference them by provider name and use them in a proxy group. Similarly, rule provider files often start with payload and can't be imported as proxy subscriptions.
“Clash format” also varies by core. mihomo builds on the Clash config system but adds protocol support and extension fields. A config accepted by mihomo isn't necessarily compatible with the original Clash core. Check which core is actually running rather than relying on the GUI client's name.
Base64: An Encoding, Not a Proxy Protocol
A typical Base64 subscription encodes multiple share links, such as ss://, vmess://, and trojan://, into one block. Decoding restores the text; it doesn't add proxy groups or routing rules. Some subscriptions return plain-text URI lists, and an individual share link may itself contain Base64. Distinguish the outer subscription encoding from encoding used by the protocol itself.
Base64 doesn't provide confidentiality. Decoded content may expose server addresses, ports, and authentication details. Treat subscription tokens and downloaded configs as credentials; don't include them in public screenshots, chat logs, or support-ticket attachments.
sing-box JSON: Use the Config Structure for Your Target Version
sing-box typically uses JSON for its config, but not every JSON array of proxies is a complete sing-box config. This structure-only example also routes traffic directly: it listens on localhost at 7890 and sends connections arriving at the mixed inbound to the direct outbound.
{
"inbounds": [
{
"type": "mixed",
"tag": "local-mixed",
"listen": "127.0.0.1",
"listen_port": 7890
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
}
],
"route": {
"final": "direct"
}
}
Test this example separately from the YAML above; don't run both at once and have them compete for the same port. Real subscriptions often include TLS, DNS, routing rules, and selectors, each with its own version requirements. Choose a target that matches the sing-box version used by your client rather than selecting “JSON” generically.
How Subscription Conversion Works: Parse, Map, and Build
A converter typically reads the source, parses it into internal proxy objects, then outputs the target config structure. Missing proxy groups, rules, DNS, and listener settings are often supplied by a conversion template. The result therefore depends both on the subscription and on the template and protocol versions supported by the converter.
- Identify the source format.Determine whether the content is a full config, a proxy provider, a plain-text URI list, or Base64 text that needs decoding first.
- Parse protocol parameters.Extract the server, port, authentication, transport, TLS, and protocol-specific options.
- Map target fields.Write proxies to Clash
proxiesor sing-boxoutbounds, and update name references. - Build the runtime config.Create proxy groups, routing, and DNS from the template, then validate the config with the target core.
For example, Clash proxies use server and port, while sing-box typically uses server and server_port. But changing key names alone won't convert a config: proxy-group references, TLS objects, transport settings, and rule actions all have different structures.
Fields and Semantics Most Likely to Be Lost in Conversion
An Imported Proxy Doesn't Mean Its Connection Settings Are Complete
Getting the server and port right is only the first step. TLS server names, certificate verification settings, ALPN, and WebSocket paths and Host headers can all affect the handshake. Reality public keys and short IDs, as well as protocol-specific UDP options, also require explicit converter support. Silently dropping unknown fields can leave a config that passes syntax checks but won't connect.
- Authentication and encoding:Special characters in passwords or usernames may use percent-encoding in URIs; decoding more than once can change the original value.
- Transport:Map WebSocket, gRPC, and other transport settings individually; don't keep only the proxy type.
- TLS:Preserve the server name and verification policy. If a certificate error occurs, investigate the cause instead of treating disabled verification as a universal conversion fix.
- UDP:The proxy protocol, server, and target core must all support the required capabilities. Converting formats doesn't add UDP support.
Rules, DNS, and TUN Settings Can't Be Copied by Name Alone
Clash proxy-groups and sing-box selectors or URL-test outbounds aren't exact equivalents. Even when both offer “automatic selection,” probe URLs, test intervals, and switching behavior may differ. If you rename proxies, update every reference in proxy groups and rules too; otherwise, you can end up with missing outbounds or empty groups.
Clash rules and rule providers can't be pasted directly into sing-box routing rules and rule sets either. Check rule order, domain-matching semantics, and the final fallback target. DNS settings such as Fake-IP ranges, domain filters, and resolver outbounds also affect traffic. Comparing proxy counts won't reveal these differences.
TUN is closer to a runtime environment setting than a proxy attribute. On macOS, virtual interface permissions, route takeover, and client service components are managed by the specific client. Even if TUN fields converted from a full config are syntactically valid, that doesn't mean the target Mac client has been authorized. First confirm that the local proxy inbound works, then enable TUN using the client's own workflow.
Import and Validation Steps on Mac
Identify the Core Before Choosing a Subscription Format
- Note the core name and version from the client's About or core information page. Record the client and core versions separately; menu paths vary by client.
- Choose the matching format on your subscription management page. For a mihomo client, prefer an option explicitly labeled Clash Meta or mihomo.
- Add the remote URL from the client's subscription or config page, refresh it, then select the imported config. Menu names vary between clients.
- Review the update log and config validation results. Note the proxy count, failed fields, and error line numbers before deciding whether conversion is needed.
Validate with the Core, Not the File Extension
If the matching command-line core is installed on your Mac, run the checks below in Terminal. The commands assume the files in the current directory are named config.yaml and config.json, and that the binaries are on your PATH. The GUI client's built-in validation works too; there's no need to replace its core just to check a config.
mihomo -t -f config.yaml
sing-box check -c config.json
A successful check means the target core accepts the config; it doesn't confirm that remote proxies are reachable, the account is valid, or the rules behave as expected. If validation fails, keep the original config and fix the first clear error. Avoid changing proxies, DNS, and rules all at once, or you'll lose a useful point of comparison.
If the client's actual mixed port is 7890, use the command below to specify an HTTP proxy and test the local inbound with an HTTPS request. It works regardless of whether Terminal reads the macOS system proxy settings.
curl --proxy http://127.0.0.1:7890 --head --max-time 15 https://example.com
Check the client's connection log at the same time to confirm which rule matched and which outbound was used. An HTTP response doesn't necessarily mean traffic went through a remote proxy: if the rule matched DIRECT, it connected directly. This command also can't verify TUN takeover because it explicitly specifies a proxy.
Common Import Issues and Post-Conversion Checklist
“Parse Error” or “No Proxies After Import”
First check whether the response is an HTML login page or an error message, then confirm the config's structure. Importing a rule file containing only payload through a full-config option, or a full config through a proxy-provider option, can both fail. For YAML, check indentation and avoid tabs; for JSON, check trailing commas and quotation marks. Renaming YAML text to .json won't make it valid JSON.
“The Proxy Count Is Right, but Some Proxies Won't Connect”
Pick one failing proxy and compare its protocol, port, TLS, and transport settings before and after conversion. If the errors affect only one protocol, first check whether the target core and converter support it. If every proxy fails, check the account status, local network, system clock, and DNS rather than blaming the format for everything.
“My Manual Fixes Disappear After the Next Update”
Refreshing a remote subscription usually regenerates or overwrites the config. For persistent changes to rules, proxy groups, or DNS, use the client's supported override, merge, or extension features, or maintain them in a conversion template you control. Check merge order and array handling before editing; otherwise, custom rules appended after the final fallback rule may never match.
- Keep the original subscription URL and response, and save converted files separately so you can roll back.
- Check proxy counts, names, and proxy-group references; distinguish intentional filtering from unexpected loss.
- Check the listening address, actual port, LAN access setting, and controller interface settings.
- Test regular HTTPS, any required UDP use cases, and both proxied and direct rules.
- Refresh the subscription once to confirm that custom settings still apply.
The key is to match the source content, converter, and target core. Full Clash YAML and full sing-box JSON can contain runtime policies; a Base64 proxy list usually provides connection details only. When converting, check proxy mapping and policy reconstruction separately, then configure the macOS system proxy or TUN routing.