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.

All runtime configuration for the InnerTube SDK is exposed as mutable properties on the YouTube singleton object. Internally each property is delegated to the underlying InnerTube instance, so a single assignment on YouTube immediately takes effect for all subsequent API calls. No builder pattern or restart is required.

Configuration properties

Locale

YouTube.locale
YouTubeLocale
required
Controls the country and language sent with every API request. YouTubeLocale is a two-field data class: gl is an ISO 3166-1 alpha-2 country code (e.g. "US") and hl is a BCP 47 language tag (e.g. "en"). The default value uses Locale.getDefault() from the Android runtime.
import com.metrolist.innertube.YouTube
import com.metrolist.innertube.models.YouTubeLocale

// Set locale to United States English
YouTube.locale = YouTubeLocale(gl = "US", hl = "en")

// Set locale to Japanese
YouTube.locale = YouTubeLocale(gl = "JP", hl = "ja")

Visitor data

YouTube.visitorData
String?
default:"null"
An opaque token that YouTube uses to track anonymous session state. Providing a stable visitor ID improves response quality, reduces bot-detection challenges, and is passed as the X-Goog-Visitor-Id header on every request. Persist this value across sessions to maintain continuity.
Fetch a fresh token from YouTube’s servers using YouTube.visitorData():
import com.metrolist.innertube.YouTube

// Fetch a visitor ID from YouTube and store it
val token: String? = YouTube.visitorData().getOrNull()
if (token != null) {
    YouTube.visitorData = token
    // Persist to SharedPreferences or DataStore for reuse across app launches
}

// Restore a previously saved token
YouTube.visitorData = myPreferences.getString("visitor_data", null)
Store the visitor ID in DataStore or SharedPreferences and restore it on every app launch. YouTube ties recommendation quality and session continuity to this token.
A raw cookie string for authenticated requests. When set, InnerTube sends the cookie and a computed SAPISIDHASH Authorization header on endpoints that require login (playlist mutation, library access, playback telemetry, etc.). Must be obtained from a logged-in YouTube Music browser session.
import com.metrolist.innertube.YouTube

// Set the cookie string obtained from a browser session
// The string must contain at minimum the SAPISID and LOGIN_INFO fields
YouTube.cookie = "SAPISID=AbCdEfGhIjKl; LOGIN_INFO=...; HSID=...; SSID=...; SID=..."
Cookie values are sensitive credentials. Never hardcode them in source files. Load them from encrypted storage (EncryptedSharedPreferences or equivalent) at runtime.

Data sync ID

YouTube.dataSyncId
String?
default:"null"
The dataSyncId is an account identifier sent as onBehalfOfUser in request bodies for authenticated browse and player calls. It can be extracted from the response of YouTube.accountInfo() after setting a valid cookie. Required for library edits and personalised content to be scoped to the correct account.
import com.metrolist.innertube.YouTube

// After setting a cookie, retrieve the account info to obtain dataSyncId
val accountInfo = YouTube.accountInfo().getOrNull()
YouTube.dataSyncId = accountInfo?.dataSyncId

Login for browse

YouTube.useLoginForBrowse
Boolean
default:"false"
When true, authentication headers (cookie + SAPISIDHASH) are injected into every browse request, including public ones. This is useful when you want YouTube to return personalised responses (e.g. whether an artist is subscribed, whether a playlist is liked) even for pages that do not strictly require login.
import com.metrolist.innertube.YouTube

// Force login headers on all browse requests
YouTube.useLoginForBrowse = true

Proxy

YouTube.proxy
java.net.Proxy?
default:"null"
A standard java.net.Proxy instance. When assigned, the InnerTube HTTP client is immediately rebuilt to route all traffic through the specified proxy. Supports both SOCKS and HTTP proxy types.
YouTube.proxyAuth
String?
default:"null"
Optional proxy authentication credential. The string is passed verbatim as the Proxy-Authorization header value. For Basic auth, set this to "Basic " + Base64.encode("user:password").
import com.metrolist.innertube.YouTube
import java.net.InetSocketAddress
import java.net.Proxy
import android.util.Base64

// HTTP proxy without authentication
YouTube.proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("proxy.example.com", 8080))

// SOCKS5 proxy with Basic authentication
YouTube.proxy = Proxy(Proxy.Type.SOCKS, InetSocketAddress("socks.example.com", 1080))
val credentials = Base64.encodeToString("username:password".toByteArray(), Base64.NO_WRAP)
YouTube.proxyAuth = "Basic $credentials"

// Clear proxy configuration
YouTube.proxy = null
YouTube.proxyAuth = null
Assigning a new value to YouTube.proxy closes the existing OkHttp client and creates a fresh one. Schedule proxy changes before your first API call, not in the middle of a request burst.

Network timeouts

The InnerTube HTTP client is configured with the following default timeout values baked into the OkHttp engine:
TimeoutDefault
Connect timeout30 seconds
Read timeout60 seconds
Write timeout60 seconds
Request timeout (Ktor)60 seconds
These defaults are suitable for most production use cases. For custom clients or environments with variable connectivity, use the NetworkConfig utility object.

NetworkConfig

NetworkConfig provides two helpers for advanced network configuration:
NetworkConfig.createOptimizedHttpClient(cacheDir, enableCache)
HttpClient
Builds a standalone Ktor HttpClient backed by OkHttp, pre-configured with the library’s standard timeouts, gzip/deflate content encoding, and an optional 128 MB disk cache. Useful when you want to make raw HTTP calls without going through the YouTube singleton, or when you need to embed the client in a custom DI graph.
NetworkConfig.getAdaptiveTimeouts(networkQuality)
TimeoutConfig
Returns a TimeoutConfig data class with connect, read, and request timeout values tuned for the given NetworkQuality level (EXCELLENT, GOOD, POOR, or UNKNOWN). Integrate with a connectivity manager to dynamically adjust timeouts based on actual network conditions.
import com.metrolist.innertube.NetworkConfig
import java.io.File

// Create a custom HTTP client with a specific cache directory
val cacheDir = File(context.cacheDir, "innertube_http")
val customClient = NetworkConfig.createOptimizedHttpClient(
    cacheDir = cacheDir,
    enableCache = true
)

// Get adaptive timeouts based on current network conditions
val timeouts = NetworkConfig.getAdaptiveTimeouts(NetworkConfig.NetworkQuality.POOR)
println("Connect timeout on poor network: ${timeouts.connectTimeout}ms")  // 30000ms
println("Read timeout on poor network:    ${timeouts.readTimeout}ms")     // 60000ms
println("Request timeout on poor network: ${timeouts.requestTimeout}ms")  // 90000ms

Complete configuration example

The following snippet shows a typical production setup applied once at application startup (e.g. in Application.onCreate()):
import com.metrolist.innertube.YouTube
import com.metrolist.innertube.models.YouTubeLocale
import java.net.InetSocketAddress
import java.net.Proxy

fun configureInnerTube(prefs: MyPreferences) {
    // 1. Locale — use device locale, or fix to a region
    YouTube.locale = YouTubeLocale(gl = "US", hl = "en")

    // 2. Visitor data — restore from persistent storage
    prefs.visitorData?.let { YouTube.visitorData = it }

    // 3. Authentication — restore saved cookie and dataSyncId
    prefs.youtubeCookie?.let { cookie ->
        YouTube.cookie = cookie
        YouTube.dataSyncId = prefs.dataSyncId
    }

    // 4. Force login headers on browse requests for personalised responses
    YouTube.useLoginForBrowse = prefs.isLoggedIn

    // 5. Proxy — only when user has configured one
    if (prefs.proxyEnabled) {
        YouTube.proxy = Proxy(
            Proxy.Type.HTTP,
            InetSocketAddress(prefs.proxyHost, prefs.proxyPort)
        )
        prefs.proxyAuth?.let { YouTube.proxyAuth = it }
    }

    // 6. Fetch and persist a fresh visitor ID if none is saved
    if (prefs.visitorData == null) {
        // Call in a coroutine scope tied to the application lifecycle
        appScope.launch {
            YouTube.visitorData().getOrNull()?.let { token ->
                YouTube.visitorData = token
                prefs.visitorData = token
            }
        }
    }
}

Build docs developers (and LLMs) love