{"id":19829497,"url":"https://github.com/lavalink-devs/youtube-source","last_synced_at":"2025-10-25T03:42:37.160Z","repository":{"id":234294392,"uuid":"787512046","full_name":"lavalink-devs/youtube-source","owner":"lavalink-devs","description":"A rewritten YouTube source manager for Lavaplayer.","archived":false,"fork":false,"pushed_at":"2025-03-26T18:07:32.000Z","size":350,"stargazers_count":235,"open_issues_count":4,"forks_count":42,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-04-04T10:06:09.958Z","etag":null,"topics":["hacktoberfest","lavaplayer","lavaplayer-source-manager","youtube","youtube-downloader"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lavalink-devs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-16T17:00:38.000Z","updated_at":"2025-04-02T22:38:38.000Z","dependencies_parsed_at":"2024-04-20T21:24:36.292Z","dependency_job_id":"2faafbb9-8b96-47e1-a62f-18580c205657","html_url":"https://github.com/lavalink-devs/youtube-source","commit_stats":null,"previous_names":["devoxin/lavaplayer-youtube-source","lavalink-devs/lavaplayer-youtube-source"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavalink-devs%2Fyoutube-source","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavalink-devs%2Fyoutube-source/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavalink-devs%2Fyoutube-source/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lavalink-devs%2Fyoutube-source/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lavalink-devs","download_url":"https://codeload.github.com/lavalink-devs/youtube-source/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248710410,"owners_count":21149186,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","lavaplayer","lavaplayer-source-manager","youtube","youtube-downloader"],"created_at":"2024-11-12T11:18:54.562Z","updated_at":"2025-10-25T03:42:37.154Z","avatar_url":"https://github.com/lavalink-devs.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# youtube-source\nA rewritten YouTube source manager for Lavaplayer.\n\nThis source aims to provide robustness by leveraging multiple InnerTube clients\nfor requests. Where one client fails, another will try to load the request.\nWhich clients are used is entirely configurable.\n\n## Table of Contents\n- [Common](#common)\n  - Information about the `common` module and usage of.\n- [V2](#v2)\n  - Information about the `v2` module and usage of.\n- [Plugin](#plugin)\n  - Information about the `plugin` module and usage of.\n- [Available Clients](#available-clients)\n  - Information about the clients provided by `youtube-source`, as well as their advantages/disadvantages.\n- [Using OAuth tokens](#using-oauth-tokens)\n  - Information on using OAuth tokens with `youtube-source`.\n- [Using a poToken](#using-a-potoken)\n  - Information on using a `poToken` with `youtube-source`.\n- [Using a remote cipher server](#using-a-remote-cipher-server)\n  - Information on using a remote cipher server with `youtube-source`.\n- [REST Routes (`plugin` only)](#rest-routes-plugin-only)\n  - Information on the REST routes provided by the `youtube-source` plugin module.\n- [Migration Information](#migration-from-lavaplayers-built-in-youtube-source)\n  - Information on migrating from Lavaplayer's built-in Youtube source manager.\n- [Additional Support](#additional-support)\n  - For everything else.\n\n## common\nThis module provides the base source manager, which can be used with any\n`com.sedmelluq.discord.lavaplayer` packages still on major version `1`.\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing in Gradle:\u003c/summary\u003e\n\n```kotlin\nrepositories {\n  // replace with https://maven.lavalink.dev/snapshots if you want to use a snapshot version.\n  maven(url = \"https://maven.lavalink.dev/releases\")\n}\n\ndependencies {\n  // Replace VERSION with the current version as shown by the Releases tab or a long commit hash `-SNAPSHOT` for snapshots.\n  implementation(\"dev.lavalink.youtube:common:VERSION\")\n}\n```\n\n\u003c/details\u003e\nExample usage:\n\n```java\nYoutubeAudioSourceManager youtube = new YoutubeAudioSourceManager();\n// Optionally, you may instantiate the source with a custom options, such as toggling use of searching, and clients.\nYoutubeAudioSourceManager youtube = new YoutubeAudioSourceManager(/*allowSearch:*/ true, new Client[] { new Music(), new Web(), new AndroidTestsuite() });\n```\n\nYou may also extend the `Client` interface to support additional InnerTube clients. There are a few abstract classes to\nmake this easier, notably, `MusicClient` (for `music.youtube.com` InnerTube clients), `NonMusicClient` (for youtube.com\ninnertube clients) and `StreamingNonMusicClient` (for clients that can be used to stream videos).\n\nSupport for IP rotation has been included, and can be achieved using the following:\n```java\nAbstractRoutePlanner routePlanner = new ...\nYoutubeIpRotatorSetup rotator = new YoutubeIpRotatorSetup(routePlanner);\n\n// 'youtube' is the variable holding your YoutubeAudioSourceManager instance.\nrotator.forConfiguration(youtube.getHttpInterfaceManager(), false)\n    .withMainDelegateFilter(youtube.getContextFilter()) // IMPORTANT\n    .setup();\n```\n\n## v2\nThis modules expands on `common` by providing additional support for\nLavaplayer `2.x` clients, such as [Lavalink-Devs/Lavaplayer](https://github.com/lavalink-devs/lavaplayer).\nSuch features currently include thumbnail support within `AudioTrackInfo`.\nAdditional clients are included that provide access to this additional information.\nThese clients are suffixed with `Thumbnail`, such as `WebWithThumbnail`, `AndroidWithThumbnail` etc.\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing in Gradle:\u003c/summary\u003e\n\n```kotlin\nrepositories {\n  // replace with https://maven.lavalink.dev/snapshots if you want to use a snapshot version.\n  maven(url = \"https://maven.lavalink.dev/releases\")\n}\n\ndependencies {\n  // Replace VERSION with the current version as shown by the Releases tab or a long commit hash `-SNAPSHOT` for snapshots.\n  implementation(\"dev.lavalink.youtube:v2:VERSION\")\n}\n```\n\n\u003c/details\u003e\n\nExample usage:\n```java\n// same as the 'common' module but there are additional clients that provide video thumbnails in the returned metadata.\nYoutubeAudioSourceManager youtube = new YoutubeAudioSourceManager(/*allowSearch:*/ true, new Client[] { new MusicWithThumbnail(), new WebWithThumbnail(), new AndroidTestsuiteWithThumbnail() });\n```\n\n## plugin\nThis module serves as the plugin for use with [Lavalink](https://github.com/lavalink-devs/Lavalink).\n\nTo use this plugin with Lavalink, you must declare the dependency.\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing with Lavalink v3:\u003c/summary\u003e\n\n```yaml\nlavalink:\n  plugins:\n    # Replace VERSION with the current version as shown by the Releases tab or a long commit hash for snapshots.\n    - dependency: \"dev.lavalink.youtube:youtube-plugin:VERSION\"\n      repository: \"https://maven.lavalink.dev/releases\" # use https://maven.lavalink.dev/snapshots if you want to use a snapshot version.\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing with Lavalink v4:\u003c/summary\u003e\n\n```yaml\nlavalink:\n  plugins:\n    # Replace VERSION with the current version as shown by the Releases tab or a long commit hash for snapshots.\n    - dependency: \"dev.lavalink.youtube:youtube-plugin:VERSION\"\n      snapshot: false # Set to true if you want to use a snapshot version.\n```\n\n\u003c/details\u003e\n\nConfiguring the plugin:\n\u003e [!IMPORTANT]\n\u003e You must make sure to disable the built-in YouTube source like so:\n```yaml\nlavalink:\n  server:\n    sources:\n      youtube: false\n```\n\n\u003e [!NOTE]\n\u003e Existing options, such as `ratelimit` and `youtubePlaylistLoadLimit` will be picked up automatically by the plugin,\n\u003e so these don't need changing.\n\u003e \n```yaml\nplugins:\n  youtube:\n    enabled: true # Whether this source can be used.\n    allowSearch: true # Whether \"ytsearch:\" and \"ytmsearch:\" can be used.\n    allowDirectVideoIds: true # Whether just video IDs can match. If false, only complete URLs will be loaded.\n    allowDirectPlaylistIds: true # Whether just playlist IDs can match. If false, only complete URLs will be loaded.\n    # The clients to use for track loading. See below for a list of valid clients.\n    # Clients are queried in the order they are given (so the first client is queried first and so on...)\n    clients:\n      - MUSIC\n      - ANDROID_VR\n      - WEB\n      - WEBEMBEDDED \n```\n\n### Advanced Options\n```yaml\n    # The below section of the config allows setting specific options for each client, such as the requests they will handle.\n    # If an option, or client, is unspecified, then the default option value/client values will be used instead.\n    # If a client is configured, but is not registered above, the options for that client will be ignored.\n    # WARNING!: THE BELOW CONFIG IS FOR ILLUSTRATION PURPOSES. DO NOT COPY OR USE THIS WITHOUT\n    # WARNING!: UNDERSTANDING WHAT IT DOES. MISCONFIGURATION WILL HINDER YOUTUBE-SOURCE'S ABILITY TO WORK PROPERLY.\n\n    # Write the names of clients as they are specified under the heading \"Available Clients\".\n    clientOptions:\n      WEB:\n        # Example: Disabling a client's playback capabilities.\n        playback: false\n        videoLoading: false # Disables loading of videos for this client. A client may still be used for playback even if this is set to 'false'.\n      WEBEMBEDDED:\n        # Example: Configuring a client to exclusively be used for video loading and playback.\n        playlistLoading: false # Disables loading of playlists and mixes.\n        searching: false # Disables the ability to search for videos.\n```\n\n## Available Clients\nCurrently, the following clients are available for use:\n\n| Identifier        | Opus Formats | OAuth | Age-restriction Support | Playback Support | Metadata Support             | Additional Notes                                     |\n|-------------------|--------------|-------|-------------------------|------------------|------------------------------|------------------------------------------------------|\n| `MUSIC`           | No           | No    | No                      | No               | Search                       | YouTube music search support via `ytmsearch:` prefix |\n| `WEB`             | Yes          | No    | No                      | Yes + Livestream | Video, Search, Playlist, Mix |                                                      |\n| `MWEB`            | Yes          | No    | No                      | Yes + Livestream | Video, Search, Playlist, Mix |                                                      |\n| `WEBEMBEDDED`     | Yes          | No    | Limited                 | Yes + Livestream | Video                        |                                                      |\n| `ANDROID`         | Yes          | No    | No                      | Yes + Livestream | Video, Search, Playlist, Mix | Heavily restricted, frequently dysfunctional         |\n| `ANDROID_MUSIC`   | Yes          | No    | No                      | Yes              | Video, Search, Mix           |                                                      |\n| `ANDROID_VR`      | Yes          | No    | No                      | Yes + Livestream | Video, Search, Playlist, Mix |                                                      |\n| `IOS`             | No           | No    | No                      | Yes + Livestream | Video, Search, Playlist, Mix |                                                      |\n| `TV`              | Yes          | Yes   | With OAuth              | Yes + Livestream | None                         | Playback requires sign-in                            |\n| `TVHTML5EMBEDDED` | Yes          | Yes   | With OAuth              | Yes + Livestream | Video, Search, Mix           | Playback requires sign-in                            |\n\n\u003e [!NOTE]\n\u003e Clients that do not return Opus formats will require transcoding.\n\u003e Livestreams do not yield Opus formats so will always require transcoding.\n\n\n## Using OAuth Tokens\nYou may notice that some requests are flagged by YouTube, causing an error message asking you to sign in to confirm you're not a bot.\nWith OAuth integration, you can request that `youtube-source` use your account credentials to appear as a normal user, with varying degrees\nof efficacy. **You do _not_ need to use `poToken` with OAuth.**\n\n\u003e [!WARNING]\n\u003e Similar to the `poToken` method, this is NOT a silver bullet solution, and worst case could get your account terminated!\n\u003e For this reason, it is advised that **you use burner accounts and NOT your primary!**\n\u003e This method may also trigger ratelimit errors if used in a high traffic environment.\n\u003e USE WITH CAUTION!\n\n\u003e [!NOTE]\n\u003e You may need to set your log level for `dev.lavalink.youtube.http.YoutubeOauth2Handler` to `INFO`, to see additional information\n\u003e within your terminal regarding completing the OAuth flow.\n\n\u003e [!NOTE]\n\u003e If you do not have a refresh token, then do not supply one. The source will output your refresh token into your terminal upon\n\u003e successfully completing the OAuth flow at least **once**. If you do not see your token, you may need to configure your\n\u003e logging (see above note).\n\nYou can instruct `youtube-source` to use OAuth with the following:\n\n### Lavaplayer\n```java\nYoutubeAudioSourceManager source = new YoutubeAudioSourceManager();\n// This will trigger an OAuth flow, where you will be instructed to head to YouTube's OAuth page and input a code.\n// This is safe, as it only uses YouTube's official OAuth flow. No tokens are seen or stored by us.\nsource.useOauth2(null, false);\n\n// If you already have a refresh token, you can instruct the source to use it, skipping the OAuth flow entirely.\n// You can also set the `skipInitialization` parameter, which skips the OAuth flow. This should only be used\n// if you intend to supply a refresh token later on. You **must** either complete the OAuth flow or supply\n// a refresh token for OAuth integration to work.\nsource.useOauth2(\"your refresh token\", true);\n```\n\n### Lavalink\n```yaml\nplugins:\n  youtube:\n    enabled: true\n    oauth:\n      # setting \"enabled: true\" is the bare minimum to get OAuth working.\n      enabled: true\n\n      # if you have a refresh token, you may set it below (make sure to uncomment the line to apply it).\n      # setting a valid refresh token will skip the OAuth flow entirely. See above note on how to retrieve\n      # your refreshToken.\n      # refreshToken: \"paste your refresh token here if applicable\"\n\n      # Set this if you don't want the OAuth flow to be triggered, if you intend to supply a refresh token later.\n      # Initialization is skipped automatically if a valid refresh token is supplied. Leave this commented if you're\n      # completing the OAuth flow for the first time/do not have a refresh token.\n      # skipInitialization: true\n```\n\n### Passing an oauth token from your client\nAnother option to use oauth is by using oauth access tokens that are managed from your client. In this case your \nbot/client provides LavaLink with the token to use when playing a track. To do this simply add the oauth access token \nto a track's [userData](https://lavalink.dev/api/rest#track) field in a json format when updating the player to \nplay a track like:\n```json\n{\n  \"oauth-token\": \"access token to use\"\n}\n```\n\n## Using a `poToken`\nA `poToken`, also known as a \"Proof of Origin Token\" is a way to identify what requests originate from.\nIn YouTube's case, this is sent as a JavaScript challenge that browsers must evaluate, and send back the resolved\nstring. Typically, this challenge would remain unsolved for bots as more often than not, they don't simulate an entire\nbrowser environment, instead only evaluating the minimum amount of JS required to do its job. Therefore, it's a reasonable\nassumption that if the challenge is not fulfilled, the request origin is a bot.\n\nTo obtain a `poToken`, you can use https://github.com/iv-org/youtube-trusted-session-generator, by running the Python script\nor the docker image. Both methods will print a `poToken` after a successful run, which you can supply to `youtube-source`\nto try and work around having automated requests blocked.\n\n\n\u003e [!NOTE]\n\u003e A `poToken` is not a silver bullet, and currently it only applies to requests made via the `WEB` \u0026 `WEBEMBEDDED` client.\n\u003e You do not need to specify a `poToken` if using OAuth, and vice versa.\n\nSpecifying the token is as simple as doing:\n\n### Lavaplayer\n```java\n// Web is dev.lavalink.youtube.clients.Web\nWeb.setPoTokenAndVisitorData(\"your po_token\", \"your visitor_data\");\n```\n\n### Lavalink\n```yaml\nplugins:\n  youtube:\n    pot:\n      token: \"paste your po_token here\"\n      visitorData: \"paste your visitor_data here\"\n```\n\n## Using a remote cipher server\n\nIt becomes harder and harder to keep up with YouTube's cipher changes, as they become more frequent and complex.\nTo help with this, you can use a remote cipher server to handle signature deciphering for you.\nYou can use [yt-cipher](https://github.com/kikkia/yt-cipher), which is a simple Deno server that exposes a REST API for deciphering signatures.\nCheck out the repository for more information on how to set it up.\n\nIf you want to implement your own, you can follow the [yt-cipher API specification](https://github.com/kikkia/yt-cipher#api-specification).\n\n### Lavaplayer\n```java\nYoutubeSourceOptions options = new YoutubeSourceOptions()\n    .setRemoteCipherUrl(\"http://localhost:8001\", \"your_secret_password\"); // The base URL of your remote cipher server \u0026 the password to authenticate with your remote cipher server.\nYoutubeAudioSourceManager sourceManager = new YoutubeAudioSourceManager(options, ...);\n```\n\n### Lavalink\n```yaml\nplugins:\n  youtube:\n    remoteCipher:\n      url: \"http://localhost:8001\" # The base URL of your remote cipher server.\n      password: \"your_secret_password\" # The password to authenticate with your remote cipher server.\n      userAgent: \"your_service_name\" # Optional user-agent header, used for metrics on the backend. \n```\n\n## REST routes (`plugin` only)\n### `POST` `/youtube`\n\nBody:\n\n\u003e [!NOTE]\n\u003e You do not need to provide everything as it is shown.\n\u003e For example, you can specify just `refreshToken` and `skipInitialization`, or just `poToken` and `visitorData`.\n\u003e You do **not** need to use `poToken` with OAuth and vice versa.\n\n```json\n{\n  \"refreshToken\": \"your new refresh token\",\n  \"skipInitialization\": true,\n  \"poToken\": \"your po_token\",\n  \"visitorData\": \"your visitor_data\"\n}\n```\n\nResponse:\n\nIf the YouTube source is not enabled, or the `refreshToken` is invalid:\n`500 - Internal Server Error`\n\nOtherwise:\n`204 - No Content`\n\n### `GET` `/youtube`\n\nResponse:\n\nIf the YouTube source is not enabled:\n`500 - Internal Server Error`\n\nOtherwise:\n```json\n{\n  \"refreshToken\": \"your current refresh token, or null\"\n}\n```\n\n### `GET` `/youtube/stream/{videoId}`\n\nQuery parameters:\n\n| Key          | Value Type | Required | Notes                                                                                                                                                                       |\n|--------------|------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| itag         | integer    | No       | The [itag](https://gist.github.com/AgentOak/34d47c65b1d28829bb17c24c04a0096f) of the desired format. If unspecified, youtube-source's default format selector will be used. |\n| withClient   | string     | No       | The identifier of the client to use for streaming. Uses all clients if unspecified.                                                                                         |\n\nResponse:\n\nIf `videoId` could not be found or loaded, or the `itag` does not exist, or if no client supports format loading:\n`400 - Bad Request`\n\nOtherwise:\n`200 - OK` accompanied by the selected format stream (audio or video). `Content-Type` header will be set appropriately.\n\n### `GET` `/youtube/oauth/{refreshToken}`\n\nResponse:\n\nIf the `refreshToken` is invalid, expired, or cannot be processed:\n`500 - Internal Server Error`\n\nIf the refresh process succeeds and a new access token is generated:\n`200 - OK` accompanied by the new access token in JSON format.\n\nExample response:\n```json\n{\n  \"access_token\": \"AccessToken\",\n  \"expires_in\": 69420,\n  \"scope\": \"used scope\",\n  \"token_type\": \"type\"\n}\n```\n\n\n\n## Migration from Lavaplayer's built-in YouTube source\n\nThis client is intended as a direct replacement for Lavaplayer's built-in `YoutubeAudioSourceManager`,\nwhich has been deprecated in a recent release of [Lavalink-Devs/Lavaplayer](https://github.com/lavalink-devs/lavaplayer).\n\nWhen using `AudioSourceManagers.registerRemoteSources(AudioPlayerManager)`, Lavaplayer will register its own\ndeprecated `YoutubeAudioSourceManager`, which must be disabled.\nSome versions of Lavaplayer may include an optional `excludeSources` parameter, allowing you to toggle the adding of the source.\nIf the version you are using does not support this, you will need to manually register each `AudioSourceManager` yourself.\n\nFirst, create and register an instance of the supported `YoutubeAudioSourceManager` from the `youtube-source` package.\n```java\nAudioPlayerManager playerManager = new DefaultAudioPlayerManager();\nYoutubeAudioSourceManager ytSourceManager = new dev.lavalink.youtube.YoutubeAudioSourceManager();\nplayerManager.registerSourceManager(ytSourceManager);\n```\n\nIf your version of Lavaplayer supports an `excludeSources` parameter or equivalent, you may exclude the built-in\n`YoutubeAudioSourceManager` using the following:\n```java\nAudioSourceManagers.registerRemoteSources(playerManager,\n                                          com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager.class);\n```\n\nOtherwise, you will need to register each source manager individually.\n\nIn addition, there are a few significant changes to note:\n\n- This source's class structure differs so if you had custom classes that you were initialising\n  the source manager with (e.g. an overridden `YoutubeTrackDetailsLoader`), this **is not** compatible\n  with this source manager.\n\n## Versioning Policy\nThis project follows [Semantic Versioning](https://semver.org/), except in the case of [client](#available-clients) removal.\nTypically, clients are not removed unless there is good reason, such as being deprecated, irreparably broken or removed from YouTube's client lifecycle.\nIn such scenarios, we anticipate that you have ceased usage of such clients prior to their removal, so do not expect any code breakage,\nhowever we advise that you periodically check and keep your client list up to date due to this.\n\n## Additional Support\nIf you need additional help with using this source, that's not covered here or in any of the issues, \n[join our Discord server](https://discord.gg/ZW4s47Ppw4).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flavalink-devs%2Fyoutube-source","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flavalink-devs%2Fyoutube-source","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flavalink-devs%2Fyoutube-source/lists"}