Skip to content

[TVer] "This video is available in Japan" with Japanese IP / HTTP Error 403: Forbidden #13874

@fireattack

Description

@fireattack

Checklist

  • I'm reporting that yt-dlp is broken on a supported site
  • I've verified that I have updated yt-dlp to nightly or master (update instructions)
  • I've checked that all provided URLs are playable in a browser with the same IP and same login details
  • I've checked that all URLs and arguments with special characters are properly quoted or escaped
  • I've searched known issues, the FAQ, and the bugtracker for similar issues including closed ones. DO NOT post duplicates
  • I've read about sharing account credentials and I'm willing to share it if required

Region

Japan

Provide a description that is worded well enough to be understood

This is essentially the same issue as #13808, but with more detailed observations. I use various Japanese VPNs/proxies and can always watch the episode without issue in a browser.

However, yt-dlp fails most of the time, though not always.

After some manual testing with the API endpoint, I noticed that requests to playback.api.streaks.jp sometimes fail, but not consistently. Below is an example of two consecutive requests made within 5 seconds. The first one succeeds, but the second fails. From what I’ve observed, once the request starts failing, it will consistently fail until I change my IP. That said, this is just anecdotal and not based on systematic testing.

D:\>curl https://playback.api.streaks.jp/v1/projects/tver-ntv/medias/ref:e571ff635e0245059aad742f4f5805bc -H origin:https://tver.jp -H Accept:application/json -H referer:https://tver.jp/
{"project_id":"tver-ntv","id":"e7ebd9911338480db8bc31dc55b9561a","ref_id":"e571ff635e0245059aad742f4f5805bc","type":"file","name":"開演まで30秒!THEパニックGP 7月28日(月)放送分 FUJIWARA結成35周年SP!人気芸人集結で爆笑コント!","description":"FUJIWARA結成35周年記念SP!千鳥との(秘)親交を明かす爆笑コント連発!FRUITS ZIPPER仲川瑠夏が原西と人生初コント挑戦で大絶賛…FUJIWARA渾身の集大成コントも必見!","duration":1190.056,"profile":"0b69bd13d7a949f2a7420e982444f138","poster":{"src":"https://images.streaks.jp/tver-ntv/medias/e7ebd9911338480db8bc31dc55b9561a/posters/53bcc8f9-2307-45a0-aa8d-7a95d88eb696.jpg"},"thumbnail":{"src":"https://images.streaks.jp/tver-ntv/medias/e7ebd9911338480db8bc31dc55b9561a/thumbnails/f4006e7a-9b3a-459b-b424-34f8ea11fece.jpg"},"sources":[{"id":"afd10a4096914baca8f8109c75023058","label":"hls_aes128","type":"application/x-mpegURL","resolution":"1920x1080","ext_x_version":3,"src":"https://manifest.streaks.jp/v6/tver-ntv/e7ebd9911338480db8bc31dc55b9561a/afd10a4096914baca8f8109c75023058/hls/v3/manifest.m3u8?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYyI6IjgxOWNmZGMwMjBhYzQ4MGI5YjA2MDBiNWFmYjMzMWEzIiwiZWRnZSI6IjkzOTdhNjg0NTg3NTQ4OWM4NjdmZGI2MzVkNTBlNzkyIiwiY29kZWNzIjoiYXV0byIsImV4cCI6MTc1Mzk4MTIwMCwic20iOiI3NGQ0MmQ3MzJmNzg0ODU2OGFkODY5NTE3ZDBjNmQ5OSIsInBwdyI6IjQ3NSJ9.gkVMOfNgiHOrBJoLgmKEtyNV732VEykGb0Fep3-HeEU","cdn":"jocdn"}],"tracks":[{"id":"0a2352f2d75e4fd4a7a6e7070cedfdb3","kind":"thumbnails","label":"thumbnail_tile0","m3u8_embeded":false,"src":"https://tracks.streaks.jp/tver-ntv/e7ebd9911338480db8bc31dc55b9561a/track/0a2352f2d75e4fd4a7a6e7070cedfdb3/thumbnails.vtt?ts=1753677593","type":"text/vtt"}],"cue_points":[{"name":"自動検出","start_time":924.491,"end_time":null,"type":"ad"},{"name":"自動検出","start_time":749.516,"end_time":null,"type":"ad"}],"chapters":[],"ads":[],"ad_fields":{"guid":"e571ff635e0245059aad742f4f5805bc","content_id":"e571ff635e0245059aad742f4f5805bc","programkey":"panicGP"},"tags":[],"offline_enabled":true,"resolution":"1920x1080","created_at":"2025-07-28T13:36:33.635+0900","updated_at":"2025-07-28T13:57:55.838+0900","copyright":"","metrics":{"host":"tver-metrics.streaks.jp/v2","sessionExpire":0,"session_expire":0,"pingTime":20,"ping_time":20,"sessionMaxAge":86400,"session_max_age":86400}}
D:\>curl https://playback.api.streaks.jp/v1/projects/tver-ntv/medias/ref:e571ff635e0245059aad742f4f5805bc -H origin:https://tver.jp -H Accept:application/json -H referer:https://tver.jp/
{"id":126,"code":"REQUEST_FAILED","status":403,"message":"この動画の視聴は許可されていません。"}

When inspecting traffic on the webpage, I noticed that it includes the header:

x-streaks-api-key: 5f7b06697815413280feea3a12cf4324

If I add this header to my curl command, the request always succeeds.

Provide verbose output that clearly demonstrates the problem

  • 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
  • Copy the WHOLE output (starting with [debug] Command-line config) and insert it below

Complete Verbose Output

[debug] Command-line config: ['https://tver.jp/episodes/ep37yhwf6a', '-P', './!test', '-vU', '--ignore-config', '-o', '%(exractor%)s-%(id)s.%(ext)s', '--extractor-arg', 'twitter:api=legacy', '-g']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8 
[debug] yt-dlp version stable@2025.07.21 from yt-dlp/yt-dlp [9951fdd0d] (source)
[debug] Lazy loading extractors is disabled 
[debug] Git HEAD: 682334e4b 
[debug] Python 3.11.1 (CPython AMD64 64bit) - Windows-10-10.0.19045-SP0 (OpenSSL 1.1.1q  5 Jul 2022) 
[debug] exe versions: ffmpeg 7.0-full_build-www.gyan.dev (setts), ffprobe 7.0-full_build-www.gyan.dev, phantomjs 2.1.1, rtmpdump 2.3 
[debug] Optional libraries: Cryptodome-3.20.0, brotli-1.1.0, certifi-2025.01.31, curl_cffi-0.11.4, mutagen-1.47.0, requests-2.32.3, secretstorage-3.3.3, sqlite3-3.39.4, urllib3-2.3.0, websockets-13.1 
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests, websockets, curl_cffi
[debug] Extractor Plugins: RadikoLiveIE, RadikoPersonIE, RadikoSearchIE, RadikoShareIE, RadikoStationButtonIE, RadikoTimeFreeIE
[debug] Plugin directories: C:\Users\ikena\AppData\Roaming\yt-dlp\plugins\yt_dlp_rajiko-1.7-py3-none-any.whl\yt_dlp_plugins, c:\Users\ikena\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp_plugins
[debug] Loaded 1864 extractors 
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2025.07.21 from yt-dlp/yt-dlp 
yt-dlp is up to date (stable@2025.07.21 from yt-dlp/yt-dlp)
[TVer] Creating session 
[TVer] Extracting URL: https://tver.jp/episodes/ep37yhwf6a 
[TVer] ep37yhwf6a: Downloading episode info 
[TVer] ep37yhwf6a: Downloading video info 
[TVer] ref:e571ff635e0245059aad742f4f5805bc: Downloading STREAKS playback API JSON 
ERROR: [TVer] ep37yhwf6a: この動画の視聴は許可されていません。 
This video is available in Japan.
You might want to use a VPN or a proxy server (with --proxy) to workaround.
Traceback (most recent call last): 
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 908, in _request_webpage
    return self._downloader.urlopen(self._create_request(url_or_request, data, headers, query, extensions))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\YoutubeDL.py", line 4236, in urlopen
    return self._request_director.send(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\common.py", line 117, in send
    response = handler.send(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\_helper.py", line 194, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\common.py", line 359, in send
    return self._send(request)
           ^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\_requests.py", line 375, in _send
    raise HTTPError(res, redirect_loop=max_redirects_exceeded)
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: Forbidden
Traceback (most recent call last):
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 908, in _request_webpage
    return self._downloader.urlopen(self._create_request(url_or_request, data, headers, query, extensions))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\YoutubeDL.py", line 4236, in urlopen
    return self._request_director.send(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\common.py", line 117, in send
    response = handler.send(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\_helper.py", line 194, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\common.py", line 359, in send
    return self._send(request)
           ^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\networking\_requests.py", line 375, in _send
    raise HTTPError(res, redirect_loop=max_redirects_exceeded)
yt_dlp.networking.exceptions.HTTPError: HTTP Error 403: Forbidden

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\streaks.py", line 27, in _extract_from_streaks_api
    response = self._download_json(
               ^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 1149, in download_content
    res = getattr(self, download_handle.__name__)(url_or_request, video_id, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 1107, in download_handle
    res = self._download_webpage_handle(
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 972, in _download_webpage_handle
    urlh = self._request_webpage(url_or_request, video_id, note, errnote, fatal, data=data,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 921, in _request_webpage
    raise ExtractorError(errmsg, cause=err)
yt_dlp.utils.ExtractorError: Unable to download JSON metadata: HTTP Error 403: Forbidden (caused by <HTTPError 403: Forbidden>)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\temp\_repo\yt-dlp\yt_dlp\YoutubeDL.py", line 1665, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\YoutubeDL.py", line 1800, in __extract_info
    ie_result = ie.extract(url)
                ^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 761, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\tver.py", line 227, in _real_extract
    **self._extract_from_streaks_api(video_info['streaks']['projectID'], streaks_id, {
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\streaks.py", line 41, in _extract_from_streaks_api
    self.raise_geo_restricted(message, countries=self._GEO_COUNTRIES)
  File "D:\temp\_repo\yt-dlp\yt_dlp\extractor\common.py", line 1264, in raise_geo_restricted
    raise GeoRestrictedError(msg, countries=countries)
yt_dlp.utils.GeoRestrictedError: [TVer] ep37yhwf6a: この動画の視聴は許可されていません。

Metadata

Metadata

Assignees

Labels

geo-blockedContent is geo-blockedsite-bugIssue with a specific website

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions