yt-dlp/yt-dlp · error · ExtractorError

Unsupported language code: {preferred_lang}. Supported langu

Error message

Unsupported language code: {preferred_lang}. Supported language codes (case-sensitive): {join_nonempty(*self._SUPPORTED_LANG_CODES, delim=", ")}.

What it means

YoutubeBaseInfoExtractor._preferred_lang (a functools.cached_property) validates the youtube:lang extractor argument against the hard-coded _SUPPORTED_LANG_CODES list using casesense=True. Any code not in that list aborts extraction immediately with expected=True, and the error message prints the full supported list. Codes like 'en', 'de', 'pt-PT', 'zh-CN', 'ja' are valid; near-misses like 'EN', 'pt-BR' (not listed), or 'zh' are not.

Source

Thrown at yt_dlp/extractor/youtube/_base.py:651

    def handle_from_url(self, url):
        return self._search_regex(rf'^(?:https?://(?:www\.)?youtube\.com)?/({self._YT_HANDLE_RE})',
                                  urllib.parse.unquote(url or ''), 'channel handle', default=None)

    def ucid_from_url(self, url):
        return self._search_regex(rf'^(?:https?://(?:www\.)?youtube\.com)?/({self._YT_CHANNEL_UCID_RE})',
                                  url, 'channel id', default=None)

    @functools.cached_property
    def _preferred_lang(self):
        """
        Returns a language code supported by YouTube for the user preferred language.
        Returns None if no preferred language set.
        """
        preferred_lang = self._configuration_arg('lang', ie_key='Youtube', casesense=True, default=[''])[0]
        if not preferred_lang:
            return
        if preferred_lang not in self._SUPPORTED_LANG_CODES:
            raise ExtractorError(
                f'Unsupported language code: {preferred_lang}. Supported language codes (case-sensitive): {join_nonempty(*self._SUPPORTED_LANG_CODES, delim=", ")}.',
                expected=True)
        elif preferred_lang != 'en':
            self.report_warning(
                f'Preferring "{preferred_lang}" translated fields. Note that some metadata extraction may fail or be incorrect.')
        return preferred_lang

    def _initialize_consent(self):
        if self._has_auth_cookies:
            return
        socs = self._youtube_cookies.get('SOCS')
        if socs and not socs.value.startswith('CAA'):  # not consented
            return
        self._set_cookie('.youtube.com', 'SOCS', 'CAI', secure=True)  # accept all (required for mixes)

    def _initialize_pref(self):
        pref_cookie = self._youtube_cookies.get('PREF')
        pref = {}

View on GitHub (pinned to 81ecd58b13)

Solutions

  1. Re-run with a code taken verbatim from the error message's supported list (e.g. youtube:lang=pt-PT, youtube:lang=zh-CN, youtube:lang=en-GB)
  2. Check exact casing: 'en' not 'EN', 'zh-CN' not 'zh-cn'
  3. Update yt-dlp; the supported-codes list changes over releases and newer builds may accept your code
  4. Drop the lang argument entirely if you do not need translated metadata

Example fix

# before
yt-dlp --extractor-args "youtube:lang=pt-BR" "https://www.youtube.com/watch?v=..."
# -> Unsupported language code: pt-BR. ...

# after
yt-dlp --extractor-args "youtube:lang=pt-PT" "https://www.youtube.com/watch?v=..."
Defensive patterns

Strategy: validation

Validate before calling

from yt_dlp.extractor.youtube._base import YoutubeBaseInfoExtractor

lang = 'pt-PT'  # value you intend to pass as youtube:lang
if lang not in YoutubeBaseInfoExtractor._SUPPORTED_LANG_CODES:
    raise ValueError(
        f'{lang!r} unsupported; pick one of: {YoutubeBaseInfoExtractor._SUPPORTED_LANG_CODES}')

Prevention

When it happens

Trigger: Running any YouTube extraction while --extractor-args youtube:lang=CODE is set and CODE is misspelled, wrong case (the check is case-sensitive), or a variant the list does not contain (e.g. 'pt-BR', 'nb', 'zh'). The property is cached, so the very first URL touching it fails.

Common situations: Copy-pasting a locale from elsewhere (BCP-47 with wrong region), assuming case-insensitivity, using an OS locale name instead of YouTube's list, or running an old yt-dlp whose supported list predates newly added codes.

Related errors


AI-assisted analysis of yt-dlp/yt-dlp@81ecd58b13 (2026-08-22). Data as JSON: /api/errors/fe58c1171edd039e. Report an issue: GitHub.