Per-app proxy

Send chosen apps on a phone through an upstream SOCKS5 or HTTP proxy, without root, check the address they appear from, and keep credentials out of your scripts.

proxy sends the apps you choose through a proxy server of your choice, while the rest of the phone, and Droidline's own connection to your PC, keep using the normal network. A typical use is giving each phone on a shelf its own outgoing address for one app.

Before you start

  • Android 10 or later.
  • The VPN permission, allowed once from the app's Setup tab. Until then, proxy fails with NO_PERMISSION.
  • No other VPN app active on the phone. Android runs one VPN at a time, so apps such as Tailscale or WireGuard cannot run alongside it.
  • An upstream proxy you are allowed to use: socks5:// or http://, with or without a user name and password.

Turn it on, check it, turn it off

d.proxy("socks5://user:pass@203.0.113.10:1080", app="com.android.chrome")
print(d.proxy_check("com.android.chrome"))
# {'active': True, 'ip': '203.0.113.10', 'upstream': 'socks5://203.0.113.10:1080', 'error': ''}
d.proxy("off")
await d.proxy("socks5://user:pass@203.0.113.10:1080", { app: "com.android.chrome" });
console.log(await d.proxyCheck("com.android.chrome"));
// { active: true, ip: '203.0.113.10', upstream: 'socks5://203.0.113.10:1080', error: '' }
await d.proxy("off");
droidline proxy socks5://user:pass@203.0.113.10:1080 --app com.android.chrome
droidline proxy_check com.android.chrome
droidline proxy off

app takes one package name or a list. proxy_check makes a request through the upstream from the phone and reports the address the outside world sees for that app.

Keep passwords out of your scripts

Save a proxy on the PC once, under a short name. The password goes into the server's secret store (DPAPI on Windows), not into config.toml or your code:

droidline proxy add kr1 socks5://user:pass@203.0.113.10:1080
droidline proxy list

Then refer to it with @ and the name:

d.proxy("@kr1", app=["com.android.chrome", "com.example.app"])
await d.proxy("@kr1", { app: ["com.android.chrome", "com.example.app"] });
droidline proxy @kr1 --app com.android.chrome,com.example.app

How it works

The app starts a VPN that applies only to the chosen apps and sets their proxy to a small proxy server inside the Droidline app. That local proxy forwards each connection to your upstream:

  • http://host:port, with optional user:pass, using HTTP CONNECT.
  • socks5://host:port, with optional user:pass. Host names are resolved by the proxy, not by the phone.

All other traffic from the chosen apps is dropped instead of leaking past the proxy. An app that ignores the system proxy setting therefore loses network access rather than connecting directly. Chrome and most apps built on WebView or OkHttp follow the setting.

When it fails

proxy fails with PROXY_FAILED and a reason:

ReasonUsually means
authWrong user name or password
timeoutThe proxy did not answer; check the address and that the phone can reach it
refusedNothing listens on that port
protocolThe URL says socks5 but the server speaks HTTP, or the other way round

proxy_check reports the same problem in its error field without failing.

Limits

  • One upstream per phone at a time. Calling proxy again with a different URL replaces it.
  • While the proxy is active, the local proxy inside the app listens on the phone's loopback address. Other apps on the same phone could use it if they tried; on a phone you control, that only matters if you install apps you do not trust.
  • Use proxies you have the right to use, for services that allow it. See the terms.