HLS Playlist Delta Updates: How Low-Latency HLS Reduces Polling Overhead with #EXT-X-SKIP
July 24, 2026 · 6 min read
A standard HLS live playlist grows by one segment every few seconds. The player polls it on a fixed interval — usually around the target duration of a segment — and expects a fresh, complete manifest each time. On a fast connection with a short playlist this is fine. On a slow link, or when a playlist has grown to hundreds of segments, re-downloading the entire manifest every two seconds adds measurable overhead. Low-Latency HLS addresses this with a mechanism called playlist delta updates, specified by the #EXT-X-SKIP tag and the _HLS_skip query parameter.
The problem delta updates solve
In a sliding-window live playlist, only the last few segments change between polls. The server appends one new segment URI and removes one old one. But the client still requests the full playlist — including every segment URI it already has. Most of that response is redundant data.
At low bitrates or on congested networks, a large manifest can take long enough to fetch that it eats into the reduced latency LL-HLS is trying to achieve. Delta updates let the client ask for only the difference since its last poll, cutting manifest transfer size by 80–90% on a typical live stream.
How the client requests a delta
When a server advertises delta update support, it adds CAN-SKIP-UNTIL to the #EXT-X-SERVER-CONTROL tag:
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,CAN-SKIP-UNTIL=18.0The CAN-SKIP-UNTILvalue is a number of seconds. If the client's last-seen playlist version is newer than that many seconds ago, it may append _HLS_skip=YES to its next playlist request:
GET /live/playlist.m3u8?_HLS_msn=42&_HLS_part=2&_HLS_skip=YESThe server responds with a playlist that replaces all segments older than CAN-SKIP-UNTIL seconds with a single #EXT-X-SKIP tag:
#EXT-X-SKIP:SKIPPED-SEGMENTS=25The client reads SKIPPED-SEGMENTS=25, knows to keep the 25 segments it already has in its buffer, and appends only the new segment URIs from the response. From the player's perspective the playlist is complete; it just arrived much faster.
The daterange skip variant
A second value is allowed: _HLS_skip=v2. This tells the server the client also wants to skip old #EXT-X-DATERANGE tags — metadata markers used for ad cue points and timed events. The server indicates support for this via CAN-SKIP-DATERANGES=YES in #EXT-X-SERVER-CONTROL. The v2 form is most useful for streams with frequent ad markers, where the #EXT-X-DATERANGE tags can themselves become a significant fraction of the manifest size.
What the client must track
Delta updates introduce a statefulness requirement. The client has to remember which segments it already has, because the server is no longer sending them. If the client loses that state — after a seek, a quality switch, or a connection reset — it must fall back to a full playlist request (no _HLS_skip) to re-establish a consistent view of the window.
hls.js handles this automatically. It tracks the #EXT-X-MEDIA-SEQUENCE number across delta responses and falls back to a full request whenever its local sequence falls outside the range the server can skip from.
Why this only matters for live playback
VOD playlists are static — they're fetched once and never re-polled. Delta updates only apply to live streams that are actively growing. This is one of the reasons the live HLS vs. VOD distinction matters technically: the protocol features available on each side are meaningfully different.
The site's own player (/play?broadcast=1) lets hls.js negotiate delta updates with supporting servers automatically — it's part of the standard LL-HLS feature set that lowLatencyMode enables. The converter (/convert) fetches the playlist once to enumerate segments for download and never polls, so delta updates are irrelevant there.
What the extension sees
When the Stream Video Downloader extension detects an HLS stream on a page, it captures the initial playlist URL — which may or may not include _HLS_skipparameters depending on the player on that page. The extension strips query parameters before presenting the URL to the user so the detected URL is the base playlist regardless of whatever delta/blocking parameters the page's own player happened to be using at the moment of capture.