Repository: yt-dlp/yt-dlp

Issue:
[youtube] Doesn't follow regional channel redirect
### Checklist

- [X] I'm reporting a broken site
- [X] I've verified that I'm running yt-dlp version **2022.02.04**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
- [X] I've checked that all provided URLs are alive and playable in a browser
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/ytdl-org/youtube-dl#video-url-contains-an-ampersand-and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [ ] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

_No response_

### Description

Channel associated with video can have regional channel urls: 

Video https://www.youtube.com/watch?v=xqTW13AYniY points towards  Super Smash Bros. with the `channel_url` https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ but when you visit the URL in the browser, you get redirected to the regional Nintendo channel e.g. https://www.youtube.com/channel/UCic48jpZWaG_kQ0sj9pTS1w for Germany or https://www.youtube.com/channel/UCn9tXkXDxeHdZ6RZpYB2ELg for France 


If you then attempt to use the original url (https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ), yt-dlp doesn't follow to the regional channel_id and gets unexpected data.

### Verbose log

```shell
yt-dlp -v  -J --flat-playlist --playlist-items 0 https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ
[debug] Command-line config: ['-v', '-J', '--flat-playlist', '--playlist-items', '0', 'https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ']
[debug] Encodings: locale UTF-8, fs utf-8, out utf-8, err utf-8, pref UTF-8
[debug] yt-dlp version 2022.02.04 [c1653e9ef]
[debug] Python version 3.9.7 (CPython 64bit) - Linux-5.4.0-97-generic-x86_64-with
[debug] exe versions: ffmpeg 4.4.1 (setts), ffprobe 4.4.1
[debug] Optional libraries: Cryptodome, mutagen, sqlite, websockets
[debug] Proxy map: {}
[debug] [youtube:tab] Extracting URL: https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ
[youtube:tab] UCwVVpHQ2Cs9iGJfpdFngePQ: Downloading webpage
WARNING: [youtube:tab] Incomplete yt initial data received. Retrying ...
[youtube:tab] UCwVVpHQ2Cs9iGJfpdFngePQ: Downloading webpage (retry #1)
WARNING: [youtube:tab] Incomplete yt initial data received. Retrying ...
[youtube:tab] UCwVVpHQ2Cs9iGJfpdFngePQ: Downloading webpage (retry #2)
WARNING: [youtube:tab] Incomplete yt initial data received. Retrying ...
[youtube:tab] UCwVVpHQ2Cs9iGJfpdFngePQ: Downloading webpage (retry #3)
WARNING: [youtube:tab] Incomplete yt initial data received
[youtube:tab] A channel/user page was given. All the channel's videos will be downloaded. To download only the videos in the home page, add a "/featured" to the URL
[debug] [youtube:tab] Final URL: https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ/videos
ERROR: [youtube:tab] UCwVVpHQ2Cs9iGJfpdFngePQ: Unable to recognize tab page; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using -U; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using -U
  File "/usr/lib/python3.9/site-packages/yt_dlp/extractor/common.py", line 612, in extract
    ie_result = self._real_extract(url)
  File "/usr/lib/python3.9/site-packages/yt_dlp/extractor/youtube.py", line 3618, in wrapper
    info_dict = func(self, url, smuggled_data)
  File "/usr/lib/python3.9/site-packages/yt_dlp/extractor/youtube.py", line 5096, in _real_extract
    raise ExtractorError('Unable to recognize tab page')

null
```



Discussion:
Looks like you can still access the original channel's videos through the uploads playlist - https://www.youtube.com/playlist?list=UUwVVpHQ2Cs9iGJfpdFngePQ

So we have the option to following the (non-standard) redirect - which is easy to do with the current code, however we'll need to add some checks to let the tab extractor know we have followed the redirects.

The other option is to hard-code a redirect to the uploads playlist when a channel and endpoint redirect is given.

Resolving patch:
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -3950,13 +3950,14 @@ def _entries(self, tab, item_id, ytcfg, account_syncid, visitor_data):
             break
 
     @staticmethod
