On a per-gigabyte proxy, the meter does not know what you meant. We bill request bytes plus response bytes for everything that passes through the proxy: your scraper’s pages, and also the game update, the cloud sync and the video tab that happened to be open when you flipped a switch. Clash Verge Rev is very good at deciding what goes through a proxy, which makes it just as good at sending your whole machine through one by accident.
The short version: use Rule mode, end your rules with MATCH,DIRECT, put no-resolve on every IP rule, and then check our usage log for hosts you never listed. Clash Verge supplies no proxies; this is about the one you bought, added as a node the way our Clash Verge setup guide shows.
Every config below ran on the Mihomo core that Clash Verge Rev is built on (v1.19.32), with a proxy we started ourselves on the same machine standing in for ours, and the log excerpts come from those runs. The app’s labels are quoted from its own interface text; we did not click through the app.
What each setting puts on the meter
| Setting | Goes through your node | Ends up on the meter |
|---|---|---|
| Global mode, your node picked | Every connection Clash receives | Everything |
| Rule mode, last rule MATCH to your group | Every connection no earlier rule sent elsewhere | Everything you did not exclude |
| Rule mode, IP-CIDR to your group without no-resolve | Any hostname that resolves into the range | Sites you never listed |
| Rule mode, last rule MATCH,DIRECT | Only what a rule names | What you listed |
| Direct mode | Nothing | Nothing, and your job is not proxied either |
Global mode: the whole machine on the meter
Clash Verge describes Global mode as “forward all network requests through the selected proxy”, and it means it. Pick your node there and every connection goes to it without a rule being consulted; in our run, each one was logged using GLOBAL and nothing else. Global is handy for a two-minute test of whether a site behaves through the proxy. Left on with System Proxy, it bills you for every browser tab, updater and sync client that follows the system setting. With Tun Mode, add the apps that do not.
A catch-all rule does the same thing, quietly
Rule mode feels safe, but a rule list is only as tight as its last line. If that line names your group instead of DIRECT, everything you did not list goes through your node anyway. In our run, a host that appears in no rule was logged match Match using METERED[monkey] and our stand-in proxy carried it. Before you add your node to a profile somebody else wrote, read its last rule on the Rules page.
The rule list that keeps the meter for the job
One node, one group, one line per site the job needs, and a fallback that goes direct. Replace the host, port and login with yours from the dashboard, and the two domains with your targets:
proxies:
- name: monkey
type: http
server: gate.example.com
port: 8000
username: USER
password: PASS
proxy-groups:
- name: METERED
type: select
proxies: [monkey]
rules:
- DOMAIN-SUFFIX,target-site.com,METERED
- DOMAIN-SUFFIX,other-target.com,METERED
- MATCH,DIRECTBoth targets were logged match DomainSuffix(…) using METERED[monkey]. A third host was logged match Match using DIRECT, and the stand-in proxy never saw it at all. Three details worth knowing:
DOMAIN-SUFFIXcovers subdomains, however deep, but not lookalikes:www.target-site.comwent to the node,not-target-site.comwent direct.- List every host the job really needs. If the site loads its data from a second domain, an API or a CDN, that request leaves from your own IP unless it has a line too. Cheap on the meter, but the site then sees one visit from two addresses.
- A
selectgroup sends nothing on its own. Left idle in our run, it put no traffic through the node. That is not true of every group type; see the small requests below.
IP-CIDR without no-resolve: the rule that bills sites you never listed
Say you add a range of addresses for your node and forget one word:
rules:
- DOMAIN-SUFFIX,target-site.com,METERED
- IP-CIDR,203.0.113.0/24,METERED
- MATCH,DIRECTTo check a hostname against an address range, Clash first has to look it up, on your machine. So every connection that gets past the domain rules is resolved, and any site whose address lands in the range goes to your node, listed or not. Big hosting and CDN ranges serve many unrelated sites, so one range can sweep in far more than you meant. In our run, with a loopback range standing in for this one, two hostnames that appear in no rule were logged match IPCIDR(…) using METERED[monkey], and the stand-in proxy carried both.
The fix is the word on the end:
- IP-CIDR,203.0.113.0/24,METERED,no-resolveWith no-resolve, hostnames skip the rule and fell through to MATCH,DIRECT in our run, while a connection made straight to an address in the range still matched and used the node. In Clash Verge’s Edit Rules, that is the No Resolve switch. The trap works the other way round too: an IP rule to DIRECT without no-resolve, placed above your domain rules, can pull a listed site off the node, and the job quietly runs from your own IP.
One app only: PROCESS-NAME
If the job is one program, you can route by program instead of by site:
rules:
- PROCESS-NAME,curl,METERED
- MATCH,DIRECTOn Linux, curl went through the node while wget and Python, pointed at the same Clash port, went direct. Python showed up as python3.12, not python, so the name has to be the one Clash sees: check the Process column on the Connections page before you trust the rule. The lookup comes from the operating system, and we only tested it on Linux, where it missed: in 80 curl connections fired back to back, 12 failed the lookup and fell through to MATCH,DIRECT. Treat it as a convenience, and give the target a domain rule too. Remember that the rule bills everything that program talks to, update checks included.
Small requests that still count
url-testandfallbackgroups test their nodes by sending a request through each one. By default that happened at start-up and again after the group was used. Withlazy: falseit happened on every interval whether we used the group or not: aHEADrequest every five seconds withinterval: 5.- Delay check on the Proxies page measures a node by fetching a test URL through it. The core’s delay test reached our stand-in proxy like any other request.
Each of these is tiny. Each is also a request through your proxy, so it lands in your usage log. With one node there is nothing to choose between, so a select group is the one to use.
Check it against the usage log
Your rules are what you meant; our usage log is what happened. Every request through us is logged with its host and the bytes we billed, and you can export the log as CSV. Export a day, save your Clash profile next to it, and run this. It totals requests and bytes per host and flags every host that no DOMAIN or DOMAIN-SUFFIX rule sends to the node:
import csv
import re
import sys
from collections import defaultdict
HOST, BYTES_IN, BYTES_OUT = "host", "bytes_in", "bytes_out"
rules = open(sys.argv[1]).read()
exact = set(re.findall(r"^\s*-\s*DOMAIN,([^,\s]+),", rules, re.M))
suffixes = re.findall(r"^\s*-\s*DOMAIN-SUFFIX,([^,\s]+),", rules, re.M)
def listed(host):
return host in exact or any(host == s or host.endswith("." + s) for s in suffixes)
totals = defaultdict(lambda: [0, 0])
with open(sys.argv[2], newline="") as f:
for row in csv.DictReader(f):
entry = totals[row[HOST]]
entry[0] += 1
entry[1] += int(row[BYTES_IN]) + int(row[BYTES_OUT])
for host, (requests, moved) in sorted(totals.items(), key=lambda item: -item[1][1]):
flag = "" if listed(host) else " <- no rule sends this here"
print(f"{host:<36}{requests:>6}{moved:>14,}{flag}")python3 check_rules.py monkey.yaml usage.csvThe column names are the ones the usage API uses; if the header row of your export says something different, change the three constants to match it. The script only reads domain rules, so with a PROCESS-NAME rule every host gets flagged and you read the list yourself. A flagged host near the top of the list is something else on your node: Global mode left on, a catch-all last rule, an IP rule without no-resolve, health checks, or another machine using the same login. The bill audit goes one step further and checks our byte counts against yours.
What a stray gigabyte costs
The same as a wanted one. Residential runs from $5.50/GB down to $1.75/GB from 1,000 GB, and the meter cannot tell your scraper from a launcher update. Nothing on this page makes a gigabyte cheaper; it stops you buying ones you did not mean to. Making each wanted page smaller is the other half, in nine ways to move fewer bytes. And if the job can run from a dedicated datacenter IP, that line comes with no traffic meter, and none of this arithmetic applies. Mo’s rule, for the record: if you did not write a rule for it, it should not be on your bill.
Top-ups start at $5.
One shared datacenter IP for 30 days is $1.25. A single gigabyte of residential is $5.50. The balance never expires.