ytmusicapi package
******************


Subpackages
===========

* ytmusicapi.auth package

  * Subpackages

    * ytmusicapi.auth.oauth package

      * Submodules

      * ytmusicapi.auth.oauth.credentials module

      * ytmusicapi.auth.oauth.exceptions module

      * ytmusicapi.auth.oauth.models module

      * ytmusicapi.auth.oauth.token module

      * Module contents

  * Submodules

  * ytmusicapi.auth.auth_parse module

    * "determine_auth_type()"

    * "parse_auth_str()"

  * ytmusicapi.auth.browser module

    * "is_browser()"

    * "setup_browser()"

  * ytmusicapi.auth.types module

    * "AuthType"

      * "AuthType.BROWSER"

      * "AuthType.OAUTH_CUSTOM_CLIENT"

      * "AuthType.OAUTH_CUSTOM_FULL"

      * "AuthType.UNAUTHORIZED"

  * Module contents

* ytmusicapi.mixins package

  * Submodules

  * ytmusicapi.mixins.browsing module

    * "BrowsingMixin"

      * "BrowsingMixin.ArtistOrderType"

      * "BrowsingMixin.get_album()"

      * "BrowsingMixin.get_album_browse_id()"

      * "BrowsingMixin.get_artist()"

      * "BrowsingMixin.get_artist_albums()"

      * "BrowsingMixin.get_basejs_url()"

      * "BrowsingMixin.get_home()"

      * "BrowsingMixin.get_lyrics()"

      * "BrowsingMixin.get_signatureTimestamp()"

      * "BrowsingMixin.get_song()"

      * "BrowsingMixin.get_song_related()"

      * "BrowsingMixin.get_tasteprofile()"

      * "BrowsingMixin.get_user()"

      * "BrowsingMixin.get_user_playlists()"

      * "BrowsingMixin.get_user_videos()"

      * "BrowsingMixin.set_tasteprofile()"

  * ytmusicapi.mixins.explore module

    * "ExploreMixin"

      * "ExploreMixin.get_charts()"

      * "ExploreMixin.get_mood_categories()"

      * "ExploreMixin.get_mood_playlists()"

  * ytmusicapi.mixins.library module

    * "LibraryMixin"

      * "LibraryMixin.add_history_item()"

      * "LibraryMixin.edit_song_library_status()"

      * "LibraryMixin.get_account_info()"

      * "LibraryMixin.get_history()"

      * "LibraryMixin.get_library_albums()"

      * "LibraryMixin.get_library_artists()"

      * "LibraryMixin.get_library_channels()"

      * "LibraryMixin.get_library_playlists()"

      * "LibraryMixin.get_library_podcasts()"

      * "LibraryMixin.get_library_songs()"

      * "LibraryMixin.get_library_subscriptions()"

      * "LibraryMixin.rate_playlist()"

      * "LibraryMixin.rate_song()"

      * "LibraryMixin.remove_history_items()"

      * "LibraryMixin.subscribe_artists()"

      * "LibraryMixin.unsubscribe_artists()"

  * ytmusicapi.mixins.playlists module

    * "PlaylistsMixin"

      * "PlaylistsMixin.add_playlist_items()"

      * "PlaylistsMixin.create_playlist()"

      * "PlaylistsMixin.delete_playlist()"

      * "PlaylistsMixin.edit_playlist()"

      * "PlaylistsMixin.get_liked_songs()"

      * "PlaylistsMixin.get_playlist()"

      * "PlaylistsMixin.get_saved_episodes()"

      * "PlaylistsMixin.remove_playlist_items()"

  * ytmusicapi.mixins.podcasts module

    * "PodcastsMixin"

      * "PodcastsMixin.get_channel()"

      * "PodcastsMixin.get_channel_episodes()"

      * "PodcastsMixin.get_episode()"

      * "PodcastsMixin.get_episodes_playlist()"

      * "PodcastsMixin.get_podcast()"

  * ytmusicapi.mixins.search module

    * "SearchMixin"

      * "SearchMixin.get_search_suggestions()"

      * "SearchMixin.remove_search_suggestions()"

      * "SearchMixin.search()"

  * ytmusicapi.mixins.uploads module

    * "UploadsMixin"

      * "UploadsMixin.delete_upload_entity()"

      * "UploadsMixin.get_library_upload_album()"

      * "UploadsMixin.get_library_upload_albums()"

      * "UploadsMixin.get_library_upload_artist()"

      * "UploadsMixin.get_library_upload_artists()"

      * "UploadsMixin.get_library_upload_songs()"

      * "UploadsMixin.upload_song()"

  * ytmusicapi.mixins.watch module

    * "WatchMixin"

      * "WatchMixin.get_watch_playlist()"

  * Module contents

* ytmusicapi.models package

  * Submodules

  * ytmusicapi.models.lyrics module

    * "LyricLine"

      * "LyricLine.end_time"

      * "LyricLine.from_raw()"

      * "LyricLine.id"

      * "LyricLine.start_time"

      * "LyricLine.text"

    * "Lyrics"

      * "Lyrics.hasTimestamps"

      * "Lyrics.lyrics"

      * "Lyrics.source"

    * "TimedLyrics"

      * "TimedLyrics.hasTimestamps"

      * "TimedLyrics.lyrics"

      * "TimedLyrics.source"

  * Module contents

    * "LyricLine"

      * "LyricLine.end_time"

      * "LyricLine.from_raw()"

      * "LyricLine.id"

      * "LyricLine.start_time"

      * "LyricLine.text"

    * "Lyrics"

      * "Lyrics.hasTimestamps"

      * "Lyrics.lyrics"

      * "Lyrics.source"

    * "TimedLyrics"

      * "TimedLyrics.hasTimestamps"

      * "TimedLyrics.lyrics"

      * "TimedLyrics.source"

* ytmusicapi.parsers package

  * Submodules

  * ytmusicapi.parsers.albums module

    * "parse_album_header()"

    * "parse_album_header_2024()"

  * ytmusicapi.parsers.browsing module

    * "parse_album()"

    * "parse_content_list()"

    * "parse_mixed_content()"

    * "parse_playlist()"

    * "parse_related_artist()"

    * "parse_single()"

    * "parse_song()"

    * "parse_song_flat()"

    * "parse_video()"

    * "parse_watch_playlist()"

  * ytmusicapi.parsers.explore module

    * "parse_chart_artist()"

    * "parse_chart_song()"

    * "parse_chart_trending()"

    * "parse_ranking()"

  * ytmusicapi.parsers.i18n module

    * "Parser"

      * "Parser.get_api_result_types()"

      * "Parser.get_search_result_types()"

      * "Parser.parse_channel_contents()"

  * ytmusicapi.parsers.library module

    * "get_library_contents()"

    * "parse_albums()"

    * "parse_artists()"

    * "parse_library_albums()"

    * "parse_library_artists()"

    * "parse_library_podcasts()"

    * "parse_library_songs()"

    * "pop_songs_random_mix()"

  * ytmusicapi.parsers.playlists module

    * "parse_audio_playlist()"

    * "parse_playlist_header()"

    * "parse_playlist_header_meta()"

    * "parse_playlist_item()"

    * "parse_playlist_items()"

    * "validate_playlist_id()"

  * ytmusicapi.parsers.podcasts module

    * "Description"

      * "Description.from_runs()"

      * "Description.text"

    * "DescriptionElement"

      * "DescriptionElement.text"

    * "Link"

      * "Link.url"

    * "Timestamp"

      * "Timestamp.seconds"

    * "parse_base_header()"

    * "parse_episode()"

    * "parse_episode_header()"

    * "parse_podcast()"

    * "parse_podcast_header()"

  * ytmusicapi.parsers.search module

    * "get_search_params()"

    * "get_search_result_type()"

    * "parse_album_playlistid_if_exists()"

    * "parse_search_result()"

    * "parse_search_results()"

    * "parse_search_suggestions()"

    * "parse_top_result()"

  * ytmusicapi.parsers.songs module

    * "parse_like_status()"

    * "parse_song_album()"

    * "parse_song_artists()"

    * "parse_song_artists_runs()"

    * "parse_song_library_status()"

    * "parse_song_menu_tokens()"

    * "parse_song_runs()"

  * ytmusicapi.parsers.uploads module

    * "parse_uploaded_items()"

  * ytmusicapi.parsers.watch module

    * "get_tab_browse_id()"

    * "parse_watch_playlist()"

    * "parse_watch_track()"

  * Module contents


Submodules
==========


ytmusicapi.constants module
===========================


ytmusicapi.continuations module
===============================

ytmusicapi.continuations.get_continuation_contents(continuation, parse_func)

ytmusicapi.continuations.get_continuation_params(results, ctoken_path='')

ytmusicapi.continuations.get_continuation_string(ctoken)

