Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/faraasaaay/innertube-v1/llms.txt

Use this file to discover all available pages before exploring further.

InnerTube can operate in two distinct modes depending on whether you supply a session cookie. Unauthenticated mode works for most read-only operations, while authenticated mode unlocks library management, social features, and upload capabilities.

Unauthenticated vs. Authenticated

No cookie is required. The library sends requests without an Authorization header. This covers the vast majority of read-only operations:
  • search(), searchSuggestions(), searchSummary()
  • album(), artist(), playlist(), podcast()
  • player() — stream URL resolution for public content
  • home(), explore(), newReleaseAlbums(), moodAndGenres()
  • next(), queue()
This is appropriate for anonymous users or app demos.

The InnerTube HTTP layer implements YouTube’s cookie-based authentication protocol automatically. When YouTube.cookie is set and a request method opts into login, two things happen:
  1. The raw cookie string is attached as the Cookie request header.
  2. A SAPISIDHASH Authorization header is computed and appended:
Authorization: SAPISIDHASH {currentTimeSec}_{sha1("{currentTimeSec} {SAPISID} {ORIGIN}")}
Where ORIGIN is https://music.youtube.com. This SHA-1 hash ties the credential to the current timestamp and origin, preventing replay attacks from other origins. The library handles all of this internally. You only need to supply the cookie string.

Setting Up Authentication

// Set the cookie string obtained from a logged-in YouTube session
YouTube.cookie = "SAPISID=AbCdEfGhIj; __Secure-3PSID=xxxx; SID=yyyy; ..."

// Provide the account's dataSyncId for personalised responses
YouTube.dataSyncId = "1234567890987654321||..."

// Maintain session continuity with visitorData
YouTube.visitorData = YouTube.visitorData().getOrNull()

// Optionally force login headers on all browse requests
// (e.g. for a personalised home page)
YouTube.useLoginForBrowse = true
Once these properties are set, all subsequent authenticated method calls will automatically include the cookie and computed hash.
YouTube does not provide an OAuth flow for InnerTube. The typical approach is to extract cookies from a logged-in YouTube session in a WebView:
// Inside a WebViewClient after the user has logged in to YouTube Music
webView.evaluateJavascript("document.cookie") { cookieValue ->
    // cookieValue arrives as a JSON-quoted string
    val raw = cookieValue.trim('"')
    YouTube.cookie = raw
    // Persist securely
    encryptedPrefs.edit().putString("yt_cookie", raw).apply()
}

// Alternatively, use CookieManager
val cookieManager = CookieManager.getInstance()
val cookies = cookieManager.getCookie("https://music.youtube.com")
YouTube.cookie = cookies
At minimum the cookie string must contain the SAPISID cookie. Without it, the SAPISIDHASH header cannot be computed and authentication will silently fall back to unauthenticated mode.

dataSyncId and onBehalfOfUser

When YouTube.dataSyncId is set, the library includes it as onBehalfOfUser in the request context body for all methods that support login. This signals to the InnerTube server which account’s data to return for library browse requests, liked songs, subscriptions, and personalised recommendations.
// After sign-in, fetch account info to confirm identity and extract dataSyncId
YouTube.cookie = rawCookieString
val account = YouTube.accountInfo().getOrNull()
// dataSyncId typically looks like: "1234567890987654321||"
YouTube.dataSyncId = account?.dataSyncId

Fetching and Persisting visitorData

visitorData is an opaque token that YouTube uses to track session state. Keeping it consistent across requests improves the quality of personalised results (radio, recommendations). Fetch it once and persist it:
// Fetch from YouTube's sw.js_data endpoint
val visitorData = YouTube.visitorData().getOrNull()
if (visitorData != null) {
    YouTube.visitorData = visitorData
    encryptedPrefs.edit().putString("yt_visitor_data", visitorData).apply()
}
On subsequent app launches, restore from storage before making any requests:
YouTube.visitorData = encryptedPrefs.getString("yt_visitor_data", null)
    ?: YouTube.visitorData().getOrNull()

useLoginForBrowse

By default, browse methods only attach login headers when they explicitly opt in (e.g. playlist(), library(), history()). Setting YouTube.useLoginForBrowse = true causes every InnerTube.browse() call to include the cookie and SAPISIDHASH header. This is useful when you want fully personalised responses from the home page or genre/mood pages.
YouTube.useLoginForBrowse = true

// Now home() returns a personalised feed instead of an anonymous one
val homePage = YouTube.home().getOrNull()

Cookies are sensitive credentials. A stolen YouTube cookie grants full access to the user’s Google account for the duration of the session. Always store cookie strings using Android Keystore-backed encryption:
  • Use EncryptedSharedPreferences from androidx.security.crypto for persistent storage.
  • Never log cookie values, include them in crash reports, or transmit them to third-party analytics.
  • Clear YouTube.cookie and delete the stored value immediately when the user signs out.
// Storing securely
val masterKey = MasterKey.Builder(context)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
    .build()

val encryptedPrefs = EncryptedSharedPreferences.create(
    context,
    "yt_secure_prefs",
    masterKey,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
)

encryptedPrefs.edit().putString("yt_cookie", YouTube.cookie).apply()

Build docs developers (and LLMs) love