Somebody has built an automation that switches the VPN on when an incognito tab appears, and it does not reliably work. There is a structural reason for that, and it is worth understanding before tuning the automation. Android per-app VPN rules select application packages, and incognito is a state inside one package, so the rule cannot distinguish the two. A notification fires after the browser has already started working, so even a correct trigger arrives late. Work through the checks below in order; a failure at check four means the approach, not the configuration, needs to change.

Check one: confirm what the per-app rule can select

An Android VPN app builds its tunnel with allowed or disallowed application lists, and those lists take package names. Chrome in normal mode and Chrome in incognito mode are the same package, with the same user id and the same network permission, so a rule that includes or excludes Chrome applies to both identically. There is no tab-scoped identity for the platform to match against.

That is not a defect to work around; it is the granularity the API offers. If your requirement is Chrome traffic through the tunnel and everything else outside, a per-app rule expresses it exactly. If your requirement is only private tabs through the tunnel while ordinary tabs go direct, no per-app rule can express it, and no amount of notification logic will add a selector the platform does not have.

Watch for the package identity trap while you check. A beta or a vendor build is a different package from the stable browser, so a rule that covers one silently misses the other:

adb shell pm list packages | grep -i chrome

Check two: test whether the trigger can ever be early enough

A notification listener observes notifications it is allowed to see. Observation is not interception: the browser has already resolved the name and opened the connection by the time the notification exists, and nothing in that path waits for your automation to finish. A task that then launches the VPN client has to wait for the client UI, any consent prompt and the tunnel handshake, which is measured in seconds while the first request is measured in milliseconds.

The detection itself is brittle for a second reason. Notification text changes between versions and localizations, so a pattern matched against one release stops matching after an update, and the failure is silent. A missing notification is not evidence that private browsing is absent; it may only mean the string changed or the channel was silenced.

There is a legitimate version of this workflow, and it is ordered rather than reactive: connect the approved VPN first, confirm a readiness signal that actually proves the tunnel is carrying traffic, then open the incognito session through supported browser controls, and stop if the readiness check fails. That protects the session you are about to start without pretending to protect one that is already running.

Check three: audit the permission you are about to grant

Notification access is a sensitive grant that lets a service read notifications from every app, not just the browser. Granting it to an unfamiliar automation tool to watch one browser state is a poor trade, and the access persists after the experiment ends. Accessibility-driven taps are worse: they are a scripting layer over the UI, not a supported VPN control interface, and they break on any layout change.

Before granting anything, ask whether the same outcome is reachable with a supported mechanism. If the answer is a policy requirement, it usually is: the platform can enforce a tunnel for an app or a profile without any listening service at all.

Check four: use always-on and blocking when the requirement is enforcement

If the browser must never communicate outside the tunnel, enforcement belongs in platform settings, not in a macro. Android supports an always-on VPN with a blocking mode that prevents traffic when the tunnel is not established, and managed devices can have it applied by policy. Confirm what the device currently has rather than assuming:

adb shell settings get global always_on_vpn_app
adb shell settings get global always_on_vpn_lockdown

A non-null app value means a package is configured as always-on, and a lockdown value of 1 means connections outside the tunnel are blocked. The pair is what turns a best-effort habit into a guarantee, and it also removes the race entirely, because the tunnel is established before application traffic is allowed.

Two boundaries are worth stating while you are here. Work profiles carry their own VPN configuration, so a rule verified in the personal profile says nothing about the work one. And a separately installed browser, a custom tab opened by another app, or an in-app webview is a different package or context with its own routing, so verify the actual package rather than assuming a differently styled window is a separate domain.

Check five: write the workflow down and test the failure path

Whatever you choose, document the order and the abort condition. For the convenience workflow that means: tunnel up, readiness proven, incognito opened, and a hard stop if readiness fails. For the enforcement path it means: always-on app configured, lockdown enabled, and the expected behaviour when the tunnel cannot come up at all, which is no traffic rather than unprotected traffic.

Then test the failure, not just the success. Disconnect the tunnel during a session and watch what the browser does; block the VPN app process and confirm nothing leaks. Finally, keep the two privacy models separate in the user documentation: incognito controls temporary browser state and does not hide traffic from the network, while a VPN carries traffic but does not erase logins or anything submitted inside the private session.

Tënë sô zo