ytmusicapi.continuations.get_continuation_token(results: list[dict[str, Any]]) -> str | None

   Return type:
      "Optional"["str"]

ytmusicapi.continuations.get_continuations(results, continuation_type, limit, request_func, parse_func, ctoken_path='', reloadable=False)

ytmusicapi.continuations.get_continuations_2025(results, limit, request_func, parse_func)

ytmusicapi.continuations.get_parsed_continuation_items(response, parse_func, continuation_type)

ytmusicapi.continuations.get_reloadable_continuation_params(results)

ytmusicapi.continuations.get_validated_continuations(results, continuation_type, limit, per_page, request_func, parse_func, ctoken_path='')

ytmusicapi.continuations.resend_request_until_parsed_response_is_valid(request_func, request_additional_params, parse_func, validate_func, max_retries)

ytmusicapi.continuations.validate_response(response, per_page, limit, current_count)


ytmusicapi.enums module
=======================

class ytmusicapi.enums.ResponseStatus(*values)

   Bases: "str", "Enum"

   SUCCEEDED = 'STATUS_SUCCEEDED'


ytmusicapi.exceptions module
============================

custom exception classes for ytmusicapi

exception ytmusicapi.exceptions.YTMusicError

   Bases: "Exception"

   base error class

   shall only be raised if none of the subclasses below are fitting

exception ytmusicapi.exceptions.YTMusicServerError

   Bases: "YTMusicError"

   error caused by the YouTube Music backend

exception ytmusicapi.exceptions.YTMusicUserError

   Bases: "YTMusicError"

   error caused by invalid usage of ytmusicapi


ytmusicapi.helpers module
=========================

ytmusicapi.helpers.get_authorization(auth)

ytmusicapi.helpers.get_visitor_id(request_func)

ytmusicapi.helpers.initialize_context()

ytmusicapi.helpers.initialize_headers()

ytmusicapi.helpers.sapisid_from_cookie(raw_cookie)

ytmusicapi.helpers.sum_total_duration(item)

ytmusicapi.helpers.to_int(string)


ytmusicapi.navigation module
============================

commonly used navigation paths

ytmusicapi.navigation.find_object_by_key(object_list, key, nested=None, is_key=False)

ytmusicapi.navigation.find_objects_by_key(object_list, key, nested=None)

ytmusicapi.navigation.nav(root: dict, items: list[Any], none_if_absent: bool = False) -> Any | None

   Access a nested object in root by item sequence.

   Return type:
      "Optional"["Any"]


ytmusicapi.setup module
=======================

ytmusicapi.setup.main() -> RefreshingToken | str

   Return type:
      "Union"["RefreshingToken", "str"]

ytmusicapi.setup.parse_args(args)

ytmusicapi.setup.setup(filepath: str | None = None, headers_raw: str | None = None) -> str

   Requests browser headers from the user via command line and returns
   a string that can be passed to YTMusic()

   Parameters:
      * **filepath** ("Optional"["str"]) -- Optional filepath to store
        headers to.

      * **headers_raw** ("Optional"["str"]) -- Optional request
        headers copied from browser. Otherwise requested from terminal

   Return type:
      "str"

   Returns:
      configuration headers string

ytmusicapi.setup.setup_oauth(client_id: str, client_secret: str, filepath: str | None = None, session: Session | None = None, proxies: dict | None = None, open_browser: bool = False) -> RefreshingToken

   Starts oauth flow from the terminal and returns a string that can
   be passed to YTMusic()

   Parameters:
      * **client_id** ("str") -- Optional. Used to specify the
        client_id oauth should use for authentication flow. If
        provided, client_secret MUST also be passed or both will be
        ignored.

      * **client_secret** ("str") -- Optional. Same as client_id but
        for the oauth client secret.

      * **session** ("Optional"["Session"]) -- Session to use for
        authentication

      * **proxies** ("Optional"["dict"]) -- Proxies to use for
        authentication

      * **filepath** ("Optional"["str"]) -- Optional filepath to store
        headers to.

      * **open_browser** ("bool") -- If True, open the default browser
        with the setup link

   Return type:
      "RefreshingToken"

   Returns:
      configuration headers string


ytmusicapi.ytmusic module
=========================

