diff --git a/yt_dlp/extractor/spankbang.py b/yt_dlp/extractor/spankbang.py
index 6805a72deb7b..05f0bb1468ed 100644
--- a/yt_dlp/extractor/spankbang.py
+++ b/yt_dlp/extractor/spankbang.py
@@ -71,9 +71,11 @@ class SpankBangIE(InfoExtractor):
     def _real_extract(self, url):
         mobj = self._match_valid_url(url)
         video_id = mobj.group('id') or mobj.group('id_2')
+        country = self.get_param('geo_bypass_country') or 'US'
+        self._set_cookie('.spankbang.com', 'country', country.upper())
         webpage = self._download_webpage(
             url.replace(f'/{video_id}/embed', f'/{video_id}/video'),
-            video_id, headers={'Cookie': 'country=US'})
+            video_id, impersonate=True)

         if re.search(r'<[^>]+\b(?:id|class)=["\']video_removed', webpage):
             raise ExtractorError(

spankbang - 403 Forbidden errors
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting that a **supported** site is broken
- [X] I've verified that I'm running yt-dlp version **2023.03.04** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#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 [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and 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)
- [X] 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

USA

### Provide a description that is worded well enough to be understood

All video url's from Spankbang are returning 403 forbidden errors. I have confirmed that they load and play in the browser just fine. Verbose output is provided. My `yt-dlp` version is completely up to date.

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
> yt-dlp -vU https://spankbang.com/6c6z5/video/fan+appreciation+event+english+sub
[debug] Command-line config: ['-vU', 'https://spankbang.com/6c6z5/video/fan+appreciation+event+english+sub']
[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] (zip)
[debug] Python version 3.8.10 (CPython 64bit) - Linux-4.4.0-19041-Microsoft-x86_64-with-glibc2.29
[debug] exe versions: ffmpeg 4.2.4, ffprobe 4.2.4
[debug] Optional libraries: Cryptodome, secretstorage, mutagen, sqlite, websockets
[debug] Proxy map: {}
Latest version: 2023.03.04, Current version: 2022.02.04
Current Build Hash a16fe3b3bd474d562c4b8645579b209377b967d58d4edffe6e31dc8de81d7283
Updating to version 2023.03.04 ...
ERROR: Unable to write to /usr/local/bin/yt-dlp; Try running as administrator
[debug] [SpankBang] Extracting URL: https://spankbang.com/6c6z5/video/fan+appreciation+event+english+sub
[SpankBang] 6c6z5: Downloading webpage
ERROR: [SpankBang] 6c6z5: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: 'Forbidden'>); 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 (caused by <HTTPError 403: 'Forbidden'>); 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/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 730, in _request_webpage
    return self._downloader.urlopen(url_or_request)
  File "/usr/local/bin/yt-dlp/yt_dlp/YoutubeDL.py", line 3558, in urlopen    return self._opener.open(req, timeout=self._socket_timeout)  File "/usr/lib/python3.8/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/lib/python3.8/urllib/request.py", line 640, in http_response
    response = self.parent.error(
  File "/usr/lib/python3.8/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
```

> My yt-dlp version is completely up to date.

> [debug] yt-dlp version **2022.02.04** [c1653e9ef] (zip)

> Latest version: **2023.03.04**, Current version: **2022.02.04**

> Updating to version 2023.03.04 ...
> **ERROR: Unable to write to /usr/local/bin/yt-dlp; Try running as administrator**
I see in the logs that it shows my `yt-dlp` version as 2022.02.04 but when I try to update using python, it says that I'm up to date already.
And when I try to update via `yt-dlp -U`:

```
Available version: stable@2023.03.04, Current version: stable@2023.03.04
Current Build Hash: 91cad9f121c1f6f0a81b747415c46ecba0ff331ed38cc6433040b4ac7b6e15ca
yt-dlp is up to date (stable@2023.03.04)
```
```
> yt-dlp --version
2023.03.04
```
The log in the OP most definitely is **not** from version 2023.03.04. Are you sure you're not running two different versions? The first log looks like it's being run in WSL?

> The log in the OP most definitely is **not** from version 2023.03.04. Are you sure you're not running two different versions? The first log looks like it's being run in WSL?

Yep, looks like I was. I ran `pip3 uninstall yt-dlp` but the command was still accessible. So looks like I had two installations going. Removing the python version got everything working. Thanks, feel free to close this issue.
Hi @bashonly , I use the master version will get 403 too
```bash
[debug] Command-line config: ['-v', '--proxy', 'http://127.0.0.1:1080', 'https://spankbang.com/81sy6/video/japanese']
[debug] Encodings: locale cp936, fs utf-8, pref cp936, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.03.04 [392389b7d]
[debug] Lazy loading extractors is disabled
[debug] Python 3.8.10 (CPython AMD64 32bit) - Windows-10-10.0.22621-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg 4.2.1 (fdk), ffprobe 4.2.1
[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2020.12.05, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4
[debug] Proxy map: {'http': 'http://127.0.0.1:1080', 'https': 'http://127.0.0.1:1080'}
[debug] Loaded 1791 extractors
[SpankBang] Extracting URL: https://spankbang.com/81sy6/video/japanese
[SpankBang] 81sy6: Downloading webpage
ERROR: [SpankBang] 81sy6: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: 'Forbidden'>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 694, in extract
    ie_result = self._real_extract(url)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\spankbang.py", line 74, in _real_extract
    webpage = self._download_webpage(
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 1100, in _download_webpage
    return self.__download_webpage(url_or_request, video_id, note, errnote, None, fatal, *args, **kwargs)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 1051, in download_content
    res = getattr(self, download_handle.__name__)(url_or_request, video_id, **kwargs)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 885, in _download_webpage_handle
    urlh = self._request_webpage(url_or_request, video_id, note, errnote, fatal, data=data, headers=headers, query=query, expected_status=expected_status)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 842, in _request_webpage
    raise ExtractorError(errmsg, cause=err)

  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 824, in _request_webpage
    return self._downloader.urlopen(self._create_request(url_or_request, data, headers, query))
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\YoutubeDL.py", line 3745, in urlopen
    return self._opener.open(req, timeout=self._socket_timeout)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 531, in open
    response = meth(req, response)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 640, in http_response
    response = self.parent.error(
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 569, in error
    return self._call_chain(*args)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 502, in _call_chain
    result = func(*args)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 649, in http_error_default

    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden
```

but the 2022.07.18 on my WSL will succeed
```bash
[debug] Command-line config: ['-v', '--proxy', 'http://127.0.0.1:1080', 'https://spankbang.com/81sy6/video/japanese']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out UTF-8, error UTF-8, screen UTF-8
[debug] yt-dlp version 2022.07.18 [135f05ef6]
[debug] Lazy loading extractors is disabled
[debug] Python 3.7.5 (CPython 64bit) - Linux-4.4.0-22621-Microsoft-x86_64-with-Ubuntu-18.04-bionic (glibc 2.26)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 3.4.8, ffprobe 3.4.8
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2020.12.05, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
[debug] Proxy map: {'http': 'http://127.0.0.1:1080', 'https': 'http://127.0.0.1:1080'}
[debug] [SpankBang] Extracting URL: https://spankbang.com/81sy6/video/japanese
[SpankBang] 81sy6: Downloading webpage
[SpankBang] 81sy6: Downloading stream JSON
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 81sy6: Downloading 1 format(s): hls-2564-1
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/1/3/13521102-1080p.mp4/index-v1-a1.m3u8?_tid=13521102&d=1&m=43&secure=nxKExkSSNg5q0juEWzONGA,1680835039"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 810
[download] Destination: Japanese [81sy6].mp4
[download]   0.5% of ~662.91MiB at  151.59KiB/s ETA 27:28 (frag 5/810)
```
I can't reproduce the 403. Maybe it's due to a change in network/proxy code?
```
$ yt-dlp --ignore-config -vF "https://spankbang.com/81sy6/video/japanese"
[debug] Command-line config: ['--ignore-config', '-vF', 'https://spankbang.com/81sy6/video/japanese']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.03.04 [392389b7d]
[debug] Lazy loading extractors is disabled
[debug] Python 3.10.10 (CPython x86_64 64bit) - Linux-6.2.8-arch1-1-x86_64-with-glibc2.37 (OpenSSL 3.0.8 7 Feb 2023, glibc 2.37)
[debug] exe versions: ffmpeg 6.0 (setts), ffprobe 6.0
[debug] Optional libraries: Cryptodome-3.12.0, brotlicffi-1.0.9.2, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4
[debug] Proxy map: {}
[debug] Loaded 1791 extractors
[SpankBang] Extracting URL: https://spankbang.com/81sy6/video/japanese
[SpankBang] 81sy6: Downloading webpage
[SpankBang] 81sy6: Downloading stream JSON
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[info] Available formats for 81sy6:
ID         EXT RESOLUTION FPS │   FILESIZE   TBR PROTO │ VCODEC        VBR ACODEC    ABR
────────────────────────────────────────────────────────────────────────────────────────
240p       mp4 240p           │                  https │ unknown           unknown
hls-379-0  mp4 426x240     25 │ ~224.74MiB  380k m3u8  │ avc1.42c01e  380k mp4a.40.2  0k
hls-379-1  mp4 426x240     25 │ ~224.74MiB  380k m3u8  │ avc1.42c01e  380k mp4a.40.2  0k
480p       mp4 480p           │                  https │ unknown           unknown
hls-1090-0 mp4 852x480     25 │ ~645.52MiB 1091k m3u8  │ avc1.4d401f 1091k mp4a.40.2  0k
hls-1090-1 mp4 852x480     25 │ ~645.52MiB 1091k m3u8  │ avc1.4d401f 1091k mp4a.40.2  0k
720p       mp4 720p           │                  https │ unknown           unknown
hls-1996-0 mp4 1280x720    25 │ ~  1.15GiB 1996k m3u8  │ avc1.640020 1996k mp4a.40.2  0k
hls-1996-1 mp4 1280x720    25 │ ~  1.15GiB 1996k m3u8  │ avc1.640020 1996k mp4a.40.2  0k
1080p      mp4 1080p          │                  https │ unknown           unknown
hls-2564-0 mp4 1920x1080   25 │ ~  1.48GiB 2565k m3u8  │ avc1.64002a 2565k mp4a.40.2  0k
hls-2564-1 mp4 1920x1080   25 │ ~  1.48GiB 2565k m3u8  │ avc1.64002a 2565k mp4a.40.2  0k
```
Termux also get `403`

```
yt-dlp --ignore-config -vF https://spankbang.com/782eu/video/band+girl+part+2+1
[debug] Command-line config: ['--ignore-config', '-vF', 'https://spankbang.com/782eu/video/band+girl+part+2+1']
[debug] Encodings: locale utf-8, fs utf-8, pref utf-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.03.04 [392389b7d] (pip)
[debug] Python 3.11.2 (CPython aarch64 64bit) - Linux-4.14.309-classified+-aarch64-with-libc (OpenSSL 3.1.0 14 Mar 2023, libc)
[debug] exe versions: none
[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4
[debug] Proxy map: {}
[debug] Loaded 1786 extractors
[SpankBang] Extracting URL: https://spankbang.com/782eu/video/band+girl+part+2+1
[SpankBang] 782eu: Downloading webpage
ERROR: [SpankBang] 782eu: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: 'Forbidden'>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/common.py", line 694, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/spankbang.py", line 74, in _real_extract
    webpage = self._download_webpage(
              ^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/common.py", line 1097, in _download_webpage
    return self.__download_webpage(url_or_request, video_id, note, errnote, None, fatal, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/common.py", line 1048, in download_content
    res = getattr(self, download_handle.__name__)(url_or_request, video_id, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/common.py", line 882, in _download_webpage_handle
    urlh = self._request_webpage(url_or_request, video_id, note, errnote, fatal, data=data, headers=headers, query=query, expected_status=expected_status)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/common.py", line 839, in _request_webpage
    raise ExtractorError(errmsg, cause=err)

  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/extractor/common.py", line 821, in _request_webpage
    return self._downloader.urlopen(self._create_request(url_or_request, data, headers, query))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 3742, in urlopen
    return self._opener.open(req, timeout=self._socket_timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/urllib/request.py", line 525, in open
    response = meth(req, response)
               ^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/urllib/request.py", line 634, in http_response
    response = self.parent.error(
               ^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/urllib/request.py", line 563, in error
    return self._call_chain(*args)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/urllib/request.py", line 496, in _call_chain
    result = func(*args)
             ^^^^^^^^^^^
  File "/data/data/com.termux/files/usr/lib/python3.11/urllib/request.py", line 643, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

```
yt-dlp stable@2023.03.04 isn't showing 403 for me with `81sy6`, but yt-dl (essentially identical extractor code) is getting 403 on the webpage itself, as is is _wget_, not showing any page content in the response. UA 'Mozilla/5.0' may break through CloudFlare: it works with yt-dl and _wget_ now, though not when I first tried.
Hi,
@bashonly the proxy network can work on my wsl with version 2022.07.18, the wsl on the same computer, so they use the same proxy
```bash
[debug] Command-line config: ['-v', '--proxy', 'http://127.0.0.1:1080', 'https://spankbang.com/81sy6/video/japanese']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out UTF-8, error UTF-8, screen UTF-8
[debug] yt-dlp version 2022.07.18 [135f05ef6]
[debug] Lazy loading extractors is disabled
[debug] Python 3.7.5 (CPython 64bit) - Linux-4.4.0-22621-Microsoft-x86_64-with-Ubuntu-18.04-bionic (glibc 2.26)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 3.4.8, ffprobe 3.4.8
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2020.12.05, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
[debug] Proxy map: {'http': 'http://127.0.0.1:1080', 'https': 'http://127.0.0.1:1080'}
[debug] [SpankBang] Extracting URL: https://spankbang.com/81sy6/video/japanese
[SpankBang] 81sy6: Downloading webpage
[SpankBang] 81sy6: Downloading stream JSON
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[SpankBang] 81sy6: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 81sy6: Downloading 1 format(s): hls-2564-1
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/1/3/13521102-1080p.mp4/index-v1-a1.m3u8?_tid=13521102&d=1&m=43&secure=nxKExkSSNg5q0juEWzONGA,1680835039"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 810
[download] Destination: Japanese [81sy6].mp4
[download]   0.5% of ~662.91MiB at  151.59KiB/s ETA 27:28 (frag 5/810)
```

@dirkf if I add set UA to 'Mozilla/5.0', I will get this output
```bash
[debug] Command-line config: ['-v', '--proxy', '127.0.0.1:1080', '--add-header', 'User-Agent:Mozilla/5.0', 'http://127.0.0.1:1080', 'https://spankbang.com/81sy6/video/japanese']
[debug] Encodings: locale cp936, fs utf-8, pref cp936, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.03.04 [392389b7d]
[debug] Lazy loading extractors is disabled
[debug] Python 3.8.10 (CPython AMD64 32bit) - Windows-10-10.0.22621-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg 4.2.1 (fdk), ffprobe 4.2.1
[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2020.12.05, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4
[debug] Proxy map: {'http': '127.0.0.1:1080', 'https': '127.0.0.1:1080'}
[debug] Loaded 1791 extractors
[generic] Extracting URL: http://127.0.0.1:1080
[generic] 127.0.0: Downloading webpage
ERROR: [generic] None: Unable to download webpage: HTTP Error 400: Invalid header received from client (caused by <HTTPError 400: 'Invalid header received from client'>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 694, in extract
    ie_result = self._real_extract(url)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\generic.py", line 2385, in _real_extract
    full_response = self._request_webpage(url, video_id, headers={
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 842, in _request_webpage
    raise ExtractorError(errmsg, cause=err)

  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 824, in _request_webpage
    return self._downloader.urlopen(self._create_request(url_or_request, data, headers, query))
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\YoutubeDL.py", line 3745, in urlopen
    return self._opener.open(req, timeout=self._socket_timeout)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 531, in open
    response = meth(req, response)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 640, in http_response
    response = self.parent.error(
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 569, in error
    return self._call_chain(*args)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 502, in _call_chain
    result = func(*args)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: Invalid header received from client

[SpankBang] Extracting URL: https://spankbang.com/81sy6/video/japanese
[SpankBang] 81sy6: Downloading webpage
ERROR: [SpankBang] 81sy6: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: 'Forbidden'>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 694, in extract
    ie_result = self._real_extract(url)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\spankbang.py", line 74, in _real_extract
    webpage = self._download_webpage(
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 1100, in _download_webpage
    return self.__download_webpage(url_or_request, video_id, note, errnote, None, fatal, *args, **kwargs)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 1051, in download_content
    res = getattr(self, download_handle.__name__)(url_or_request, video_id, **kwargs)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 885, in _download_webpage_handle
    urlh = self._request_webpage(url_or_request, video_id, note, errnote, fatal, data=data, headers=headers, query=query, expected_status=expected_status)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 842, in _request_webpage
    raise ExtractorError(errmsg, cause=err)

  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\extractor\common.py", line 824, in _request_webpage
    return self._downloader.urlopen(self._create_request(url_or_request, data, headers, query))
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\site-packages\yt_dlp-2023.3.4-py3.8.egg\yt_dlp\YoutubeDL.py", line 3745, in urlopen
    return self._opener.open(req, timeout=self._socket_timeout)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 531, in open
    response = meth(req, response)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 640, in http_response
    response = self.parent.error(
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 569, in error
    return self._call_chain(*args)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 502, in _call_chain
    result = func(*args)
  File "C:\Users\test\AppData\Local\Programs\Python\Python38-32\lib\urllib\request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden
```
workaround: try adding `--legacy-server-connect` to your command
I was able to fix this by switching to a different proxy/vpn
In my case, `'Cookie': 'country=US'` in `_real_extract` of `extractor/spankbang.py` needs to be manually replaced with the Cookie header. Note that setting the user-agent will cause a 403 error, even after replacing `'Cookie': 'country=US'`. Additionally, the cookie must be added to the `self._download_json()` method. Also, the cookie needs to be renewed after it expires.

Details [in this comment](https://github.com/yt-dlp/yt-dlp/issues/6545#issuecomment-1609300876).
> In my case, `'Cookie': 'country=US'` in `_real_extract` of `extractor/spankbang.py` needs to be manually replaced with the Cookie header. Note that setting the user-agent will cause a 403 error, even after replacing `'Cookie': 'country=US'`. Additionally, the cookie must be added to the `self._download_json()` method. Also, the cookie needs to be renewed after it expires.

can you go into greater detail please?
> > In my case, `'Cookie': 'country=US'` in `_real_extract` of `extractor/spankbang.py` needs to be manually replaced with the Cookie header. Note that setting the user-agent will cause a 403 error, even after replacing `'Cookie': 'country=US'`. Additionally, the cookie must be added to the `self._download_json()` method. Also, the cookie needs to be renewed after it expires.
>
> can you go into greater detail please?

Simply right-click on video web page - >"Inspect" -> "Network" tab -> click upper left "Clear" button -> Ctrl+R Reload page -> click current page url item(normally first item or it has blue icon on left side) -> right panel -> "Headers" tab -> "Requests Headers" section), copy **Cookie**'s value(and copy **User-Agent**'s value later) and paste into the below **4 Lines to replace:** in the file `extractor/spankbang.py` (  you can find parent folder of `extractor/spankbang.py` with command `python3 -c "import yt_dlp; print(yt_dlp.__path__[0])"`   ). ->  save the edited file -> rerun yt-dlp should no more 403 error.

**4 Lines to edit:**

[1]
 Add this line `MY_COOKIE = ` on top of line `class SpankBangIE(InfoExtractor):` with your copied cookie value, you only need to edit this line in future when renew cookie, e.g.:
```

MY_COOKIE = 'paste your copied cookie value, surrounded with single quotes. No extra space'

class SpankBangIE(InfoExtractor):
```

[2]
`url, playlist_id, headers={'Cookie': 'country=US; mobile=on'})`

edit it to:

`url, playlist_id, headers={'Cookie': MY_COOKIE})`

and:

[3]
`video_id, headers={'Cookie': 'country=US'})`

edit it to:

`video_id, headers={'Cookie': MY_COOKIE})`

[4]
Then under `self._download_json` need add cookie too, e.g.:

```
                }), headers={
                    'Referer': url,
                    'X-Requested-With': 'XMLHttpRequest',
                })
```

edit it to:

```
                   }), headers={
                    'Cookie': MY_COOKIE,
                    'Referer': url,
                    'X-Requested-With': 'XMLHttpRequest',
                })
```

Note that the **spaces before the lines** need typing space instead of tab. And ensure total spaces same as original.

Note that the cookie needs renewal after it expires or the IP changes. You may need clear and reload page if first attempt of cookie not working. Ensure copy the complete cookie value. Update yt-dlp may replace this code and need redo.

You also need add your copied latest **User-Agent**'s value(same steps as get **Cookie**'s value. It probably updated when web browser update) to your command, e.g. `--add-headers 'User-Agent:paste your copied user-agent value, surrounded with single quotes'`:

`yt-dlp --add-headers 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'  ...`

Note that you need to use user agent get from the **same web browser** of the cookie above.

[UPDATE 2024]: `extractor/spankbang.py` needs to disable .m3u8 and allow only .mp4 if you encounter `HTTP Error 502: Bad Gateway`:
```
            ext = determine_ext(f_url)
            ''' # Add this to start disable m3u8
            if format_id.startswith('m3u8') or ext == 'm3u8':
                formats.extend(self._extract_m3u8_formats(
                    f_url, video_id, 'mp4', entry_protocol='m3u8_native',
                    m3u8_id='hls', fatal=False))
            elif format_id.startswith('mpd') or ext == 'mpd':
                formats.extend(self._extract_mpd_formats(
                    f_url, video_id, mpd_id='dash', fatal=False))
            elif ext == 'mp4' or f.get('width') or f.get('height'):
            ''' # Add this to end disable
            if ext == 'mp4' or f.get('width') or f.get('height'): # New Added
```
Tried the above and still getting 403 forbidden. Verified formatting and complete cookie value.
The extractor needs to be fixed so that it's not hardcoding a cookie header into the request. It should check if the user has passed the necessary cookies (via `--cookies` or `--cookies-from-browser`), and if not, then set cookie(s) to the cookiejar before the request(s)
> The extractor needs to be fixed so that it's not hardcoding a cookie header into the request. It should check if the user has passed the necessary cookies (via `--cookies` or `--cookies-from-browser`), and if not, then set cookie(s) to the cookiejar before the request(s)

I found one of your previous suggestions of adding --legacy-server-connect to my config file and it seems to working through my testing so far.
> adding --legacy-server-connect to my config file

don't do this. only use this option when needed
> > adding --legacy-server-connect to my config file
>
> don't do this. only use this option when needed

good call. created separate config and batch to call that option if needed.
Confirmed. Still happening on latest. Not happening on any other site.
> In my case, `'Cookie': 'country=US'` in `_real_extract` of `extractor/spankbang.py` needs to be manually replaced with the Cookie header. Note that setting the user-agent will cause a 403 error, even after replacing `'Cookie': 'country=US'`. Additionally, the cookie must be added to the `self._download_json()` method. Also, the cookie needs to be renewed after it expires.

This work but cookie expire really fast. Need to renew about after 10-20 downloads
not sure if its possible to add this import to the extractor, but using this package bypasses cloudflares 403 page and returns the real page source

`pip install cloudscraper`

```python
import cloudscraper
url = "https://spankbang.com/5icow/video/skylarvox08"
scraper = cloudscraper.create_scraper()
content = scraper.get(url).content

print(content) # bytes
#or
print(content.decode('utf-8'))
```
#7595, once completed, should fix this
Anyone got a work around, I've tried almost all the answers ? I'm using the last version of yt-dlp with python 3.11.4, youtube is working fine, but spankbang is not got like op " 8iidg: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: 'Forbidden'>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U"
One workaround I found is working perfectly.

Just change the URL from https://spankbang.com/5icow/video/skylarvox08 to https://spankbang.party/5icow/video/skylarvox08

Domain part from spankbang.com to spankbang.party works perfectly for all URLs I tested.

> One workaround I found is working perfectly.
>
> Just change the URL from https://spankbang.com/5icow/video/skylarvox08 to https://spankbang.party/5icow/video/skylarvox08
>
> Domain part from spankbang.com to spankbang.party works perfectly for all URLs I tested.

This will only allow 720p downloads
@cosify The above URL has 4K resolution but maybe it's a yt-dlp issue that it only gets up to 720p.

You can check by getting the HTML content of the URL and searching for **var stream_data = {**

Isn't the HTML5 format `4` found by the generic extractor 4320x2160 (actually 2x2160x2160 since this video is 3D)?

If the SB extractor is tweaked to recognise `.party` and to use that root domain for its `stream JSON` retrieval:
```console
$ yt-dlp -v -F 'https://spankbang.party/5icow/video/skylarvox08'
[debug] Command-line config: ['-v', '-F', 'https://spankbang.party/5icow/video/skylarvox08']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.06.22 [812cdfa06] (source)
[debug] Lazy loading extractors is disabled
[debug] Git HEAD: de4cf77ec
[debug] Python 3.9.16 (CPython i686 32bit) - Linux-4.4.0-210-generic-i686-with-glibc2.23 (OpenSSL 1.1.1v  1 Aug 2023, glibc 2.23)
[debug] exe versions: ffmpeg 4.3, ffprobe 4.3
[debug] Optional libraries: Cryptodome-3.11.0, certifi-2019.11.28, secretstorage-3.2.0, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Loaded 1851 extractors
[SpankBang] Extracting URL: https://spankbang.party/5icow/video/skylarvox08
[SpankBang] 5icow: Downloading webpage
[SpankBang] 5icow: Downloading stream JSON
[SpankBang] 5icow: Downloading m3u8 information
[SpankBang] 5icow: Downloading m3u8 information
[SpankBang] 5icow: Downloading m3u8 information
[SpankBang] 5icow: Downloading m3u8 information
[SpankBang] 5icow: Downloading m3u8 information
[SpankBang] 5icow: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[info] Available formats for 5icow:
ID         EXT RESOLUTION FPS │   FILESIZE   TBR PROTO │ VCODEC      ACODEC
──────────────────────────────────────────────────────────────────────────────
240p       mp4 240p           │                  https │ unknown     unknown
hls-231-0  mp4 480x240     30 │ ~ 60.42MiB  231k m3u8  │ avc1.42c01e mp4a.40.2
hls-231-1  mp4 480x240     30 │ ~ 60.42MiB  231k m3u8  │ avc1.42c01e mp4a.40.2
480p       mp4 480p           │                  https │ unknown     unknown
hls-1201-0 mp4 960x480     30 │ ~314.06MiB 1202k m3u8  │ avc1.4d401f mp4a.40.2
hls-1201-1 mp4 960x480     30 │ ~314.06MiB 1202k m3u8  │ avc1.4d401f mp4a.40.2
720p       mp4 720p           │                  https │ unknown     unknown
hls-2172-0 mp4 1440x720    30 │ ~567.77MiB 2172k m3u8  │ avc1.640020 mp4a.40.2
hls-2172-1 mp4 1440x720    30 │ ~567.77MiB 2172k m3u8  │ avc1.640020 mp4a.40.2
1080p      mp4 1080p          │                  https │ unknown     unknown
hls-3390-0 mp4 2160x1080   30 │ ~886.07MiB 3390k m3u8  │ avc1.64002a mp4a.40.2
hls-3390-1 mp4 2160x1080   30 │ ~886.07MiB 3390k m3u8  │ avc1.64002a mp4a.40.2
4k         mp4 2160p          │                  https │ unknown     unknown
hls-5543-0 mp4 4320x2160   30 │ ~  1.41GiB 5543k m3u8  │ avc1.640034 mp4a.40.2
hls-5543-1 mp4 4320x2160   30 │ ~  1.41GiB 5543k m3u8  │ avc1.640034 mp4a.40.2
$
```
@dirkf any plans to submit a PR? I would assume that it would be within scope to automatically use spankbang.party's server, unless that's an unofficial mirror, which I highly doubt
seems to work with the party server but it doesn't work with playlist links
I've noticed yt-dlp using TLSv1_2 while the web browser uses TLSv1_3.

You can **temporarily** add TLSv1_3 in `yt_dlp/networking/_helper.py` : _(Note that this affects all websites, so you should revert these changes if other websites stop working.)_

```

#context.minimum_version = ssl.TLSVersion.TLSv1_2
context.minimum_version = ssl.TLSVersion.TLSv1_3
```

Similar issue [#25437](https://github.com/ytdl-org/youtube-dl/issues/25437)

I've got the same issue. Logs:

```
yt-dlp.exe -v https://spankbang.com/7ihal/video/perfect+body+strip+tease+3+seductive+cam+show+dance+shows+off+everything+she+s+got

[debug] Command-line config: ['-v', '--proxy', 'socks5://127.0.0.1:9999', 'https://spankbang.com/7ihal/video/perfect+body+strip+tease+3+seductive+cam+show+dance+shows+off+everything+she+s+got']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.09.24 [088add956] (win_exe)
[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.22621-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: none
[debug] Optional libraries: Cryptodome-3.19.0, brotli-1.1.0, certifi-2023.07.22, mutagen-1.47.0, sqlite3-3.35.5, websockets-11.0.3
[debug] Proxy map: {'all': 'socks5://127.0.0.1:9999'}
[debug] Loaded 1886 extractors
[SpankBang] Extracting URL: https://spankbang.com/7ihal/video/perfect+body+strip+tease+3+seductive+cam+show+dance+shows+off+everything+she+s+got
[SpankBang] 7ihal: Downloading webpage
ERROR: [SpankBang] 7ihal: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: Forbidden>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "yt_dlp\extractor\common.py", line 715, in extract
  File "yt_dlp\extractor\spankbang.py", line 74, in _real_extract
  File "yt_dlp\extractor\common.py", line 1118, in _download_webpage
  File "yt_dlp\extractor\common.py", line 1069, in download_content
  File "yt_dlp\extractor\common.py", line 903, in _download_webpage_handle
  File "yt_dlp\extractor\common.py", line 860, in _request_webpage

  File "yt_dlp\networking\_urllib.py", line 410, in _send
  File "urllib\request.py", line 531, in open
  File "urllib\request.py", line 640, in http_response
  File "urllib\request.py", line 569, in error
  File "urllib\request.py", line 502, in _call_chain
  File "urllib\request.py", line 649, in http_error_default
urllib.error.HTTPError: HTTP Error 403: Forbidden

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "yt_dlp\YoutubeDL.py", line 4051, in urlopen
  File "yt_dlp\networking\common.py", line 114, in send
  File "yt_dlp\networking\_helper.py", line 204, in wrapper
  File "yt_dlp\networking\common.py", line 325, in send
  File "yt_dlp\networking\_urllib.py", line 415, in _send
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: Forbidden

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "yt_dlp\extractor\common.py", line 847, in _request_webpage
  File "yt_dlp\YoutubeDL.py", line 4070, in urlopen
yt_dlp.networking.exceptions._CompatHTTPError: HTTP Error 403: Forbidden
```
> I've noticed yt-dlp using TLSv1_2 while the web browser uses TLSv1_3.
>
> You can **temporarily** add TLSv1_3 in `yt_dlp/networking/_helper.py` (note that this affects all requests, of course):
>
> ```
>
> #context.minimum_version = ssl.TLSVersion.TLSv1_2
> context.minimum_version = ssl.TLSVersion.TLSv1_3
> ```
>
> Similar issue [#25437](https://github.com/ytdl-org/youtube-dl/issues/25437)

This worked for me.  I think this library (_helper.py) is too global to change that value for the whole project, but it would be nice if specific extractors/downloaders could set that value to workaround this issue.
> I would assume that it would be within scope to automatically use spankbang.party's server, unless that's an unofficial mirror, which I highly doubt

Actually I'm not sure. Spankbang.party looks kinda dodgy, is it possible that it's an unofficial mirror?
The .party and .com domains are both registered via NameCheap from `Capital Region` (Reykjavik, apparently) with the same authoritative domain servers in ns.cloudflare.com. I wouldn't worry.
> The .party and .com domains are both registered via NameCheap from Capital Region (Reykjavik, apparently)

that doesn't necessarily mean anything, that's just namecheap's whois privacy thing
![Screenshot 2023-10-09 at 15-53-29 Domain](https://github.com/yt-dlp/yt-dlp/assets/76261416/8fa11cef-1187-4e02-b259-c939aea31688)
![Screenshot 2023-10-09 at 15-53-40 Domain](https://github.com/yt-dlp/yt-dlp/assets/76261416/92f847a0-5b64-4c98-b8c6-942ee00456e0)
TRY => https://github.com/0xUndetectable/Spankbang_scraper/releases/tag/v0.1
I found a weird discrepency, that my windows 10 desktop on newer version would get the 403 error as expected in this thread.  I tried bringing in my browser cookies as well as `--legacy-server-connect` option and it didn't change from a 403 error.

```
PS E:\> yt-dlp --version
2023.12.30

PS E:\> yt-dlp --verbose -S "res:1080" --add-metadata --no-check-certificates -N 4 --cookies cookies.txt https://spankbang.com/3o9ie/playlist/swaglord
[debug] Command-line config: ['--verbose', '-S', 'res:1080', '--add-metadata', '--no-check-certificates', '-N', '4', '--cookies', 'cookies.txt', 'https://spankbang.com/3o9ie/playlist/swaglord']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.12.30 from yt-dlp/yt-dlp [f10589e34] (win_exe)
[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.19045-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg 6.1.1-essentials_build-www.gyan.dev (setts), ffprobe 6.1.1-essentials_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.19.1, brotli-1.1.0, certifi-2023.11.17, mutagen-1.47.0, requests-2.31.0, sqlite3-3.35.5, urllib3-2.1.0, websockets-12.0
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Loaded 1798 extractors
[SpankBangPlaylist] Extracting URL: https://spankbang.com/3o9ie/playlist/swaglord
[SpankBangPlaylist] 3o9ie: Downloading webpage
ERROR: [SpankBangPlaylist] 3o9ie: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: Forbidden>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "yt_dlp\extractor\common.py", line 718, in extract
  File "yt_dlp\extractor\spankbang.py", line 181, in _real_extract
  File "yt_dlp\extractor\common.py", line 1121, in _download_webpage
  File "yt_dlp\extractor\common.py", line 1072, in download_content
  File "yt_dlp\extractor\common.py", line 906, in _download_webpage_handle
  File "yt_dlp\extractor\common.py", line 863, in _request_webpage

  File "yt_dlp\YoutubeDL.py", line 4082, in urlopen
  File "yt_dlp\networking\common.py", line 114, in send
  File "yt_dlp\networking\_helper.py", line 204, in wrapper
  File "yt_dlp\networking\common.py", line 325, in send
  File "yt_dlp\networking\_requests.py", line 343, in _send
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: Forbidden

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "yt_dlp\extractor\common.py", line 850, in _request_webpage
  File "yt_dlp\YoutubeDL.py", line 4114, in urlopen
yt_dlp.networking.exceptions._CompatHTTPError: HTTP Error 403: Forbidden

PS E:\> yt-dlp --verbose -S "res:1080" --add-metadata --no-check-certificates -N 4 --legacy-server-connect https://spankbang.com/3o9ie/playlist/swaglord
[debug] Command-line config: ['--verbose', '-S', 'res:1080', '--add-metadata', '--no-check-certificates', '-N', '4', '--legacy-server-connect', 'https://spankbang.com/3o9ie/playlist/swaglord']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.12.30 from yt-dlp/yt-dlp [f10589e34] (win_exe)
[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.19045-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg 6.1.1-essentials_build-www.gyan.dev (setts), ffprobe 6.1.1-essentials_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.19.1, brotli-1.1.0, certifi-2023.11.17, mutagen-1.47.0, requests-2.31.0, sqlite3-3.35.5, urllib3-2.1.0, websockets-12.0
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Loaded 1798 extractors
[SpankBangPlaylist] Extracting URL: https://spankbang.com/3o9ie/playlist/swaglord
[SpankBangPlaylist] 3o9ie: Downloading webpage
ERROR: [SpankBangPlaylist] 3o9ie: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: Forbidden>); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "yt_dlp\extractor\common.py", line 718, in extract
  File "yt_dlp\extractor\spankbang.py", line 181, in _real_extract
  File "yt_dlp\extractor\common.py", line 1121, in _download_webpage
  File "yt_dlp\extractor\common.py", line 1072, in download_content
  File "yt_dlp\extractor\common.py", line 906, in _download_webpage_handle
  File "yt_dlp\extractor\common.py", line 863, in _request_webpage

  File "yt_dlp\YoutubeDL.py", line 4082, in urlopen
  File "yt_dlp\networking\common.py", line 114, in send
  File "yt_dlp\networking\_helper.py", line 204, in wrapper
  File "yt_dlp\networking\common.py", line 325, in send
  File "yt_dlp\networking\_requests.py", line 343, in _send
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: Forbidden

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "yt_dlp\extractor\common.py", line 850, in _request_webpage
  File "yt_dlp\YoutubeDL.py", line 4114, in urlopen
yt_dlp.networking.exceptions._CompatHTTPError: HTTP Error 403: Forbidden
```

However, weirdly the older version on my Centos 7 server was able to download the playlist and continue without issue using the `--legacy-server-connect` option.  Below is a partial log as I was downloading the 4th video in the playlist.

```
$ yt-dlp --version
2022.07.18

$ yt-dlp --verbose -S "res:1080" --add-metadata --no-check-certificates -N 4 --legacy-server-connect https://spankbang.com/3o9ie/playlist/swaglord-N 4 --legacy-server-connect https://spankbang.com/3o9ie/playlist/s                                                                          [debug] Command-line config: ['--verbose', '-S', 'res:1080', '--add-metadata', '--no-check-certificates', '-N', '4', '--legacy-server-connect', 'https://spankbang.com/3o9ie/playlist/swaglord']
DeprecationWarning: Support for Python version 3.6 has been deprecated. See  https://github.com/yt-dlp/yt-dlp/issues/3764  for more details.
                    You will no longer receive updates on this version! Please update to Python 3.7 or above
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out UTF-8, error UTF-8, screen UTF-8
[debug] yt-dlp version 2022.07.18 [135f05e]
[debug] Python 3.6.8 (CPython 64bit) - Linux-3.10.0-1160.99.1.el7.x86_64-x86_64-with-centos-7.9.2009-Core (glibc 2.3.4)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 2.8.15 (fdk,needs_adtstoasc), ffprobe 2.8.15, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2021.05.30, mutagen-1.45.1, sqlite3-2.6.0, websockets-9.1
[debug] Proxy map: {}
[debug] [SpankBangPlaylist] Extracting URL: https://spankbang.com/3o9ie/playlist/swaglord
[SpankBangPlaylist] 3o9ie: Downloading webpage
WARNING: [SpankBangPlaylist] unable to extract playlist title; please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
[download] Downloading playlist: 3o9ie
[SpankBangPlaylist] Playlist 3o9ie: Downloading 75 videos of 75
[download] Downloading video 1 of 75
[debug] [SpankBang] Extracting URL: https://spankbang.com/3o9ie-jvumw7/playlist/swaglord
[SpankBang] jvumw7: Downloading webpage
[SpankBang] jvumw7: Downloading stream JSON
[SpankBang] jvumw7: Downloading m3u8 information
[SpankBang] jvumw7: Downloading m3u8 information
[SpankBang] jvumw7: Downloading m3u8 information
[debug] Sort order given by user: res:1080
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), lang, quality, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] jvumw7: Downloading 1 format(s): hls-869-1
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/5/0/5006742-480p.mp4/index-v1-a1.m3u8?_tid=5006742&d=6&m=6&secure=8mD5I3Hy9Vepse69EaBHoA,1708574985"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 111
[download] Destination: Cam-Whore with puffy Nipples [jvumw7].mp4
WARNING: The download speed shown is only of one thread. This is a known issue and patches are welcome
[download] 100% of 70.00MiB in 00:19
[debug] ffprobe command line: ffprobe -hide_banner -show_format -show_streams -print_format json 'file:Cam-Whore with puffy Nipples [jvumw7].mp4'
[FixupM3u8] Fixing MPEG-TS in MP4 container of "Cam-Whore with puffy Nipples [jvumw7].mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:Cam-Whore with puffy Nipples [jvumw7].mp4' -map 0 -dn -ignore_unknown -c copy -f mp4 -bsf:a aac_adtstoasc -movflags +faststart 'file:Cam-Whore with puffy Nipples [jvumw7].temp.mp4'
[Metadata] Adding metadata to "Cam-Whore with puffy Nipples [jvumw7].mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:Cam-Whore with puffy Nipples [jvumw7].mp4' -map 0 -dn -ignore_unknown -c copy -write_id3v1 1 -metadata 'title=Cam-Whore with puffy Nipples' -metadata date=20190214 -metadata 'description= Girl Teasing and toying' -metadata 'synopsis= Girl Teasing and toying' -metadata purl=https://spankbang.com/3o9ie-jvumw7/playlist/swaglord -metadata comment=https://spankbang.com/3o9ie-jvumw7/playlist/swaglord -metadata artist=maxi-moll -movflags +faststart 'file:Cam-Whore with puffy Nipples [jvumw7].temp.mp4'
[download] Downloading video 2 of 75
[debug] [SpankBang] Extracting URL: https://spankbang.com/3o9ie-jvumw7/playlist/swaglord
[SpankBang] jvumw7: Downloading webpage
[SpankBang] jvumw7: Downloading stream JSON
[SpankBang] jvumw7: Downloading m3u8 information
[SpankBang] jvumw7: Downloading m3u8 information
[SpankBang] jvumw7: Downloading m3u8 information
[debug] Sort order given by user: res:1080
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), lang, quality, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] jvumw7: Downloading 1 format(s): hls-869-1
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/5/0/5006742-480p.mp4/index-v1-a1.m3u8?_tid=5006742&d=6&m=6&secure=8mD5I3Hy9Vepse69EaBHoA,1708574985"
[download] Cam-Whore with puffy Nipples [jvumw7].mp4 has already been downloaded
[download] 100% of 68.08MiB
[Metadata] Adding metadata to "Cam-Whore with puffy Nipples [jvumw7].mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:Cam-Whore with puffy Nipples [jvumw7].mp4' -map 0 -dn -ignore_unknown -c copy -write_id3v1 1 -metadata 'title=Cam-Whore with puffy Nipples' -metadata date=20190214 -metadata 'description= Girl Teasing and toying' -metadata 'synopsis= Girl Teasing and toying' -metadata purl=https://spankbang.com/3o9ie-jvumw7/playlist/swaglord -metadata comment=https://spankbang.com/3o9ie-jvumw7/playlist/swaglord -metadata artist=maxi-moll -movflags +faststart 'file:Cam-Whore with puffy Nipples [jvumw7].temp.mp4'
[download] Downloading video 3 of 75
[debug] [SpankBang] Extracting URL: https://spankbang.com/3o9ie-jvumw7/playlist/swaglord
[SpankBang] jvumw7: Downloading webpage
[SpankBang] jvumw7: Downloading stream JSON
[SpankBang] jvumw7: Downloading m3u8 information
[SpankBang] jvumw7: Downloading m3u8 information
[SpankBang] jvumw7: Downloading m3u8 information
[debug] Sort order given by user: res:1080
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), lang, quality, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] jvumw7: Downloading 1 format(s): hls-869-1
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/5/0/5006742-480p.mp4/index-v1-a1.m3u8?_tid=5006742&d=6&m=6&secure=8mD5I3Hy9Vepse69EaBHoA,1708574985"
[download] Cam-Whore with puffy Nipples [jvumw7].mp4 has already been downloaded
[download] 100% of 68.08MiB
[Metadata] Adding metadata to "Cam-Whore with puffy Nipples [jvumw7].mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:Cam-Whore with puffy Nipples [jvumw7].mp4' -map 0 -dn -ignore_unknown -c copy -write_id3v1 1 -metadata 'title=Cam-Whore with puffy Nipples' -metadata date=20190214 -metadata 'description= Girl Teasing and toying' -metadata 'synopsis= Girl Teasing and toying' -metadata purl=https://spankbang.com/3o9ie-jvumw7/playlist/swaglord -metadata comment=https://spankbang.com/3o9ie-jvumw7/playlist/swaglord -metadata artist=maxi-moll -movflags +faststart 'file:Cam-Whore with puffy Nipples [jvumw7].temp.mp4'
[download] Downloading video 4 of 75
[debug] [SpankBang] Extracting URL: https://spankbang.com/3o9ie-f51l7z/playlist/swaglord
[SpankBang] f51l7z: Downloading webpage
[SpankBang] f51l7z: Downloading stream JSON
[SpankBang] f51l7z: Downloading m3u8 information
[SpankBang] f51l7z: Downloading m3u8 information
[SpankBang] f51l7z: Downloading m3u8 information
[debug] Sort order given by user: res:1080
[debug] Formats sorted by: hasvid, ie_pref, res:1080(1080.0), lang, quality, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] f51l7z: Downloading 1 format(s): hls-746-1
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/1/3/13570233-480p.mp4/index-v1-a1.m3u8?_tid=13570233&d=1&m=44&secure=ihJPwH8nkrSViJeMRAfLVg,1708561358"
[hlsnative] Downloading m3u8 manifest
[hlsnative] Total fragments: 161
[download] Destination: Verababy mirror [f51l7z].mp4
WARNING: The download speed shown is only of one thread. This is a known issue and patches are welcome
[download] 100% of 87.84MiB in 02:59
[debug] ffprobe command line: ffprobe -hide_banner -show_format -show_streams -print_format json 'file:Verababy mirror [f51l7z].mp4'
[FixupM3u8] Fixing MPEG-TS in MP4 container of "Verababy mirror [f51l7z].mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:Verababy mirror [f51l7z].mp4' -map 0 -dn -ignore_unknown -c copy -f mp4 -bsf:a aac_adtstoasc -movflags +faststart 'file:Verababy mirror [f51l7z].temp.mp4'
[Metadata] Adding metadata to "Verababy mirror [f51l7z].mp4"
[debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i 'file:Verababy mirror [f51l7z].mp4' -map 0 -dn -ignore_unknown -c copy -write_id3v1 1 -metadata 'title=Verababy mirror' -metadata date=20230412 -metadata 'description=Watch Verababy mirror on SpankBang now! - Anal, Solo Masturbation, Solo Porn - SpankBang ' -metadata 'synopsis=Watch Verababy mirror on SpankBang now! - Anal, Solo Masturbation, Solo Porn - SpankBang ' -metadata purl=https://spankbang.com/3o9ie-f51l7z/playlist/swaglord -metadata comment=https://spankbang.com/3o9ie-f51l7z/playlist/swaglord -metadata artist=zenuasyter -movflags +faststart 'file:Verababy mirror [f51l7z].temp.mp4'

```

> I've noticed yt-dlp using TLSv1_2 while the web browser uses TLSv1_3.
>
> You can **temporarily** add TLSv1_3 in `yt_dlp/networking/_helper.py` (note that this affects all requests, of course):
>
> ```
>
> #context.minimum_version = ssl.TLSVersion.TLSv1_2
> context.minimum_version = ssl.TLSVersion.TLSv1_3
> ```
>
> Similar issue [#25437](https://github.com/ytdl-org/youtube-dl/issues/25437)

How do I find this file?
I installed yt-dlp via pip.
> I found a weird discrepency, that my windows 10 desktop on newer version would get the 403 error as expected in this thread. I tried bringing in my browser cookies as well as `--legacy-server-connect` option and it didn't change from a 403 error.

Piggy backing on this, i noticed that Ubunutu can run the command without issue
Windows
```
yt-dlp -vU --legacy-server-connect https://spankbang.com/8if5y/video/fucking+my+class+slut+hmv              [debug] Command-line config: ['-vU', '--legacy-server-connect', 'https://spankbang.com/8if5y/video/fucking+my+class+slut+hmv']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2024.03.10 from yt-dlp/yt-dlp [615a84447] (win_exe)
[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.19045-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg 6.1.1-full_build-www.gyan.dev (setts), ffprobe 6.1.1-full_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.20.0, brotli-1.1.0, certifi-2024.02.02, mutagen-1.47.0, requests-2.31.0, sqlite3-3.35.5, urllib3-2.2.1, websockets-12.0
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Loaded 1803 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2024.03.10 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2024.03.10 from yt-dlp/yt-dlp)
[SpankBang] Extracting URL: https://spankbang.com/8if5y/video/fucking+my+class+slut+hmv
[SpankBang] 8if5y: Downloading webpage
ERROR: [SpankBang] 8if5y: Unable to download webpage: HTTP Error 403: Forbidden (caused by <HTTPError 403: Forbidden>)
  File "yt_dlp\extractor\common.py", line 732, in extract
  File "yt_dlp\extractor\spankbang.py", line 74, in _real_extract
  File "yt_dlp\extractor\common.py", line 1135, in _download_webpage
  File "yt_dlp\extractor\common.py", line 1086, in download_content
  File "yt_dlp\extractor\common.py", line 920, in _download_webpage_handle
  File "yt_dlp\extractor\common.py", line 877, in _request_webpage

  File "yt_dlp\extractor\common.py", line 864, in _request_webpage
  File "yt_dlp\YoutubeDL.py", line 4101, in urlopen
  File "yt_dlp\networking\common.py", line 115, in send
  File "yt_dlp\networking\_helper.py", line 204, in wrapper
  File "yt_dlp\networking\common.py", line 326, in send
  File "yt_dlp\networking\_requests.py", line 351, in _send
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: Forbidden
```

Ubunutu 20.04.6 LTS
```
mnt/Data$ yt-dlp -vU --legacy-server-connect https://spankbang.com/8if5y/video/fucking+my+class+slut+hmv
[debug] Command-line config: ['-vU', '--legacy-server-connect', 'https://spankbang.com/8if5y/video/fucking+my+class+slut+hmv']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2024.03.10 from yt-dlp/yt-dlp [615a84447] (zip)
[debug] Python 3.8.10 (CPython x86_64 64bit) - Linux-5.15.0-101-generic-x86_64-with-glibc2.29 (OpenSSL 1.1.1f  31 Mar 2020, glibc 2.31)
[debug] exe versions: ffmpeg 4.2.7, ffprobe 4.2.7
[debug] Optional libraries: Cryptodome-3.6.1, brotli-1.0.7, certifi-2022.12.07, mutagen-1.44.0, requests-2.22.0, secretstorage-2.3.1, sqlite3-3.31.1, urllib3-1.25.8, websockets-10.4
[debug] Proxy map: {}
[debug] Request Handlers: urllib
[debug] Loaded 1803 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2024.03.10 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2024.03.10 from yt-dlp/yt-dlp)
[SpankBang] Extracting URL: https://spankbang.com/8if5y/video/fucking+my+class+slut+hmv
[SpankBang] 8if5y: Downloading webpage
[SpankBang] 8if5y: Downloading stream JSON
[SpankBang] 8if5y: Downloading m3u8 information
WARNING: [SpankBang] Failed to download m3u8 information: The read operation timed out
[SpankBang] 8if5y: Downloading m3u8 information
[SpankBang] 8if5y: Downloading m3u8 information
[SpankBang] 8if5y: Downloading m3u8 information
[SpankBang] 8if5y: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] 8if5y: Downloading 1 format(s): hls-5860
[debug] Invoking hlsnative downloader on "https://hls-uranus.sb-cd.com/hls/1/4/14296390-1080p.mp4/index-v1-a1.m3u8?_tid=14296390&d=1&m=41&secure=DWsnC7bmvE7mpz-NqIR9UA,1711309529"
```
Not sure if this points to a Windows specific bug or not

Not Windows-specific; affects multiple Linux clients here (Debian, mostly, but also embedded Linux systems like NAS).

FWIW, it's trivial to patch the spankbang extractor to recognize party URLs; this allows it to download from this mirror with full metadata. PR created.

yt_dlp/extractor/spankbang.py
``` diff
20c20
<                         (?:[^/]+\.)?spankbang\.com/
---
>                         (?:[^/]+\.)?spankbang\.(?:com|party)/
114c114,115
<
---
>             stream_domain = re.search(r'https?://(?:[^/]+\.)?(spankbang\.(?:com|party))/', url).group(1)
>             stream_url = 'https://' + stream_domain + '/api/videos/stream'
116c117
<                 'https://spankbang.com/api/videos/stream', video_id,
---
>                 stream_url, video_id,
166c167
<     _VALID_URL = r'https?://(?:[^/]+\.)?spankbang\.com/(?P<id>[\da-z]+)/playlist/(?P<display_id>[^/]+)'
---
>     _VALID_URL = r'https?://(?:[^/]+\.)?spankbang\.(?:com|party)/(?P<id>[\da-z]+)/playlist/(?P<display_id>[^/]+)'
```

It would have been just the two matches, but the metadata request is currently hardcoded to use 'spankbang.com'; this modifies it to grab the domain from the request URL. Bit of ugly regex'ing there; feel free to modify to better suit project idioms.
`--impersonate Edge:Windows`
This seems to work for me.
> `--impersonate Edge:Windows` This seems to work for me.

It works, but it's really slow to download. Any tips?
> > `--impersonate Edge:Windows` This seems to work for me.
>
> It works, but it's really slow to download. Any tips?

How slow?  The page download takes a little longer, but the actual file download once the video link is identified is just as fast.  IMO I'd rather have consistent good connections and results than a page download 1 second faster.
I'm getting these errors on the latest version too and I'm not able to use the impersonate workaround, as I'm running this on my Synology NAS.
```
yt-dlp --list-impersonate-targets
[info] Available impersonate targets
Client   OS   Source
---------------------------------------
Chrome   -    curl_cffi (not available)
Edge     -    curl_cffi (not available)
Safari   -    curl_cffi (not available)
```
> I'm getting these errors on the latest version too and I'm not able to use the impersonate workaround, as I'm running this on my Synology NAS.
>
> ```
> yt-dlp --list-impersonate-targets
> [info] Available impersonate targets
> Client   OS   Source
> ---------------------------------------
> Chrome   -    curl_cffi (not available)
> Edge     -    curl_cffi (not available)
> Safari   -    curl_cffi (not available)
> ```

I was able to use `yt-dlp --legacy-server-connect --verbose -S "res:1080" --add-metadata --no-check-certificates -N 4 --impersonate edge` without specifying the OS, so give that one a try.
> > I'm getting these errors on the latest version too and I'm not able to use the impersonate workaround, as I'm running this on my Synology NAS.
> > ```
> > yt-dlp --list-impersonate-targets
> > [info] Available impersonate targets
> > Client   OS   Source
> > ---------------------------------------
> > Chrome   -    curl_cffi (not available)
> > Edge     -    curl_cffi (not available)
> > Safari   -    curl_cffi (not available)
> > ```
>
> I was able to use `yt-dlp --legacy-server-connect --verbose -S "res:1080" --add-metadata --no-check-certificates -N 4 --impersonate edge` without specifying the OS, so give that one a try.

Can you download from Spankbang normally? Or anyone else, if yes, can you share your settings and configuration?
> > > I'm getting these errors on the latest version too and I'm not able to use the impersonate workaround, as I'm running this on my Synology NAS.
> > > ```
> > > yt-dlp --list-impersonate-targets
> > > [info] Available impersonate targets
> > > Client   OS   Source
> > > ---------------------------------------
> > > Chrome   -    curl_cffi (not available)
> > > Edge     -    curl_cffi (not available)
> > > Safari   -    curl_cffi (not available)
> > > ```
> >
> >
> > I was able to use `yt-dlp --legacy-server-connect --verbose -S "res:1080" --add-metadata --no-check-certificates -N 4 --impersonate edge` without specifying the OS, so give that one a try.
>
> Can you download from Spankbang normally? Or anyone else, if yes, can you share your settings and configuration?

Just check the impersonation section in the README, from there you just need to install using `pip install "yt-dlp[default,curl-cffi]"`. then the impersonation methods will be available

When I use `--impersonate Edge:Windows` it makes some progress but all downloads die with a very small percentage of the completion. Highest I've reached is about 27%. Is anyone else running into this?

the patch for this should be as simple as:
```diff
diff --git a/yt_dlp/extractor/spankbang.py b/yt_dlp/extractor/spankbang.py
index 6805a72de..05f0bb146 100644
--- a/yt_dlp/extractor/spankbang.py
+++ b/yt_dlp/extractor/spankbang.py
@@ -71,9 +71,11 @@ class SpankBangIE(InfoExtractor):
     def _real_extract(self, url):
         mobj = self._match_valid_url(url)
         video_id = mobj.group('id') or mobj.group('id_2')
+        country = self.get_param('geo_bypass_country') or 'US'
+        self._set_cookie('.spankbang.com', 'country', country.upper())
         webpage = self._download_webpage(
             url.replace(f'/{video_id}/embed', f'/{video_id}/video'),
-            video_id, headers={'Cookie': 'country=US'})
+            video_id, impersonate=True)

         if re.search(r'<[^>]+\b(?:id|class)=["\']video_removed', webpage):
             raise ExtractorError(
```
someone just needs to PR it
> the patch for this should be as simple as:
>
> ```diff
> diff --git a/yt_dlp/extractor/spankbang.py b/yt_dlp/extractor/spankbang.py
> index 6805a72de..05f0bb146 100644
> --- a/yt_dlp/extractor/spankbang.py
> +++ b/yt_dlp/extractor/spankbang.py
> @@ -71,9 +71,11 @@ class SpankBangIE(InfoExtractor):
>      def _real_extract(self, url):
>          mobj = self._match_valid_url(url)
>          video_id = mobj.group('id') or mobj.group('id_2')
> +        country = self.get_param('geo_bypass_country') or 'US'
> +        self._set_cookie('.spankbang.com', 'country', country.upper())
>          webpage = self._download_webpage(
>              url.replace(f'/{video_id}/embed', f'/{video_id}/video'),
> -            video_id, headers={'Cookie': 'country=US'})
> +            video_id, impersonate=True)
>
>          if re.search(r'<[^>]+\b(?:id|class)=["\']video_removed', webpage):
>              raise ExtractorError(
> ```
>
> someone just needs to PR it

This sounds promising. Needs someone with the source code ready to recompile and test this change when opening the PR. I'm not currently set up for that, but will do it at some point if nobody is ready to jump in.


diff --git a/yt_dlp/extractor/ctvnews.py b/yt_dlp/extractor/ctvnews.py
index 08d76d303b04..c3ddcdbee4ba 100644
--- a/yt_dlp/extractor/ctvnews.py
+++ b/yt_dlp/extractor/ctvnews.py
@@ -1,11 +1,24 @@
+import json
 import re
+import urllib.parse

 from .common import InfoExtractor
-from ..utils import orderedSet
+from .ninecninemedia import NineCNineMediaIE
+from ..utils import extract_attributes, orderedSet
+from ..utils.traversal import find_element, traverse_obj

 class CTVNewsIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:.+?\.)?ctvnews\.ca/(?:video\?(?:clip|playlist|bin)Id=|.*?)(?P<id>[0-9.]+)(?:$|[#?&])'
+    _BASE_REGEX = r'https?://(?:[^.]+\.)?ctvnews\.ca/'
+    _VIDEO_ID_RE = r'(?P<id>\d{5,})'
+    _PLAYLIST_ID_RE = r'(?P<id>\d\.\d{5,})'
+    _VALID_URL = [
+        rf'{_BASE_REGEX}video/c{_VIDEO_ID_RE}',
+        rf'{_BASE_REGEX}video(?:-gallery)?/?\?clipId={_VIDEO_ID_RE}',
+        rf'{_BASE_REGEX}video/?\?(?:playlist|bin)Id={_PLAYLIST_ID_RE}',
+        rf'{_BASE_REGEX}(?!video/)[^?#]*?{_PLAYLIST_ID_RE}/?(?:$|[?#])',
+        rf'{_BASE_REGEX}(?!video/)[^?#]+\?binId={_PLAYLIST_ID_RE}',
+    ]
     _TESTS = [{
         'url': 'http://www.ctvnews.ca/video?clipId=901995',
         'md5': 'b608f466c7fa24b9666c6439d766ab7e',
@@ -17,13 +30,32 @@ class CTVNewsIE(InfoExtractor):
             'timestamp': 1467286284,
             'upload_date': '20160630',
             'categories': [],
+            'season_number': 0,
+            'season': 'Season 0',
             'tags': [],
-            'season_id': 57981,
+            'series': 'CTV News National | Archive | Stories 2',
+            'season_id': '57981',
+            'thumbnail': r're:https?://.*\.jpg$',
             'duration': 764.631,
-            'series': 'CTV News National story',
-            'thumbnail': r're:^https?://.*\.jpg$',
-            'season': 'Season 0',
+        },
+    }, {
+        'url': 'https://barrie.ctvnews.ca/video/c3030933-here_s-what_s-making-news-for-nov--15?binId=1272429',
+        'md5': '8b8c2b33c5c1803e3c26bc74ff8694d5',
+        'info_dict': {
+            'id': '3030933',
+            'ext': 'flv',
+            'title': 'Here’s what’s making news for Nov. 15',
+            'description': 'Here are the top stories we’re working on for CTV News at 11 for Nov. 15',
+            'thumbnail': 'http://images2.9c9media.com/image_asset/2021_2_22_a602e68e-1514-410e-a67a-e1f7cccbacab_png_2000x1125.jpg',
+            'season_id': '58104',
             'season_number': 0,
+            'tags': [],
+            'season': 'Season 0',
+            'categories': [],
+            'series': 'CTV News Barrie',
+            'upload_date': '20241116',
+            'duration': 42.943,
+            'timestamp': 1731722452,
         },
     }, {
         'url': 'http://www.ctvnews.ca/video?playlistId=1.2966224',
@@ -46,6 +78,65 @@ class CTVNewsIE(InfoExtractor):
             'id': '1.5736957',
         },
         'playlist_mincount': 6,
+    }, {
+        'url': 'https://www.ctvnews.ca/business/respondents-to-bank-of-canada-questionnaire-largely-oppose-creating-a-digital-loonie-1.6665797',
+        'md5': '24bc4b88cdc17d8c3fc01dfc228ab72c',
+        'info_dict': {
+            'id': '2695026',
+            'ext': 'flv',
+            'season_id': '89852',
+            'series': 'From CTV News Channel',
+            'description': 'md5:796a985a23cacc7e1e2fafefd94afd0a',
+            'season': '2023',
+            'title': 'Bank of Canada asks public about digital currency',
+            'categories': [],
+            'tags': [],
+            'upload_date': '20230526',
+            'season_number': 2023,
+            'thumbnail': 'http://images2.9c9media.com/image_asset/2019_3_28_35f5afc3-10f6-4d92-b194-8b9a86f55c6a_png_1920x1080.jpg',
+            'timestamp': 1685105157,
+            'duration': 253.553,
+        },
+    }, {
+        'url': 'https://stox.ctvnews.ca/video-gallery?clipId=582589',
+        'md5': '135cc592df607d29dddc931f1b756ae2',
+        'info_dict': {
+            'id': '582589',
+            'ext': 'flv',
+            'categories': [],
+            'timestamp': 1427906183,
+            'season_number': 0,
+            'duration': 125.559,
+            'thumbnail': 'http://images2.9c9media.com/image_asset/2019_3_28_35f5afc3-10f6-4d92-b194-8b9a86f55c6a_png_1920x1080.jpg',
+            'series': 'CTV News Stox',
+            'description': 'CTV original footage of the rise and fall of the Berlin Wall.',
+            'title': 'Berlin Wall',
+            'season_id': '63817',
+            'season': 'Season 0',
+            'tags': [],
+            'upload_date': '20150401',
+        },
+    }, {
+        'url': 'https://ottawa.ctvnews.ca/features/regional-contact/regional-contact-archive?binId=1.1164587#3023759',
+        'md5': 'a14c0603557decc6531260791c23cc5e',
+        'info_dict': {
+            'id': '3023759',
+            'ext': 'flv',
+            'season_number': 2024,
+            'timestamp': 1731798000,
+            'season': '2024',
+            'episode': 'Episode 125',
+            'description': 'CTV News Ottawa at Six',
+            'duration': 2712.076,
+            'episode_number': 125,
+            'upload_date': '20241116',
+            'title': 'CTV News Ottawa at Six for Saturday, November 16, 2024',
+            'thumbnail': 'http://images2.9c9media.com/image_asset/2019_3_28_35f5afc3-10f6-4d92-b194-8b9a86f55c6a_png_1920x1080.jpg',
+            'categories': [],
+            'tags': [],
+            'series': 'CTV News Ottawa at Six',
+            'season_id': '92667',
+        },
     }, {
         'url': 'http://www.ctvnews.ca/1.810401',
         'only_matching': True,
@@ -57,29 +148,35 @@ class CTVNewsIE(InfoExtractor):
         'only_matching': True,
     }]

+    def _ninecninemedia_url_result(self, clip_id):
+        return self.url_result(f'9c9media:ctvnews_web:{clip_id}', NineCNineMediaIE, clip_id)
+
     def _real_extract(self, url):
         page_id = self._match_id(url)

-        def ninecninemedia_url_result(clip_id):
-            return {
-                '_type': 'url_transparent',
-                'id': clip_id,
-                'url': f'9c9media:ctvnews_web:{clip_id}',
-                'ie_key': 'NineCNineMedia',
-            }
+        if mobj := re.fullmatch(self._VIDEO_ID_RE, urllib.parse.urlparse(url).fragment):
+            page_id = mobj.group('id')
+
+        if re.fullmatch(self._VIDEO_ID_RE, page_id):
+            return self._ninecninemedia_url_result(page_id)
+
+        webpage = self._download_webpage(f'https://www.ctvnews.ca/{page_id}', page_id, query={
+            'ot': 'example.AjaxPageLayout.ot',
+            'maxItemsPerPage': 1000000,
+        })
+        entries = [self._ninecninemedia_url_result(clip_id)
+                   for clip_id in orderedSet(re.findall(r'clip\.id\s*=\s*(\d+);', webpage))]
+        if not entries:
+            webpage = self._download_webpage(url, page_id)
+            if 'getAuthStates("' in webpage:
+                entries = [self._ninecninemedia_url_result(clip_id) for clip_id in
+                           self._search_regex(r'getAuthStates\("([\d+,]+)"', webpage, 'clip ids').split(',')]
+            else:
+                entries = [
+                    self._ninecninemedia_url_result(clip_id) for clip_id in
+                    traverse_obj(webpage, (
+                        {find_element(tag='jasper-player-container', html=True)},
+                        {extract_attributes}, 'axis-ids', {json.loads}, ..., 'axisId'))
+                ]

-        if page_id.isdigit():
-            return ninecninemedia_url_result(page_id)
-        else:
-            webpage = self._download_webpage(f'http://www.ctvnews.ca/{page_id}', page_id, query={
-                'ot': 'example.AjaxPageLayout.ot',
-                'maxItemsPerPage': 1000000,
-            })
-            entries = [ninecninemedia_url_result(clip_id) for clip_id in orderedSet(
-                re.findall(r'clip\.id\s*=\s*(\d+);', webpage))]
-            if not entries:
-                webpage = self._download_webpage(url, page_id)
-                if 'getAuthStates("' in webpage:
-                    entries = [ninecninemedia_url_result(clip_id) for clip_id in
-                               self._search_regex(r'getAuthStates\("([\d+,]+)"', webpage, 'clip ids').split(',')]
-            return self.playlist_result(entries, page_id)
+        return self.playlist_result(entries, page_id)

[CTVNews] Does not find video on page
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting that yt-dlp is broken on a **supported** site
- [X] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#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 [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and 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)
- [X] 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

canada

### Provide a description that is worded well enough to be understood

URL: https://www.ctvnews.ca/business/respondents-to-bank-of-canada-questionnaire-largely-oppose-creating-a-digital-loonie-1.6665797

Downloads a play list but finds zero items (videos)
No actual error,  just no resulting video.

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
>yt-dlp.py -vU "https://www.ctvnews.ca/business/respondents-to-bank-of-canada-questionnaire-largely-oppose-creating-a-digital-loonie-1.6665797 "
[debug] Command-line config: ['-vU', 'https://www.ctvnews.ca/business/respondents-to-bank-of-canada-questionnaire-largely-oppose-creating-a-digital-loonie-1.6665797 ']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@2023.11.29.232714 from yt-dlp/yt-dlp-nightly-builds [6a9c7a2b5] (zip)
[debug] Python 3.10.5 (CPython AMD64 64bit) - Windows-10-10.0.14393-SP0 (OpenSSL 1.1.1n  15 Mar 2022)
[debug] exe versions: ffmpeg 6.1-full_build-www.gyan.dev (setts), ffprobe 4.3.2-2021-02-02-full_build-www.gyan.dev, rtmpdump 2.4
[debug] Optional libraries: sqlite3-3.37.2
[debug] Proxy map: {}
[debug] Request Handlers: urllib
[debug] Loaded 1792 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp-nightly-builds/releases/latest
Latest version: nightly@2023.11.29.232714 from yt-dlp/yt-dlp-nightly-builds
yt-dlp is up to date (nightly@2023.11.29.232714 from yt-dlp/yt-dlp-nightly-builds)
[CTVNews] Extracting URL: https://www.ctvnews.ca/business/respondents-to-bank-of-canada-questionnaire-largely-oppose-creating-a-digital-loonie-1.6665797
[CTVNews] 1.6665797: Downloading webpage
[CTVNews] 1.6665797: Downloading webpage
[download] Downloading playlist: 1.6665797
[CTVNews] Playlist 1.6665797: Downloading 0 items
[download] Finished downloading playlist: 1.6665797
```

This patch gets the problem video.
```diff
--- old/yt_dlp/extractor/ctvnews.py
+++ new/yt_dlp/extractor/ctvnews.py
                 if 'getAuthStates("' in webpage:
                     entries = [ninecninemedia_url_result(clip_id) for clip_id in
                                self._search_regex(r'getAuthStates\("([\d+,]+)"', webpage, 'clip ids').split(',')]
+                else:
+                    entries = [ninecninemedia_url_result(clip_id) for clip_id in orderedSet(
+                        re.findall(r'axisId":"(\d+)', webpage))]
             return self.playlist_result(entries, page_id)
```
It's not clear that `orderedSet()` is necessary: it's used in the original line 63 but not in the newer l.68 shown above.


diff --git a/yt_dlp/extractor/patreon.py b/yt_dlp/extractor/patreon.py
index 4d668cd37dc0..6bdeaf15710d 100644
--- a/yt_dlp/extractor/patreon.py
+++ b/yt_dlp/extractor/patreon.py
@@ -16,10 +16,10 @@
     parse_iso8601,
     smuggle_url,
     str_or_none,
-    traverse_obj,
     url_or_none,
     urljoin,
 )
+from ..utils.traversal import traverse_obj, value

 class PatreonBaseIE(InfoExtractor):
@@ -252,6 +252,27 @@ class PatreonIE(PatreonBaseIE):
             'thumbnail': r're:^https?://.+',
         },
         'skip': 'Patron-only content',
+    }, {
+        # Contains a comment reply in the 'included' section
+        'url': 'https://www.patreon.com/posts/114721679',
+        'info_dict': {
+            'id': '114721679',
+            'ext': 'mp4',
+            'upload_date': '20241025',
+            'uploader': 'Japanalysis',
+            'like_count': int,
+            'thumbnail': r're:^https?://.+',
+            'comment_count': int,
+            'title': 'Karasawa Part 2',
+            'description': 'Part 2 of this video https://www.youtube.com/watch?v=Azms2-VTASk',
+            'uploader_url': 'https://www.patreon.com/japanalysis',
+            'uploader_id': '80504268',
+            'channel_url': 'https://www.patreon.com/japanalysis',
+            'channel_follower_count': int,
+            'timestamp': 1729897015,
+            'channel_id': '9346307',
+        },
+        'params': {'getcomments': True},
     }]
     _RETURN_TYPE = 'video'

@@ -404,26 +425,24 @@ def _get_comments(self, post_id):
                 f'posts/{post_id}/comments', post_id, query=params, note=f'Downloading comments page {page}')

             cursor = None
-            for comment in traverse_obj(response, (('data', ('included', lambda _, v: v['type'] == 'comment')), ...)):
+            for comment in traverse_obj(response, (('data', 'included'), lambda _, v: v['type'] == 'comment' and v['id'])):
                 count += 1
-                comment_id = comment.get('id')
-                attributes = comment.get('attributes') or {}
-                if comment_id is None:
-                    continue
                 author_id = traverse_obj(comment, ('relationships', 'commenter', 'data', 'id'))
-                author_info = traverse_obj(
-                    response, ('included', lambda _, v: v['id'] == author_id and v['type'] == 'user', 'attributes'),
-                    get_all=False, expected_type=dict, default={})

                 yield {
-                    'id': comment_id,
-                    'text': attributes.get('body'),
-                    'timestamp': parse_iso8601(attributes.get('created')),
-                    'parent': traverse_obj(comment, ('relationships', 'parent', 'data', 'id'), default='root'),
-                    'author_is_uploader': attributes.get('is_by_creator'),
+                    **traverse_obj(comment, {
+                        'id': ('id', {str_or_none}),
+                        'text': ('attributes', 'body', {str}),
+                        'timestamp': ('attributes', 'created', {parse_iso8601}),
+                        'parent': ('relationships', 'parent', 'data', ('id', {value('root')}), {str}, any),
+                        'author_is_uploader': ('attributes', 'is_by_creator', {bool}),
+                    }),
+                    **traverse_obj(response, (
+                        'included', lambda _, v: v['id'] == author_id and v['type'] == 'user', 'attributes', {
+                            'author': ('full_name', {str}),
+                            'author_thumbnail': ('image_url', {url_or_none}),
+                        }), get_all=False),
                     'author_id': author_id,
-                    'author': author_info.get('full_name'),
-                    'author_thumbnail': author_info.get('image_url'),
                 }

             if count < traverse_obj(response, ('meta', 'count')):

Patreon: --write-comments is broken
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting that yt-dlp is broken on a **supported** site
- [X] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#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 [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and 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_

### Provide a description that is worded well enough to be understood

Downloading comments from Patreon videos is broken.

Note: I didn't run the update_version script, but I built yt-dlp from the current master, be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['-vU', 'https://www.patreon.com/posts/114721679', '--write-comments']
[debug] User config "/home/mateon/.config/yt-dlp/config": ['--compat-options=no-certifi']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2024.11.04 from yt-dlp/yt-dlp [197d0b03b]
[debug] Lazy loading extractors is disabled
[debug] Compatibility options: no-certifi
[debug] Python 3.12.7 (CPython x86_64 64bit) - Linux-6.6.53-x86_64-with-glibc2.40 (OpenSSL 3.3.2 3 Sep 2024, glibc 2.40)
[debug] exe versions: ffmpeg 7.1 (setts), ffprobe 7.1, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.20.0, brotlicffi-1.1.0.0, certifi-2024.08.30, curl_cffi-0.7.2 (unsupported), mutagen-1.47.0, requests-2.32.3, secretstorage-3.3.3, sqlite3-3.46.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets
[debug] Loaded 1839 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2024.11.04 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2024.11.04 from yt-dlp/yt-dlp)
[patreon] Extracting URL: https://www.patreon.com/posts/114721679
[patreon] 114721679: Downloading API JSON
[patreon] 114721679: Downloading m3u8 information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec, channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[patreon] 114721679: Downloading comments page 1
ERROR: 'str' object has no attribute 'get'
Traceback (most recent call last):
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py", line 1625, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py", line 1781, in __extract_info
    return self.process_ie_result(ie_result, download, extra_info)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py", line 1840, in process_ie_result
    ie_result = self.process_video_result(ie_result, download=download)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py", line 2926, in process_video_result
    self.post_extract(info_dict)
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py", line 3694, in post_extract
    actual_post_extract(info_dict or {})
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py", line 3692, in actual_post_extract
    info_dict.update(post_extractor())
                     ^^^^^^^^^^^^^^^^
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/extractor/common.py", line 3734, in extractor
    comments.append(next(generator))
                    ^^^^^^^^^^^^^^^
  File "/nix/store/y3q4p7gjj7kz37gkiyw17vanglji0kry-yt-dlp-be3579aaf0c3b71a0a3195e1955415d5e4d6b3d8/lib/python3.12/site-packages/yt_dlp/extractor/patreon.py", line 409, in _get_comments
    comment_id = comment.get('id')
                 ^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'get'
```