Proxy CaptainProxy switcher
Chrome · Brave · Edge · Firefox

The toggle is green. Is the traffic?

Per-site proxy routing, and — on Chrome, Brave and Edge — a check that tells you when your browser is lying about being proxied. Chromium strips SOCKS credentials before they leave, and takes a PAC’s direct fallback silently, with the toggle still green.

Connection check example result
Through your proxy 203.0.113.74
Proxy removed 198.51.100.12
PROXIEDThe readings differ. Your traffic is leaving through the proxy. socks5h · gw.corp.example:1080 · Firefox
Runs only when you press it. No cookies sent, no redirects followed, and the one address it asks — www.cloudflare.com/cdn-cgi/trace — is named in the privacy policy, along with the two alternatives you can switch it to.
Through your proxy 198.51.100.12
Proxy removed 198.51.100.12
NOT PROXIED Same address both times. Chromium dropped your SOCKS credentials and connected direct. crbug 40323993 — never implemented. Use HTTP/HTTPS auth here, or Firefox.

Two readings, compared. Testing that a proxy server answers is table stakes — plenty of tools do it. This asks the other question: did your browser’s packet actually go through it?

Free, no account: 3 proxies · 20 rules · all four schemes · JSON import & export.

The silent fallback

Your browser will drop your SOCKS password and never mention it.

Not a bug in any switcher, and not fixable by one. It is how Chromium works — tracked upstream as “SOCKS5 authentication support”, never implemented.

You save a SOCKS proxy with a username and password.

Every switcher accepts it. So do we — the form takes socks5://user:pass@gw.example:1080 like anything else.

Chromium strips the credentials.

The proxy API has no credential field and a PAC result line cannot carry one. Your password is stored, displayed — and never sent.

Your proxy refuses the anonymous connection.

As it should. It was configured to require authentication.

What happens next depends on the PAC.

Offer Chromium a direct fallback and it takes one — no warning, no console line, the toggle still green and your traffic leaving bare. Configure the SOCKS proxy directly instead and it refuses outright. Neither answer authenticates.

Plenty of tools can test a proxy server. The failure that matters is different: the proxy is fine — your browser just isn’t using it.

Chromium issue 40323993 — “SOCKS5 authentication support”, formerly crbug 256785. Still not implemented.

SwitchyOmega and SmartProxy both accept SOCKS credentials on Chromium — and say nothing about any of this. We warn at the credential field, in the popup, and in the check result.
On Firefox the browser is capable of it, and we send the credentials. Gecko’s proxy API takes a username and a password on every request, and the engine sets both — pinned by unit tests. The ledger says which parts have been watched working and which have not. proxy.onRequest · engine/firefox.js
We check this against a real browser, not against our own opinion of it. A test points a real Chromium at a credentialed SOCKS5 proxy and requires that it fails to authenticate. It needs a live browser, so it runs on demand rather than on every build. test/e2e/chromium.e2e.test.js
Every row below was watched in a real browser
How to read it. tier A, no extension is the browser on its own, driven at a real proxy through its own settings with Proxy Captain not installed — platform behaviour, not our code. tier B is the shipped zip, installed in Brave and in release Firefox 153 and doing the work itself; it is ordinary tests now, and it produced the last four rows. test/e2e/packaged.e2e.test.js
chromiumtier A · credentialed SOCKS5 → refused outright, no silent fallbackobserved
chromiumtier A · a PAC offering a DIRECT fallback → went direct, silentlyobserved
firefoxtier A · SOCKS5 + remote DNS, no credentials → carriedobserved
chromiumtier A · an HTTP proxy carried it, and changing the browser’s proxy setting moved where traffic left fromobserved
firefoxtier A · the same, in Gecko: the browser’s own setting moved where traffic left fromobserved
chromiumtier B · the shipped zip loads in Brave, and its toggle moved traffic direct → alpha → beta → directobserved
firefoxtier B · the shipped add-on routed SOCKS5 with credentials — the headline claimobserved
firefoxtier B · with the flag off, the shipped add-on stopped sending traffic through our proxy, and sent it again when the flag went back onobserved
firefoxtier B · clicking the switch in the real popup stops the traffic, and clicking it again restores it popup/popup.jsobserved
How these were tested, what is fixed, and what no browser has watched yet
Authenticated SOCKS5 on Firefox is measured, not promised. The origin saw the request arrive from a SOCKS5 proxy that refuses anonymous clients at the handshake, alongside an unauthenticated control leg, so the difference can only be the credentials. test/e2e/packaged.e2e.test.js asserts “SOCKS5 WITH credentials genuinely routes — the product’s headline claim” against packages/proxycaptain-firefox.zip
The off switch on Firefox is fixed. Turning Proxy Captain off used to leave your traffic going through the proxy while the popup said “Proxy is off”. Two independent causes, both closed. The request path reads the switch now, watched against the shipped add-on and switched back on in the same run. engine/firefox.js · test/e2e/packaged.e2e.test.js
The second cause was the half a person actually touches: the popup saved your change to a storage slot the engine does not read, so the click never arrived while the label flipped. Fixed, then watched — and the origin, never our own UI, is what reports the traffic moving. popup/popup.js · test/e2e/packaged.e2e.test.js asserts “clicking the real popup toggle stops proxying”
A fresh install leaves a proxy you already set alone. It used to throw that proxy away on the very first request while the switch read on. That is fixed: a new install now defers to the proxy you set in Firefox yourself, measured at the origin against the packed add-on, with the control leg taken in the same profile before the add-on was there. engine/firefox.js
The options page carries the same fix, and no browser has run it. It saved the same way, so on Firefox nothing it changed — not a proxy, not a rule, not a profile — reached the engine. Same one-line fix, landed the same hour. There is no row above, because there is no assertion to cite. options/options.js
One knob we wrote and did not wire up. A browserFallback mode — override the browser’s own proxy for named sites only — is never read off stored settings, so no setting turns it on. engine/firefox.js