-    def _extract_selected_tab(tabs):
+    def _extract_selected_tab(tabs, fatal=True):
         for tab in tabs:
             renderer = dict_get(tab, ('tabRenderer', 'expandableTabRenderer')) or {}
             if renderer.get('selected') is True:
                 return renderer
         else:
-            raise ExtractorError('Unable to find selected tab')
+            if fatal:
+                raise ExtractorError('Unable to find selected tab')
 
     @classmethod
     def _extract_uploader(cls, data):
@@ -4229,7 +4230,7 @@ def _extract_webpage(self, url, item_id, fatal=True):
                     self.report_warning(error_to_compat_str(e))
                     break
 
-                if dict_get(data, ('contents', 'currentVideoEndpoint')):
+                if dict_get(data, ('contents', 'currentVideoEndpoint', 'onResponseReceivedActions')):
                     break
 
                 last_error = 'Incomplete yt initial data received'
@@ -4248,7 +4249,7 @@ def _extract_data(self, url, item_id, ytcfg=None, fatal=True, webpage_fatal=Fals
             ytcfg = ytcfg or self.extract_ytcfg(item_id, webpage)
             # Reject webpage data if redirected to home page without explicitly requesting
             selected_tab = self._extract_selected_tab(traverse_obj(
-                data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list, default=[])) or {}
+                data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list, default=[]), fatal=False) or {}
             if (url != 'https://www.youtube.com/feed/recommended'
                     and selected_tab.get('tabIdentifier') == 'FEwhat_to_watch'  # Home page
                     and 'no-youtube-channel-redirect' not in self.get_param('compat_opts', [])):
@@ -4280,7 +4281,7 @@ def _extract_tab_endpoint(self, url, item_id, ytcfg=None, fatal=True, default_cl
                 return self._extract_response(
                     item_id=item_id, query=params, ep=ep, headers=headers,
                     ytcfg=ytcfg, fatal=fatal, default_client=default_client,
-                    check_get_keys=('contents', 'currentVideoEndpoint'))
+                    check_get_keys=('contents', 'currentVideoEndpoint', 'onResponseReceivedActions'))
         err_note = 'Failed to resolve url (does the playlist exist?)'
         if fatal:
             raise ExtractorError(err_note, expected=True)
@@ -4981,6 +4982,10 @@ class YoutubeTabIE(YoutubeTabBaseInfoExtractor):
             'skip_download': True,
             'extractor_args': {'youtubetab': {'skip': ['webpage']}}
         },
+    }, {
+        'note': 'non-standard redirect to regional channel',
+        'url': 'https://www.youtube.com/channel/UCwVVpHQ2Cs9iGJfpdFngePQ',
+        'only_matching': True
     }]
 
     @classmethod
@@ -5053,6 +5058,16 @@ def get_mobj(url):
 
         data, ytcfg = self._extract_data(url, item_id)
 
+        # YouTube may provide a non-standard redirect to the regional channel
+        # See: https://github.com/yt-dlp/yt-dlp/issues/2694
+        redirect_url = traverse_obj(
+            data, ('onResponseReceivedActions', ..., 'navigateAction', 'endpoint', 'commandMetadata', 'webCommandMetadata', 'url'), get_all=False)
+        if redirect_url and 'no-youtube-channel-redirect' not in compat_opts:
+            redirect_url = ''.join((
+                urljoin('https://www.youtube.com', redirect_url), mobj['tab'], mobj['post']))
+            self.to_screen(f'This playlist is likely not available in your region. Following redirect to regional playlist {redirect_url}')
+            return self.url_result(redirect_url, ie=YoutubeTabIE.ie_key())
+
         tabs = traverse_obj(data, ('contents', 'twoColumnBrowseResultsRenderer', 'tabs'), expected_type=list)
         if tabs:
             selected_tab = self._extract_selected_tab(tabs)


Test patch: