Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/faraasaaay/inner/llms.txt

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

This guide walks you through everything you need to make your first YouTube Music API call with Inner. By the end you will have the innertube module on your classpath, an optional session cookie configured, and a working coroutine that searches for songs and prints their titles.
1

Add the module

Inner ships as a local Gradle module — the innertube directory inside the repository. Copy or clone the innertube directory into your project root, then declare it in your project’s settings.gradle.kts:
settings.gradle.kts
include(":innertube")
Next, add it as a dependency in your app module’s build.gradle.kts:
app/build.gradle.kts
dependencies {
    implementation(project(":innertube"))
}
Sync your Gradle project to resolve the module.
2

Initialize YouTube

YouTube is a Kotlin object — a singleton that requires no constructor call or manual initialisation. Import it and start configuring:
import com.tamed.music.innertube.YouTube
import com.tamed.music.innertube.models.YouTubeLocale

// Set the locale for region-aware content (country code + language tag)
YouTube.locale = YouTubeLocale(gl = "US", hl = "en-US")
YouTubeLocale.gl is the two-letter ISO 3166-1 country code used for region-specific charts and recommendations. YouTubeLocale.hl is the BCP 47 language tag for response language.
3

Set your session cookie (optional)

Anonymous browsing works without any credentials — you can search, browse, and fetch album/artist pages without a cookie. To access authenticated features (library, history, playlist management, account info), provide a YouTube Music session cookie:
// Paste the full Cookie header value from your browser's DevTools
YouTube.cookie = "SAPISID=xxxxxxxxxxxx; __Secure-3PAPISID=xxxxxxxxxxxx; ..."
The cookie is stored inside the PlaybackAuthState and is automatically attached to requests that require login. Setting cookie to null returns the client to anonymous mode.
You can obtain a valid cookie by opening YouTube Music in a browser, signing in, and copying the Cookie request header from any music.youtube.com network request in your browser’s developer tools.
4

Make your first search

All YouTube methods are suspend functions that return Result<T>. Call them from a coroutine scope — runBlocking is used here for simplicity, but in production code use viewModelScope, lifecycleScope, or your own CoroutineScope:
import com.tamed.music.innertube.YouTube
import com.tamed.music.innertube.YouTube.SearchFilter
import com.tamed.music.innertube.models.YouTubeLocale
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    YouTube.locale = YouTubeLocale(gl = "US", hl = "en-US")

    val result = YouTube.search("Bohemian Rhapsody", SearchFilter.FILTER_SONG)

    result.onSuccess { searchResult ->
        searchResult.items.forEach { item ->
            println(item.title)
        }
    }.onFailure { error ->
        println("Search failed: ${error.message}")
    }
}
SearchFilter is a @JvmInline value class with the following pre-built filters:
FilterMatches
SearchFilter.FILTER_SONGAudio tracks
SearchFilter.FILTER_VIDEOMusic videos
SearchFilter.FILTER_ALBUMAlbums and EPs
SearchFilter.FILTER_ARTISTArtist pages
SearchFilter.FILTER_FEATURED_PLAYLISTOfficial/curated playlists
SearchFilter.FILTER_COMMUNITY_PLAYLISTUser-created playlists
5

Fetch more results

SearchResult contains an optional continuation token. When it is non-null, more results are available. Pass it to YouTube.searchContinuation() to load the next page:
import com.tamed.music.innertube.YouTube
import com.tamed.music.innertube.YouTube.SearchFilter
import com.tamed.music.innertube.models.YouTubeLocale
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    YouTube.locale = YouTubeLocale(gl = "US", hl = "en-US")

    var result = YouTube.search("Queen", SearchFilter.FILTER_SONG).getOrThrow()

    // Print the first page
    result.items.forEach { println(it.title) }

    // Load the next page if a continuation token is available
    if (result.continuation != null) {
        val nextPage = YouTube.searchContinuation(result.continuation!!).getOrThrow()
        nextPage.items.forEach { println(it.title) }
    }
}
You can keep following continuation tokens in a loop until the value is null, which signals the last page of results.
All YouTube methods return Result<T> and are suspend functions. Use runCatching, .onSuccess, .onFailure, or .getOrThrow() depending on your error-handling preference. .getOrThrow() is convenient in quick scripts but will propagate exceptions — prefer .onFailure or runCatching in production UI code.

Next steps

Now that you have a working search call, explore the rest of Inner’s capabilities:
  • Searching — Typed filters, search summaries, and suggestion autocomplete
  • Browsing — Home feed, artist pages, album pages, charts, and moods & genres
  • Authentication — Session cookies, visitor data, PoToken, and the PlaybackAuthState model

Build docs developers (and LLMs) love