Per-tab proxy routing in Chrome
I route some traffic through a SOCKS5 proxy but not all of it. Video calls and streaming get slow if they go through the proxy, and most browsing doesn’t need it. I wanted to pick which tabs get proxied without switching the whole browser back and forth.
Chrome’s proxy API works at the browser level through PAC scripts. No per-tab support (SwitchyOmega has had open issues about this since 2017). But it can route by domain, which is close enough. I built an extension around that.
PAC script routing
Right-click a page, select “Route this tab through proxy.” The extension grabs the hostname, adds it to a list, and regenerates the PAC script:

function FindProxyForURL(url, host) {
if (dnsDomainIs(host, "app.example.com") || host === "app.example.com") {
return "SOCKS5 localhost:1080";
}
return "DIRECT";
}
“Per-tab” is really per-domain. Two tabs on the same host both get routed. Chrome API limitation.
There’s also an all-traffic mode that sends everything through the proxy, and a toggle to turn it off entirely.

Control API
The proxy address is configurable in settings. Optionally you can point it at an HTTP API that handles connect/disconnect (for example if the proxy lives in a Docker container you start and stop):
GET /status → {"connected": true}
POST /connect → {"auth_url": "https://..."} or {"connected": true}
POST /disconnect → {"disconnected": true}
With an API configured, the popup gets Connect/Disconnect buttons and polls for status. Without it, the extension is just a proxy switcher.
IPv6 gotcha
Chrome resolves DNS on the proxy side for SOCKS5. If the proxy returns IPv6 addresses first and the network is IPv4-only, connections fail silently with ERR_SOCKS_CONNECTION_FAILED. Took a while to figure out. Fix: precedence ::ffff:0:0/96 100 in /etc/gai.conf on the proxy host.