class ytmusicapi.ytmusic.YTMusic(auth: str | dict | None = None, user: str | None = None, requests_session: Session | None = None, proxies: dict[str, str] | None = None, language: str = 'en', location: str = '', oauth_credentials: OAuthCredentials | None = None)

   Bases: "YTMusicBase", "BrowsingMixin", "SearchMixin", "WatchMixin",
   "ExploreMixin", "LibraryMixin", "PlaylistsMixin", "PodcastsMixin",
   "UploadsMixin"

   Allows automated interactions with YouTube Music by emulating the
   YouTube web client's requests. Permits both authenticated and non-
   authenticated requests. Authentication header data must be provided
   on initialization.

class ytmusicapi.ytmusic.YTMusicBase(auth: str | dict | None = None, user: str | None = None, requests_session: Session | None = None, proxies: dict[str, str] | None = None, language: str = 'en', location: str = '', oauth_credentials: OAuthCredentials | None = None)

   Bases: "object"

   as_mobile() -> Iterator[None]

      Return type:
         "Iterator"["None"]


      Not thread-safe!
      ----------------

      Temporarily changes the *context* to enable different results
      from the API, meant for the Android mobile-app. All calls inside
      the *with*-statement with emulate mobile behavior.

      This context-manager has no *enter_result*, as it operates in-
      place and only temporarily alters the underlying
      *YTMusic*-object.

      Example:

         with yt.as_mobile():
             yt._send_request(...)  # results as mobile-app

         yt._send_request(...)  # back to normal, like web-app

   property base_headers: CaseInsensitiveDict

   property headers: CaseInsensitiveDict

   proxies: "Optional"["dict"["str", "str"]]

      params for session modification


Module contents
===============

class ytmusicapi.OAuthCredentials(client_id: str, client_secret: str, session: Session | None = None, proxies: dict | None = None)

   Bases: "Credentials"

   Class for handling OAuth credential retrieval and refreshing.

   client_id: "str"

   client_secret: "str"

   get_code() -> AuthCodeDict

      Method for obtaining a new user auth code. First step of token
      creation.

      Return type:
         "AuthCodeDict"

   refresh_token(refresh_token: str) -> BaseTokenDict

      Method for requesting a new access token for a given
      "refresh_token". Token must have been created by the same OAuth
      client.

      Parameters:
         **refresh_token** ("str") -- Corresponding "refresh_token"
         for a matching "access_token". Obtained via

      Return type:
         "BaseTokenDict"

   token_from_code(device_code: str) -> RefreshableTokenDict

      Method for verifying user auth code and conversion into a
      FullTokenDict.

      Return type:
         "RefreshableTokenDict"

class ytmusicapi.YTMusic(auth: str | dict | None = None, user: str | None = None, requests_session: Session | None = None, proxies: dict[str, str] | None = None, language: str = 'en', location: str = '', oauth_credentials: OAuthCredentials | None = None)

   Bases: "YTMusicBase", "BrowsingMixin", "SearchMixin", "WatchMixin",
   "ExploreMixin", "LibraryMixin", "PlaylistsMixin", "PodcastsMixin",
   "UploadsMixin"

   Allows automated interactions with YouTube Music by emulating the
   YouTube web client's requests. Permits both authenticated and non-
   authenticated requests. Authentication header data must be provided
   on initialization.

ytmusicapi.setup(filepath: str | None = None, headers_raw: str | None = None) -> str

   Requests browser headers from the user via command line and returns
   a string that can be passed to YTMusic()

   Parameters:
      * **filepath** ("Optional"["str"]) -- Optional filepath to store
        headers to.

      * **headers_raw** ("Optional"["str"]) -- Optional request
        headers copied from browser. Otherwise requested from terminal

   Return type:
      "str"

   Returns:
      configuration headers string

ytmusicapi.setup_oauth(client_id: str, client_secret: str, filepath: str | None = None, session: Session | None = None, proxies: dict | None = None, open_browser: bool = False) -> RefreshingToken

   Starts oauth flow from the terminal and returns a string that can
   be passed to YTMusic()

   Parameters:
      * **client_id** ("str") -- Optional. Used to specify the
        client_id oauth should use for authentication flow. If
        provided, client_secret MUST also be passed or both will be
        ignored.

      * **client_secret** ("str") -- Optional. Same as client_id but
        for the oauth client secret.

      * **session** ("Optional"["Session"]) -- Session to use for
        authentication

      * **proxies** ("Optional"["dict"]) -- Proxies to use for
        authentication

      * **filepath** ("Optional"["str"]) -- Optional filepath to store
        headers to.

      * **open_browser** ("bool") -- If True, open the default browser
        with the setup link

   Return type:
      "RefreshingToken"

   Returns:
      configuration headers string
