We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
plugins.dlive: Failed to fetch segment | 403 Client Error
### Checklist

- [X] This is a [plugin issue](https://streamlink.github.io/plugins.html) and not [a different kind of issue](https://github.com/streamlink/streamlink/issues/new/choose)
- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)
- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)
- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)

### Streamlink version

[cli][info] Your Streamlink version (6.2.1) is up to date!

### Description

I navigate to the folder where streamlink.exe is located and enter the command "streamlink.exe https://dlive.tv/cryptokaprika best". It doesn't matter which channel is specified, the same error comes up for all of them as of late.


Here is the complete output that is shown to me in the command line:


C:\Program Files\Streamlink\bin>streamlink.exe https://dlive.tv/cryptokaprika best

[cli][info] Found matching plugin dlive for URL https://dlive.tv/cryptokaprika

[cli][info] Available streams: src (worst, best)

[cli][info] Opening stream: src (hls)

[cli][info] Starting player: C:\Program Files\VideoLAN\VLC\vlc.exe

[stream.hls][error] Failed to fetch segment 79790: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079790.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079790.ts)

[stream.hls][error] Failed to fetch segment 79791: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079791.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079791.ts)

[cli][info] Stream ended

[cli][info] Closing currently open stream...


The VLC Media Player also starts, but I only get the following picture and am referred to the homepage: [https://imgur.com/a/NpuAHQ3](https://imgur.com/a/NpuAHQ3)

### Debug log

```text
C:\Program Files\Streamlink\bin>streamlink.exe --loglevel=debug https://dlive.tv/cryptokaprika best
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.11.5
[cli][debug] OpenSSL:    OpenSSL 3.0.9 30 May 2023
[cli][debug] Streamlink: 6.2.1
[cli][debug] Dependencies:
[cli][debug]  certifi: 2023.7.22
[cli][debug]  isodate: 0.6.1
[cli][debug]  lxml: 4.9.3
[cli][debug]  pycountry: 22.3.5
[cli][debug]  pycryptodome: 3.19.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.31.0
[cli][debug]  trio: 0.22.2
[cli][debug]  trio-websocket: 0.11.1
[cli][debug]  typing-extensions: 4.8.0
[cli][debug]  urllib3: 2.0.6
[cli][debug]  websocket-client: 1.6.3
[cli][debug] Arguments:
[cli][debug]  url=https://dlive.tv/cryptokaprika
[cli][debug]  stream=['best']
[cli][debug]  --loglevel=debug
[cli][debug]  --ffmpeg-ffmpeg=C:\Program Files\Streamlink\ffmpeg\ffmpeg.exe
[cli][info] Found matching plugin dlive for URL https://dlive.tv/cryptokaprika
[plugins.dlive][debug] Getting live HLS streams for cryptokaprika
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: src (worst, best)
[cli][info] Opening stream: src (hls)
[cli][info] Starting player: C:\Program Files\VideoLAN\VLC\vlc.exe
[stream.hls][debug] Reloading playlist
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] First Sequence: 79786; Last Sequence: 79791
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 79786; End Sequence: 79791
[stream.hls][debug] Adding segment 79786 to queue
[stream.hls][debug] Adding segment 79787 to queue
[stream.hls][debug] Adding segment 79788 to queue
[stream.hls][debug] Adding segment 79789 to queue
[stream.hls][debug] Adding segment 79790 to queue
[stream.hls][debug] Adding segment 79791 to queue
[stream.segmented][debug] Closing worker thread
[stream.hls][debug] Writing segment 79786 to output
[stream.hls][debug] Segment 79786 complete
[cli.output][debug] Opening subprocess: ['C:\\Program Files\\VideoLAN\\VLC\\vlc.exe', '--input-title-format', 'https://dlive.tv/cryptokaprika', '-']
[stream.hls][debug] Writing segment 79787 to output
[stream.hls][debug] Segment 79787 complete
[stream.hls][debug] Writing segment 79788 to output
[stream.hls][debug] Segment 79788 complete
[stream.hls][debug] Writing segment 79789 to output
[stream.hls][debug] Segment 79789 complete
[cli][debug] Writing stream to output
[stream.hls][error] Failed to fetch segment 79790: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079790.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079790.ts)
[stream.hls][error] Failed to fetch segment 79791: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079791.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079791.ts)
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
[cli][info] Closing currently open stream...
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/streamlink/plugins/dlive.py`
Content:
```
1 """
2 $description Global live-streaming platform owned by BitTorrent, Inc.
3 $url dlive.tv
4 $type live, vod
5 $metadata author
6 $metadata title
7 """
8 
9 import logging
10 import re
11 from urllib.parse import unquote_plus
12 
13 from streamlink.plugin import Plugin, pluginmatcher
14 from streamlink.plugin.api import validate
15 from streamlink.stream.hls import HLSStream
16 
17 
18 log = logging.getLogger(__name__)
19 
20 
21 @pluginmatcher(re.compile(r"""
22     https?://(?:www\.)?dlive\.tv/
23     (?:
24         p/(?P<video>[^/]+)
25         |
26         (?P<channel>[^/]+)
27     )
28 """, re.VERBOSE))
29 class DLive(Plugin):
30     URL_LIVE = "https://live.prd.dlive.tv/hls/live/{username}.m3u8"
31 
32     QUALITY_WEIGHTS = {
33         "src": 1080,
34     }
35 
36     @classmethod
37     def stream_weight(cls, key):
38         weight = cls.QUALITY_WEIGHTS.get(key)
39         if weight:
40             return weight, "dlive"
41 
42         return super().stream_weight(key)
43 
44     def _get_streams_video(self, video):
45         log.debug(f"Getting video HLS streams for {video}")
46         hls_url = self.session.http.get(self.url, schema=validate.Schema(
47             validate.regex(re.compile(r'"playbackUrl"\s*:\s*"([^"]+\.m3u8)"')),
48             validate.get(1),
49             validate.transform(unquote_plus),
50             validate.transform(lambda url: bytes(url, "utf-8").decode("unicode_escape")),
51             validate.url(),
52         ))
53 
54         return HLSStream.parse_variant_playlist(self.session, hls_url)
55 
56     def _get_streams_live(self, channel):
57         log.debug(f"Getting live HLS streams for {channel}")
58         query = f"""query {{
59             userByDisplayName(displayname:"{channel}") {{
60                 livestream {{
61                     title
62                 }}
63                 username
64             }}
65         }}"""
66         livestream, username = self.session.http.post(
67             "https://graphigo.prd.dlive.tv/",
68             json={"query": query},
69             schema=validate.Schema(
70                 validate.parse_json(),
71                 {
72                     "data": {
73                         "userByDisplayName": {
74                             "livestream": {
75                                 "title": str,
76                             },
77                             "username": str,
78                         },
79                     },
80                 },
81                 validate.get(("data", "userByDisplayName")),
82                 validate.union_get("livestream", "username"),
83             ),
84         )
85 
86         self.author = channel
87         self.title = livestream["title"]
88 
89         return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username))
90 
91     def _get_streams(self):
92         video = self.match.group("video")
93         channel = self.match.group("channel")
94 
95         if video:
96             return self._get_streams_video(video)
97         elif channel:
98             return self._get_streams_live(channel)
99 
100 
101 __plugin__ = DLive
102
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/streamlink/plugins/dlive.py b/src/streamlink/plugins/dlive.py
--- a/src/streamlink/plugins/dlive.py
+++ b/src/streamlink/plugins/dlive.py
@@ -86,7 +86,7 @@
         self.author = channel
         self.title = livestream["title"]
 
-        return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username))
+        return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username), headers={"Referer": "https://dlive.tv/"})
 
     def _get_streams(self):
         video = self.match.group("video")

{"golden_diff": "diff --git a/src/streamlink/plugins/dlive.py b/src/streamlink/plugins/dlive.py\n--- a/src/streamlink/plugins/dlive.py\n+++ b/src/streamlink/plugins/dlive.py\n@@ -86,7 +86,7 @@\n         self.author = channel\n         self.title = livestream[\"title\"]\n \n-        return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username))\n+        return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username), headers={\"Referer\": \"https://dlive.tv/\"})\n \n     def _get_streams(self):\n         video = self.match.group(\"video\")\n", "issue": "plugins.dlive: Failed to fetch segment | 403 Client Error\n### Checklist\n\n- [X] This is a [plugin issue](https://streamlink.github.io/plugins.html) and not [a different kind of issue](https://github.com/streamlink/streamlink/issues/new/choose)\n- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)\n- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)\n- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)\n\n### Streamlink version\n\n[cli][info] Your Streamlink version (6.2.1) is up to date!\n\n### Description\n\nI navigate to the folder where streamlink.exe is located and enter the command \"streamlink.exe https://dlive.tv/cryptokaprika best\". It doesn't matter which channel is specified, the same error comes up for all of them as of late.\r\n\r\n\r\nHere is the complete output that is shown to me in the command line:\r\n\r\n\r\nC:\\Program Files\\Streamlink\\bin>streamlink.exe https://dlive.tv/cryptokaprika best\r\n\r\n[cli][info] Found matching plugin dlive for URL https://dlive.tv/cryptokaprika\r\n\r\n[cli][info] Available streams: src (worst, best)\r\n\r\n[cli][info] Opening stream: src (hls)\r\n\r\n[cli][info] Starting player: C:\\Program Files\\VideoLAN\\VLC\\vlc.exe\r\n\r\n[stream.hls][error] Failed to fetch segment 79790: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079790.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079790.ts)\r\n\r\n[stream.hls][error] Failed to fetch segment 79791: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079791.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079791.ts)\r\n\r\n[cli][info] Stream ended\r\n\r\n[cli][info] Closing currently open stream...\r\n\r\n\r\nThe VLC Media Player also starts, but I only get the following picture and am referred to the homepage: [https://imgur.com/a/NpuAHQ3](https://imgur.com/a/NpuAHQ3)\n\n### Debug log\n\n```text\nC:\\Program Files\\Streamlink\\bin>streamlink.exe --loglevel=debug https://dlive.tv/cryptokaprika best\r\n[cli][debug] OS:         Windows 10\r\n[cli][debug] Python:     3.11.5\r\n[cli][debug] OpenSSL:    OpenSSL 3.0.9 30 May 2023\r\n[cli][debug] Streamlink: 6.2.1\r\n[cli][debug] Dependencies:\r\n[cli][debug]  certifi: 2023.7.22\r\n[cli][debug]  isodate: 0.6.1\r\n[cli][debug]  lxml: 4.9.3\r\n[cli][debug]  pycountry: 22.3.5\r\n[cli][debug]  pycryptodome: 3.19.0\r\n[cli][debug]  PySocks: 1.7.1\r\n[cli][debug]  requests: 2.31.0\r\n[cli][debug]  trio: 0.22.2\r\n[cli][debug]  trio-websocket: 0.11.1\r\n[cli][debug]  typing-extensions: 4.8.0\r\n[cli][debug]  urllib3: 2.0.6\r\n[cli][debug]  websocket-client: 1.6.3\r\n[cli][debug] Arguments:\r\n[cli][debug]  url=https://dlive.tv/cryptokaprika\r\n[cli][debug]  stream=['best']\r\n[cli][debug]  --loglevel=debug\r\n[cli][debug]  --ffmpeg-ffmpeg=C:\\Program Files\\Streamlink\\ffmpeg\\ffmpeg.exe\r\n[cli][info] Found matching plugin dlive for URL https://dlive.tv/cryptokaprika\r\n[plugins.dlive][debug] Getting live HLS streams for cryptokaprika\r\n[utils.l10n][debug] Language code: en_US\r\n[cli][info] Available streams: src (worst, best)\r\n[cli][info] Opening stream: src (hls)\r\n[cli][info] Starting player: C:\\Program Files\\VideoLAN\\VLC\\vlc.exe\r\n[stream.hls][debug] Reloading playlist\r\n[cli][debug] Pre-buffering 8192 bytes\r\n[stream.hls][debug] First Sequence: 79786; Last Sequence: 79791\r\n[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 79786; End Sequence: 79791\r\n[stream.hls][debug] Adding segment 79786 to queue\r\n[stream.hls][debug] Adding segment 79787 to queue\r\n[stream.hls][debug] Adding segment 79788 to queue\r\n[stream.hls][debug] Adding segment 79789 to queue\r\n[stream.hls][debug] Adding segment 79790 to queue\r\n[stream.hls][debug] Adding segment 79791 to queue\r\n[stream.segmented][debug] Closing worker thread\r\n[stream.hls][debug] Writing segment 79786 to output\r\n[stream.hls][debug] Segment 79786 complete\r\n[cli.output][debug] Opening subprocess: ['C:\\\\Program Files\\\\VideoLAN\\\\VLC\\\\vlc.exe', '--input-title-format', 'https://dlive.tv/cryptokaprika', '-']\r\n[stream.hls][debug] Writing segment 79787 to output\r\n[stream.hls][debug] Segment 79787 complete\r\n[stream.hls][debug] Writing segment 79788 to output\r\n[stream.hls][debug] Segment 79788 complete\r\n[stream.hls][debug] Writing segment 79789 to output\r\n[stream.hls][debug] Segment 79789 complete\r\n[cli][debug] Writing stream to output\r\n[stream.hls][error] Failed to fetch segment 79790: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079790.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079790.ts)\r\n[stream.hls][error] Failed to fetch segment 79791: Unable to open URL: https://videos.prd.dlivecdn.com/dlive/0000079791.ts (403 Client Error: Forbidden for url: https://videos.prd.dlivecdn.com/dlive/0000079791.ts)\r\n[stream.segmented][debug] Closing writer thread\r\n[cli][info] Stream ended\r\n[cli][info] Closing currently open stream...\n```\n\n", "before_files": [{"content": "\"\"\"\n$description Global live-streaming platform owned by BitTorrent, Inc.\n$url dlive.tv\n$type live, vod\n$metadata author\n$metadata title\n\"\"\"\n\nimport logging\nimport re\nfrom urllib.parse import unquote_plus\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(r\"\"\"\n    https?://(?:www\\.)?dlive\\.tv/\n    (?:\n        p/(?P<video>[^/]+)\n        |\n        (?P<channel>[^/]+)\n    )\n\"\"\", re.VERBOSE))\nclass DLive(Plugin):\n    URL_LIVE = \"https://live.prd.dlive.tv/hls/live/{username}.m3u8\"\n\n    QUALITY_WEIGHTS = {\n        \"src\": 1080,\n    }\n\n    @classmethod\n    def stream_weight(cls, key):\n        weight = cls.QUALITY_WEIGHTS.get(key)\n        if weight:\n            return weight, \"dlive\"\n\n        return super().stream_weight(key)\n\n    def _get_streams_video(self, video):\n        log.debug(f\"Getting video HLS streams for {video}\")\n        hls_url = self.session.http.get(self.url, schema=validate.Schema(\n            validate.regex(re.compile(r'\"playbackUrl\"\\s*:\\s*\"([^\"]+\\.m3u8)\"')),\n            validate.get(1),\n            validate.transform(unquote_plus),\n            validate.transform(lambda url: bytes(url, \"utf-8\").decode(\"unicode_escape\")),\n            validate.url(),\n        ))\n\n        return HLSStream.parse_variant_playlist(self.session, hls_url)\n\n    def _get_streams_live(self, channel):\n        log.debug(f\"Getting live HLS streams for {channel}\")\n        query = f\"\"\"query {{\n            userByDisplayName(displayname:\"{channel}\") {{\n                livestream {{\n                    title\n                }}\n                username\n            }}\n        }}\"\"\"\n        livestream, username = self.session.http.post(\n            \"https://graphigo.prd.dlive.tv/\",\n            json={\"query\": query},\n            schema=validate.Schema(\n                validate.parse_json(),\n                {\n                    \"data\": {\n                        \"userByDisplayName\": {\n                            \"livestream\": {\n                                \"title\": str,\n                            },\n                            \"username\": str,\n                        },\n                    },\n                },\n                validate.get((\"data\", \"userByDisplayName\")),\n                validate.union_get(\"livestream\", \"username\"),\n            ),\n        )\n\n        self.author = channel\n        self.title = livestream[\"title\"]\n\n        return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username))\n\n    def _get_streams(self):\n        video = self.match.group(\"video\")\n        channel = self.match.group(\"channel\")\n\n        if video:\n            return self._get_streams_video(video)\n        elif channel:\n            return self._get_streams_live(channel)\n\n\n__plugin__ = DLive\n", "path": "src/streamlink/plugins/dlive.py"}], "after_files": [{"content": "\"\"\"\n$description Global live-streaming platform owned by BitTorrent, Inc.\n$url dlive.tv\n$type live, vod\n$metadata author\n$metadata title\n\"\"\"\n\nimport logging\nimport re\nfrom urllib.parse import unquote_plus\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(r\"\"\"\n    https?://(?:www\\.)?dlive\\.tv/\n    (?:\n        p/(?P<video>[^/]+)\n        |\n        (?P<channel>[^/]+)\n    )\n\"\"\", re.VERBOSE))\nclass DLive(Plugin):\n    URL_LIVE = \"https://live.prd.dlive.tv/hls/live/{username}.m3u8\"\n\n    QUALITY_WEIGHTS = {\n        \"src\": 1080,\n    }\n\n    @classmethod\n    def stream_weight(cls, key):\n        weight = cls.QUALITY_WEIGHTS.get(key)\n        if weight:\n            return weight, \"dlive\"\n\n        return super().stream_weight(key)\n\n    def _get_streams_video(self, video):\n        log.debug(f\"Getting video HLS streams for {video}\")\n        hls_url = self.session.http.get(self.url, schema=validate.Schema(\n            validate.regex(re.compile(r'\"playbackUrl\"\\s*:\\s*\"([^\"]+\\.m3u8)\"')),\n            validate.get(1),\n            validate.transform(unquote_plus),\n            validate.transform(lambda url: bytes(url, \"utf-8\").decode(\"unicode_escape\")),\n            validate.url(),\n        ))\n\n        return HLSStream.parse_variant_playlist(self.session, hls_url)\n\n    def _get_streams_live(self, channel):\n        log.debug(f\"Getting live HLS streams for {channel}\")\n        query = f\"\"\"query {{\n            userByDisplayName(displayname:\"{channel}\") {{\n                livestream {{\n                    title\n                }}\n                username\n            }}\n        }}\"\"\"\n        livestream, username = self.session.http.post(\n            \"https://graphigo.prd.dlive.tv/\",\n            json={\"query\": query},\n            schema=validate.Schema(\n                validate.parse_json(),\n                {\n                    \"data\": {\n                        \"userByDisplayName\": {\n                            \"livestream\": {\n                                \"title\": str,\n                            },\n                            \"username\": str,\n                        },\n                    },\n                },\n                validate.get((\"data\", \"userByDisplayName\")),\n                validate.union_get(\"livestream\", \"username\"),\n            ),\n        )\n\n        self.author = channel\n        self.title = livestream[\"title\"]\n\n        return HLSStream.parse_variant_playlist(self.session, self.URL_LIVE.format(username=username), headers={\"Referer\": \"https://dlive.tv/\"})\n\n    def _get_streams(self):\n        video = self.match.group(\"video\")\n        channel = self.match.group(\"channel\")\n\n        if video:\n            return self._get_streams_video(video)\n        elif channel:\n            return self._get_streams_live(channel)\n\n\n__plugin__ = DLive\n", "path": "src/streamlink/plugins/dlive.py"}]}