Look at what the subscription actually returned
A successful refresh means bytes came back from the server. A failed download looks different: the log carries timeout or 403 and never finishes. Here the data arrived and the core could not read it. Paste the subscription URL into a browser address bar and read the first few lines.
- A wall of letters and digits with no line breaks, possibly ending in equals signs. That is a base64 list of share links, the format v2rayN and its relatives consume. No
proxiessection for Clash to read. - Something opening with a brace, with
outboundsinside. That is a sing-box config: same job, different project. - HTML, a login page, or a bot-check screen. You received a web page. A mistyped link, an expired token, or a protection layer in front of the provider look like this.
A Clash profile is plain YAML, and its opening lines show fields like mixed-port and proxies. When parsing yields nothing, most clients only check whether the HTTP request succeeded, so the interface still claims success while proxies stays empty.
One link, several formats, picked by User-Agent
Providers serve different content from the same URL depending on the User-Agent header. Anything containing clash or mihomo gets YAML, v2rayN gets base64, a browser or a missing header gets the default. So gibberish in your browser does not prove the link is dead — it may only mean the provider took you for a different client. Ask twice and compare:
curl -sS -A "clash-verge/1.0" https://sub.host/link -o a.yaml
curl -sS -A "v2rayN/6.0" https://sub.host/link -o b.txt
Swap in your own address. If the two files differ, you have the answer. Most clients expose that header in the profile edit dialog, in a field called User Agent.
The nodes are in the file, the group just hides them
The other shape of this: proxies holds forty entries and the proxy page is still blank. Then read the groups, especially an override you copied from someone else:
proxy-groups:
- name: Auto
type: url-test
include-all: true
filter: "(?i)(HK|Hong)"
url: http://www.gstatic.com/generate_204
filter is a regular expression, and only matching node names enter the group. The provider renames Hong Kong 01 to HK-01, or the override you borrowed was written for another provider's naming, and the group empties out. Delete that line, reload, see whether they come back. exclude-filter fails the same way in reverse.
Some missing rather than all
- Words like
unsupportedorskipin the log: the core does not know that protocol and walked past those entries. A core update usually brings them back. - Exactly one node left, named something like plan expired or please renew. That is not a fault, that is an invoice.
- Duplicate names inside
proxies: later entries overwrite earlier ones, and the count in the interface comes out short.
proxies list and the groups are populated, everything above is ruled out. What is left is nodes that exist but will not connect — a latency-test and log question, not something another re-import will fix.