YouTube flags anonymous traffic that does not present valid browser signals. This guide explains how InnerTube mitigates bot detection through guest-session rotation and WebView-based Proof-of-Origin Token (PoToken) generation.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/faraasaaay/innertube-v2/llms.txt
Use this file to discover all available pages before exploring further.
What Is Bot Detection?
When YouTube determines that a request does not originate from a real browser or signed-in user, it blocks playback at the player or CDN level. Common symptoms in guest sessions:PlayerResponse.playabilityStatus.statusisLOGIN_REQUIRED- Stream URLs return HTTP
403even though the format list was populated playabilityStatus.reasoncontains phrases like"Sign in to confirm you're not a bot"or"Error 2000"
NOT_AVAILABLE_IN_THIS_COUNTRY or similar messages. InnerTube will not attempt session rotation for geo-errors because rotating the session cannot change the content’s regional availability.
BotDetectionMitigator
BotDetectionMitigator is a singleton that tracks guest playback failures and coordinates visitorData rotation. It is imported from com.music.vivi.utils.
Reporting Failures and Successes
CallnotifyPlaybackFailure() whenever a stream error occurs in a guest session. The method returns true if the error looks like a bot-detection signal (meaning rotation may help) and false if it is a geo-restriction or the user is logged in. The errorMessage parameter is optional and defaults to null.
notifyPlaybackSuccess() when a track begins playing successfully to reset the internal failure counter:
Error Classification Helpers
Two helper functions are available if you need to inspect error messages before callingnotifyPlaybackFailure:
isGeoError matches strings containing any of: "not available in your country", "not available in your region", "not available in this country", "not available in this region", "geo-restricted", "GEO_RESTRICTED", "NOT_AVAILABLE_IN_THIS_COUNTRY", "only available in certain countries", "country restriction", or "region restriction" (case-insensitive). isBotDetectionError matches "Sign in to confirm", "confirm you're not a bot", "automated queries", "Error 2000", "403", or "This content isn't available on this device" (case-insensitive).
Rotating the Guest Session
rotateGuestSession() is a suspend function that refreshes visitorData while preserving the user’s locale, so the new token is issued for the correct region:
- Snapshots
YouTube.locale(region and language). - Sets
YouTube.visitorData = null. - Calls
YouTube.refreshVisitorData()to obtain a new token. - Persists the new token to
DataStoreviaVisitorDataKey. - Resets the failure counter.
refreshVisitorData() fails, the locale is restored so that subsequent attempts use the correct region.
Integrating with Playback
The following pattern mirrors howYTPlayerUtils.playerResponseForPlayback() uses BotDetectionMitigator:
PoToken Generation
Some YouTube clients (WEB_REMIX and TVHTML5) require a Proof-of-Origin Token to accompany player requests. The PoToken proves that the request was initiated by a real browser or WebView environment running Google’s BotGuard JavaScript.
PoTokenResult
PoTokenResult is a simple class holding two tokens:
PoTokenGenerator
PoTokenGenerator is a high-level manager that owns a PoTokenWebView instance and handles its lifecycle automatically. Create one instance per session and reuse it across player requests.
getWebClientPoToken() returns null if:
- The device does not have a functional Android
WebView(e.g. running on a plain JVM). - The
WebViewimplementation is broken (detected automatically via BotGuard console errors).
PoTokenGenerator:
- Acquires a mutex to ensure only one
PoTokenWebViewexists at a time. - Creates a new
PoTokenWebViewif none exists, if the current one has expired, or if thesessionIdhas changed. - Generates the
streamingDataPoTokenonce per session (passed thesessionId). - Generates a fresh
playerRequestPoTokenfor eachvideoId. - On failure, retries once with a freshly recreated
PoTokenWebView.
PoTokenWebView
PoTokenWebView is the low-level component that runs BotGuard in a hidden Android WebView. You do not normally need to interact with it directly.
- Loads BotGuard JavaScript from the app’s
assets/po_token.html. - Makes HTTP requests to
jnn/v1/Createandjnn/v1/GenerateITvia OkHttp to obtain and exchange a BotGuard challenge. - Obeys
YouTube.proxy— all OkHttp requests from the WebView go through the configured proxy. isExpired: Boolean—trueafter the integrity token’s expiry window (minus a 10-minute safety margin).close()— must be called on the main thread to cleanly destroy the WebView and cancel all pending coroutines.
How to Use PoTokens with player()
PoToken generation requires a real Android
WebView. It will not work in pure JVM environments such as unit tests or server-side Kotlin. In those environments, PoTokenGenerator.getWebClientPoToken() returns null. Use a client that does not require PoTokens (such as ANDROID_VR_1_43_32) in environments without WebView support.