Having two or three subscriptions is normal: a main one, a backup, and possibly something self-hosted.
Switching between config files in the client is tedious, and every switch drops all your connections. The better approach is merging them into one configuration with proxy-providers.
What proxy-providers is
It separates "where the nodes come from" out of the main config: the main config only describes policy groups and rules, while nodes are supplied dynamically by providers.
Basic syntax
proxy-providers:
main:
type: http
url: "https://main-subscription-url"
interval: 3600
path: ./providers/main.yaml
health-check:
enable: true
url: http://www.gstatic.com/generate_204
interval: 300
lazy: true
backup:
type: http
url: "https://backup-subscription-url"
interval: 3600
path: ./providers/backup.yaml
health-check:
enable: true
url: http://www.gstatic.com/generate_204
interval: 600
lazy: true
proxy-groups:
- name: "🚀 Select"
type: select
use: [main, backup] # every node from both providers
proxies: ["♻️ Auto", DIRECT] # other entries can be mixed in
- name: "♻️ Auto"
type: url-test
use: [main]
url: http://www.gstatic.com/generate_204
interval: 300
tolerance: 50The fields
| Field | Meaning |
|---|---|
type | http (remote subscription) / file (local file) / inline |
url | The subscription address |
interval | Update interval in seconds; 3600 = one hour |
path | Local cache path |
header | Custom request headers, for setting a User-Agent |
filter | Keep only matching nodes |
exclude-filter | Drop matching nodes |
exclude-type | Drop certain protocol types |
health-check | Health-check configuration |
override | Bulk-modify node attributes (Mihomo) |
Cleaning the node list with filter
Subscriptions frequently include pseudo-nodes like "Remaining: xx GB" or "Expires in: xx days", plus regions you have no use for.
proxy-providers:
main:
type: http
url: "..."
interval: 3600
path: ./providers/main.yaml
# keep only these regions
filter: "(?i)HK|Hong ?Kong|JP|Japan|SG|Singapore|US"
# drop these
exclude-filter: "(?i)remaining|expire|traffic|website|reset|subscription|test"
exclude-type: "ss|ssr" # drop certain protocols
health-check:
enable: true
url: http://www.gstatic.com/generate_204
interval: 300User-Agent: when you cannot get the Clash format
Some providers return a different subscription format depending on the UA:
proxy-providers:
main:
type: http
url: "..."
header:
User-Agent: ["clash.meta"]Common values: clash.meta, mihomo, clash-verge/v2.5.2, ClashforWindows/0.19.23.
If a provider never produces any nodes, the UA is the first thing to suspect.
health-check: why it is mandatory
Without health checks the nodes inside a provider have no latency data, so a url-test group has nothing to choose from.
health-check:
enable: true
url: http://www.gstatic.com/generate_204
interval: 300
lazy: true
expected-status: 204 # the status code expectedlazy: true skips checks when no traffic is passing, saving resources.
override: bulk-editing node attributes
A Mihomo feature for adjusting every node in a provider at once:
proxy-providers:
main:
type: http
url: "..."
override:
udp: true # force UDP on
skip-cert-verify: false # force certificate verification
additional-prefix: "[Main] " # prefix every node name
# additional-suffix: " ⚡"additional-prefix is genuinely useful with several subscriptions — one glance at the node list tells you where each node came from.
A complete multi-subscription configuration
proxy-providers:
subA:
type: http
url: "https://a.example.com/sub"
interval: 3600
path: ./providers/a.yaml
exclude-filter: "(?i)remaining|expire|website"
override:
additional-prefix: "[A] "
health-check: { enable: true, url: http://www.gstatic.com/generate_204, interval: 300, lazy: true }
subB:
type: http
url: "https://b.example.com/sub"
interval: 3600
path: ./providers/b.yaml
exclude-filter: "(?i)remaining|expire|website"
override:
additional-prefix: "[B] "
health-check: { enable: true, url: http://www.gstatic.com/generate_204, interval: 600, lazy: true }
proxy-groups:
# master switch
- name: "🚀 Select"
type: select
proxies: ["♻️ Best overall", "🅰️ Subscription A", "🅱️ Subscription B", "🇭🇰 Hong Kong", DIRECT]
# fastest across both subscriptions
- name: "♻️ Best overall"
type: url-test
use: [subA, subB]
interval: 300
tolerance: 50
lazy: true
# grouped per subscription, for comparison and diagnosis
- name: "🅰️ Subscription A"
type: url-test
use: [subA]
interval: 300
tolerance: 50
- name: "🅱️ Subscription B"
type: url-test
use: [subB]
interval: 300
tolerance: 50
# grouped by region across subscriptions
- name: "🇭🇰 Hong Kong"
type: url-test
use: [subA, subB]
filter: "(?i)HK|Hong ?Kong"
interval: 300
tolerance: 50
# primary/backup: fall to B when A dies
- name: "🛡 Primary/backup"
type: fallback
proxies: ["🅰️ Subscription A", "🅱️ Subscription B"]
interval: 300Local files and inline definitions
Local file (nodes you maintain yourself):
proxy-providers:
selfhosted:
type: file
path: ./providers/self.yaml
health-check: { enable: true, url: http://www.gstatic.com/generate_204, interval: 300 }The file format:
proxies:
- name: "My VPS"
type: trojan
server: my.example.com
port: 443
password: "pwd"Inline (written straight into the main config):
proxy-providers:
selfhosted:
type: inline
payload:
- name: "My VPS"
type: trojan
server: my.example.com
port: 443
password: "pwd"Diagnosing a provider that will not load
When updates will not come through
If the subscription address itself is unreachable from your current network, tell the provider to download through a proxy. Some versions support it directly:
proxy-providers:
main:
type: http
url: "..."
proxy: DIRECT # or the name of a policy groupWhere that is unsupported, enable "update subscriptions through the proxy" in the client.
How this differs from keeping multiple profiles
Clash Verge lets you save several profile cards and switch with a click. That is a different idea from proxy-providers:
| Multiple profiles | proxy-providers | |
|---|---|---|
| Switching | Click a card manually | No switching needed |
| Cost of switching | Core reload, connections drop | None |
| Merging nodes | Not possible | Groups can span subscriptions |
| Maintenance | Each profile independent | One main config |
| Suits | Genuinely different scenarios (work and home with entirely different rules) | Only the source of nodes differs |
If only the subscription source differs and the rules are the same, use providers; if the rules differ too, use separate profiles.
In short
- For several subscriptions, merge with proxy-providers rather than swapping config files
exclude-filterclears out "remaining traffic" pseudo-nodeshealth-checkis mandatory, or url-test has no data to work with- Give backup subscriptions a longer interval to cut pointless connections
additional-prefixmarks the source, which saves time when diagnosing- When loading fails, first look at what is in the cache file
Related: the five proxy-group types and node naming and grouping regex.
Related docs
A Clash / Mihomo config taken apart from top to bottom — ports, mode, DNS, proxies, proxy-groups, rules and rule-providers — with a minimal working config you can paste straight in.
What each policy group actually does, when to use it, the parameters that matter, plus a grouping structure you can copy wholesale and Mihomo's include-all and filter options.
Editing the downloaded config gets undone at the next update. How Clash Verge's extended config works: prepend/append/override syntax, merge order, and a set of useful snippets.