# Buggy code
def fetch(self, segment, retries=None):
    if self.closed or not retries:
        return

    try:
        headers = {}
        now = datetime.datetime.now(tz=utc)
        if segment.available_at > now:
            time_to_wait = (segment.available_at - now).total_seconds()
            fname = os.path.basename(urlparse(segment.url).path)
            log.debug(
                "Waiting for segment: {fname} ({wait:.01f}s)".format(
                    fname=fname, wait=time_to_wait
                )
            )
            sleep_until(segment.available_at)

        if segment.range:
            start, length = segment.range
            if length:
                end = start + length - 1
            else:
                end = ""
            headers["Range"] = "bytes={0}-{1}".format(start, end)

        return self.session.http.get(
            segment.url, timeout=self.timeout, exception=StreamError, headers=headers
        )
    except StreamError as err:
        log.error("Failed to open segment {0}: {1}", segment.url, err)
        return self.fetch(segment, retries - 1)


# Traceback (requests.exceptions.HTTPError)
$ streamlink https://www.tf1.fr/lci/direct 576p_dash
[cli][debug] OS:         Linux
[cli][debug] Python:     3.6.7
[cli][debug] Streamlink: 1.0.0+3.g4100688.dirty
[cli][debug] Requests(2.21.0), Socks(1.6.7), Websocket(0.54.0)
[cli][info] Found matching plugin tf1 for URL https://www.tf1.fr/lci/direct
[plugin.tf1][debug] Found channel lci
[plugin.tf1][debug] Got dash stream https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=
[utils.l10n][debug] Language code: en_US
[stream.dash][debug] Available languages for DASH audio streams: NONE (using: n/a)
[plugin.tf1][debug] Got hls stream https://lci-hls-live-ssl.tf1.fr/lci/1/hls/master_4000000.m3u8?e=&amp;st=
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: 234p_dash, 360p_dash, 576p_dash, 234p (worst), 360p, 576p_alt, 576p, 720p (best)
[cli][info] Opening stream: 576p_dash (dash)
[stream.dash][debug] Opening DASH reader for: live_1828_H264 (video/mp4)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live_1828_H264))
[stream.dash][debug] Reloading manifest (live_1828_H264:video/mp4)
[stream.dash][debug] Opening DASH reader for: live_2328_AAC (audio/mp4)
[stream.dash_manifest][debug] Generating segment timeline for dynamic playlist (id=live_2328_AAC))
[stream.dash][debug] Reloading manifest (live_2328_AAC:audio/mp4)
[stream.mp4mux-ffmpeg][debug] ffmpeg command: /usr/bin/ffmpeg -nostats -y -i /tmp/ffmpeg-2811-460 -i /tmp/ffmpeg-2811-532 -c:v copy -c:a copy -copyts -f matroska pipe:1
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/ffmpeg-2811-460
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/ffmpeg-2811-532
[cli][debug] Pre-buffering 8192 bytes
[stream.dash][debug] Download of segment: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_1828/init.m4v complete
Exception in thread Thread-DASHStreamWorker:
Traceback (most recent call last):
File "src/streamlink/plugin/api/http_session.py", line 166, in request
res.raise_for_status()
File "env/lib/python3.6/site-packages/requests/models.py", line 940, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "src/streamlink/stream/segmented.py", line 59, in run
for segment in self.iter_segments():
File "src/streamlink/stream/dash.py", line 97, in iter_segments
if not self.reload():
File "src/streamlink/stream/dash.py", line 111, in reload
res = self.session.http.get(self.mpd.url, exception=StreamError)
File "env/lib/python3.6/site-packages/requests/sessions.py", line 546, in get
return self.request('GET', url, **kwargs)
File "src/streamlink/plugin/api/http_session.py", line 175, in request
raise err
streamlink.exceptions.StreamError: Unable to open URL: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=
(403 Client Error: Forbidden for url: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=)
Exception in thread Thread-DASHStreamWorker:
Traceback (most recent call last):
File "src/streamlink/plugin/api/http_session.py", line 166, in request
res.raise_for_status()
File "env/lib/python3.6/site-packages/requests/models.py", line 940, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "src/streamlink/stream/segmented.py", line 59, in run
for segment in self.iter_segments():
File "src/streamlink/stream/dash.py", line 97, in iter_segments
if not self.reload():
File "src/streamlink/stream/dash.py", line 111, in reload
res = self.session.http.get(self.mpd.url, exception=StreamError)
File "env/lib/python3.6/site-packages/requests/sessions.py", line 546, in get
return self.request('GET', url, **kwargs)
File "src/streamlink/plugin/api/http_session.py", line 175, in request
raise err
streamlink.exceptions.StreamError: Unable to open URL: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=
(403 Client Error: Forbidden for url: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2000000.mpd?e=&amp;st=)

[stream.dash][debug] Download of segment: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2328/init.m4a complete
[stream.dash][debug] Download of segment: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2328/65796000.m4a complete
[stream.dash][debug] Download of segment: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2328/65800000.m4a complete
[stream.dash][debug] Download of segment: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_2328/65804000.m4a complete
[stream.dash][debug] Download of segment: https://lci-das-live-ssl.tf1.fr/lci/1/dash/live_1828/65792000.m4v complete

# Fixed code
def fetch(self, segment, retries=None):
    if self.closed or not retries:
        return

    try:
        request_args = copy.deepcopy(self.reader.stream.args)
        headers = request_args.pop("headers", {})
        now = datetime.datetime.now(tz=utc)
        if segment.available_at > now:
            time_to_wait = (segment.available_at - now).total_seconds()
            fname = os.path.basename(urlparse(segment.url).path)
            log.debug(
                "Waiting for segment: {fname} ({wait:.01f}s)".format(
                    fname=fname, wait=time_to_wait
                )
            )
            sleep_until(segment.available_at)

        if segment.range:
            start, length = segment.range
            if length:
                end = start + length - 1
            else:
                end = ""
            headers["Range"] = "bytes={0}-{1}".format(start, end)

        return self.session.http.get(
            segment.url,
            timeout=self.timeout,
            exception=StreamError,
            headers=headers,
            **request_args,
        )
    except StreamError as err:
        log.error("Failed to open segment {0}: {1}", segment.url, err)
        return self.fetch(segment, retries - 1)