Built to report, not reassure

A status light that is allowed to say “I don’t know.”

The check reads your egress address twice — once with the proxy in the path, once with it deliberately out — and compares. The work went into the honest negatives: the answers most tools round up to green.

You press it. It never runs itself.

An egress check is an outbound request to a third party, so it happens only when you click — never on install, on startup, or on a timer. One named address, Cloudflare’s cdn-cgi/trace, with no cookies and no redirects.

userInitiated: required · credentials: omit · redirect: error

It refuses to guess.

A proxy on your own LAN egresses through the same address you do, so matching readings prove nothing there — that verdict is inconclusive, and it says so. “Not proxied” is stated only when the mechanism is known, and it names the cause.

SAME_EGRESS_POSSIBLE → inconclusive, never a green light

Warned before, not diagnosed after.

Type a username into a SOCKS proxy on Chrome and the warning appears under the field as you type — the same sentence in the popup, the options page and the check result.

needsChromiumWarning() · one sentence, everywhere

On Chrome, Brave and Edge. The check does not exist on the Firefox build: the Gecko engine imports no verifier and answers no message from the popup, so the button there reports “could not verify” and never a verdict — a missing feature on Gecko, not a broken one. engine/firefox.js

PROXIED readings differ NOT_PROXIED with the cause named INCONCLUSIVE agreement proves nothing here NO_PROXY target is DIRECT ERROR check could not run REFUSED not user-initiated

One extension, two engines

The same rules, routed the way each browser actually allows.

On Chromium your rules compile to a PAC applied through chrome.proxy; on Firefox every request is answered live through proxy.onRequest. Same data, same precedence — and here is exactly where the two differ.

CapabilityChrome · Brave · EdgeFirefox
HTTP / HTTPS / SOCKS4 / SOCKS5 proxiesAll four schemesAll four schemes
HTTP / HTTPS proxy with username & passwordAnswered on the 407 challenge, for your stored proxy only — never a blanket reply.WorksWorks
SOCKS with username & passwordChromium strips the credentials and silently connects direct.Impossible — we warn youCarried nativelyGecko takes the credentials on every request, and the engine sets them. This row has been watched happen against the shipped add-on in release Firefox 153 — see the ledger.
Remote DNSsocks5h:// and socks4a:// resolve host names at the proxy, not on your machine.SupportedSupported
The connection checkReads your egress address twice — with the proxy in the path and deliberately out — and compares.WorksThe verifier is a service-worker subsystem — sw.js owns it.Not in this buildA missing feature on Gecko, not a broken one — see above.
When a proxy diesLoud, visible errorNever a silent retry over a direct connection — a single-token PAC by design.Reported honestlyFirefox’s own direct-failover pref is outside any extension’s reach.

Per-site routing

Seven tiers of precedence, and it tells you which one answered.

Corp hosts through the corp gateway, the staging IP range direct, everything else through your default — written as rules, resolved in a fixed order. Every routing decision carries a reason code, so “why did this site go direct?” has an answer.

Most specific wins, by definition — not by luck

Exact host beats wildcard, longest wildcard beats shorter. A leading *. means the domain and its subdomains; a * anywhere else never crosses a dot, and *.example.com can never be matched by example.com.evil.net. Rules resolve identically in the popup preview, the live engine and the generated PAC.

Bad rules are refused, not “repaired”

A malformed CIDR is handed back with the field named — never quietly rewritten into a pattern that matches everything. A pathological regex is caught before it is stored, because inside a PAC there is no timeout to save you.

DIRECT is a decision, not an accident

Sending a site around the proxy takes an explicit DIRECT target. When nothing matches and no default exists, the result says so — with a reason code, so unproxied traffic is always explained.

Precedence — first tier that answers, wins
1intranet.corp.exampleexact host
2*.corp.examplelongest wildcard
310.20.0.0/16PROCIDR
4/^docs-\d+\.example$/PROregex
5stagingPROkeyword
6profile defaultthe active profile
7global proxyeverything else
Free writes tiers 1–2 — host and wildcard rules, up to 20, which covers most real routing tables. Pro adds CIDR, regex and keyword rules, without limits.

Fail loud, never open

Every failure path ends in an error you can see — not a quiet direct connection.

pacScript.mandatory = true

A broken config stops traffic, it doesn’t leak it

Chrome’s default for an unparseable proxy config is “just go direct”. We flip the one flag that makes it fail visibly on the tab instead.

single-token PAC

No silent failover past a dead proxy

A PAC may legally answer “try the proxy, then go direct”. Ours never does — a dead proxy is a visible connection error, not invisible bare traffic.

levelOfControl

We check who actually holds the setting

Another extension or an enterprise policy can take proxy control — and the API still reports success. We read the control level after every apply and report “blocked” honestly.

no dnsResolve()

The PAC never leaks lookups

PAC helpers like dnsResolve leak the very host name you are routing, before any connection is made. The generated script never calls them.

Your data, portable by policy

Arrive with your old config. Leave with everything.

Import from SwitchyOmega backups (.bak) and SmartProxy exports, or from Proxy Captain’s own JSON. JSON export and import are free, forever — portability is never the hostage. Every import ends in an accounting.

Import report SwitchyOmega .bak
proxies7 read → 7 kept
rules21 read → 16 kept
profiles9 read → 8 kept
dropped6, each one named in the report
socks auth2 proxies Chromium cannot authenticate
Nothing is dropped in silence, and the figures add up. Five rules and one profile did not survive — six, the dropped count — and each has a warning naming the record. A doubtful rule fails toward the proxy: over-proxying is inconvenient, a widened bypass would be a leak. That last line is often the first time a SwitchyOmega user learns their SOCKS credentials were never reaching Chrome.

Where proxy passwords are kept

In plain text, in your browser’s local extension storage. An extension has no OS keychain, and a key stored next door encrypts nothing. They never leave your machine, are excluded from browser sync, and exports redact them by default — but anyone with your OS user account can read them. Full detail in the privacy policy.

What never leaves your machine

Rules, proxies, credentials, browsing — none of it is uploaded. No analytics, no telemetry, no content scripts, no reading of any page. Exactly three things ever make a request: your own browsing through your proxy, the check you press, and the licence lookup to api.montereystudio.com.

Pricing

Free does the job. Pro removes the ceilings.

The free tier is a working proxy switcher, not a demo — every scheme, both browsers, the connection check on Chromium, and your data free to leave whenever you like.

Free NO ACCOUNT

$0Installed is signed in. Works offline.

  • 3 proxies — HTTP, HTTPS, SOCKS4 and SOCKS5, credentials included
  • 20 rules — exact-host and wildcard, with the full precedence engine
  • Global on/off toggle and per-site routing
  • The connection check on Chrome, Brave and Edge — every honest verdict
  • JSON export and import — portability is never the hostage
  • Import from SwitchyOmega and SmartProxy

Pro ONE-TIME

$19Bought once. No subscription, no renewal, no seat count.

  • Unlimited proxies
  • Unlimited rules
  • Rule profiles — Work, Home, Travel, switched in one click
  • Regex, CIDR and keyword rules
  • PAC export — take your ruleset to any device that speaks PAC
Hit a free cap and nothing is deleted. Entries past the cap are kept, marked inactive, and wake up the moment you upgrade.

What Pro will never claim: if a capability isn’t running in the shipped code, it isn’t on this page.

Questions, answered plainly

The answers other listings hope you won’t ask for.

Why does it need the <all_urls> permission?
A proxy rule can be written for any host, so the routing decision has to be available for any host — and it is what lets the proxy’s authentication challenge reach us. It is not used to read pages: there is no content script in this extension, and no blocking listener that sees request bodies. Every permission is justified line by line in the privacy policy.
Does the connection check phone home?
No. It runs only when you press it — never on install, startup or a schedule — and asks one named endpoint, Cloudflare’s cdn-cgi/trace, what address your request arrived from. No cookies, no redirects, and no analytics or telemetry anywhere in the extension.
Can you make authenticated SOCKS work on Chrome?
No — and neither can anyone else. chrome.proxy has no field for SOCKS credentials and onAuthRequired never fires for SOCKS. Use HTTP/HTTPS proxy authentication on Chromium — that challenge does reach an extension, which is the whole asymmetry — or use Firefox, where the proxy API carries SOCKS credentials and we set them.
What happens when my proxy goes down?
You see a connection error on the tab. The alternative — quietly retrying over a direct connection — is how other configurations leak traffic while the UI stays green. Failing visibly is deliberate.
Is the free tier actually usable?
Yes: 3 proxies and 20 host/wildcard rules, all four schemes with credentials, both browsers, the connection check on Chromium, and JSON export and import — with no account. Go over a cap and nothing is deleted: extra entries are kept and marked inactive, and wake up when you upgrade or prune back under.

Stop trusting the toggle. Start checking the traffic.

Free: 3 proxies, 20 rules, all four schemes, no account. Import from SwitchyOmega, export whenever you like.