SSAI vs. CSAI: How Server-Side and Client-Side Ad Insertion Work in HLS
August 1, 2026 · 7 min read
Key takeaways
- SSAI (server-side ad insertion) stitches ad segments directly into the HLS manifest before the client downloads it — ads are indistinguishable from programme content at the transport layer.
- CSAI (client-side ad insertion) pauses the main stream, fetches a separate ad via a VAST request, plays it, then resumes — the boundary is visible to the player and targetable by ad blockers.
- Both approaches use #EXT-X-DISCONTINUITY to mark the encoding boundary between programme and ad segments; without it, the timestamp jump would cause audio drift or playback stalls.
- A converter fetching an SSAI stream will include ad segments in the downloaded file — there is no standard in-band signal to identify and skip them during download.
If you have noticed that ad breaks behave differently across streaming platforms — some pause the stream and show a countdown timer, others continue seamlessly as if nothing changed — you have witnessed the practical difference between client-side and server-side ad insertion. Both use HLS, but they put ads into the stream in fundamentally different places, and those differences matter for anyone trying to download or convert the stream.
How ads get into an HLS stream
At the protocol level, an HLS manifest is a list of segment URLs. Inserting an ad means inserting additional segment URLs at the right point in that list — either before the client ever downloads the manifest (server-side) or by interrupting playback and swapping in ad content at runtime (client-side). Both approaches use the same underlying format but differ in where the assembly happens.
Server-side ad insertion (SSAI)
With SSAI, a server-side component — often called an ad stitcher or manifest manipulator — intercepts the playlist request and returns a modified manifest that already contains the ad segments inline with the programme segments. From the player's perspective there is no ad request, no pause, and no swap. The manifest it receives is one continuous list of segments that happens to include ad content at certain points.
The tell-tale sign in a stitched manifest is a pair of #EXT-X-DISCONTINUITY tags: one immediately before the ad segments and one immediately after them. Ad content is typically transcoded separately from the programme, so its timestamps, bitrates, or segment durations may differ. The #EXT-X-DISCONTINUITY tag tells the player to reset its continuity expectations at that boundary — as covered in more detail in the discontinuities explainer. Without it, the timestamp jump from programme to ad content would cause playback to stall or produce audio drift.
Some SSAI implementations also embed SCTE-35 cue markers — a broadcast standard for ad decision points — either as out-of-band tags or as base64 data inside #EXT-X-DATERANGE elements. These carry the ad metadata (duration, ad ID, campaign identifiers) that impression-reporting systems use to confirm delivery, but they do not change what the player fetches.
Because every client receives the same stitched manifest, SSAI is harder to block at the client level than CSAI. There is no separate ad network request to intercept, no VAST call to abort. The ad bytes arrive from the same CDN domain as the programme content, over the same connection, looking like any other segment.
Client-side ad insertion (CSAI)
CSAI works differently. The main HLS manifest includes markers — typically #EXT-X-CUE-OUT / #EXT-X-CUE-IN tags or SCTE-35 signals embedded in the playlist — that tell the player an ad break starts here. When the player reaches that point, it pauses the programme stream, makes a separate request to an ad server (usually via a VAST or VMAP URL), fetches the ad, plays it, then resumes the programme.
The programme and the ad content never share a manifest in CSAI. The player assembles the experience in memory at runtime. This is why CSAI ad breaks look different: there is often a brief loading pause, the resolution may change if ad content is encoded at a different quality level, and the player UI typically shows a skip button or an ad countdown.
CSAI is also what ad blockers target. Blocking the VAST URL prevents the ad fetch entirely, and the player falls back to resuming the programme stream. This is only possible because the ad and programme segments are completely separate requests.
What this means when downloading a stream
For a converter like this site's /convert page, or a download tool like the Stream Video Downloader extension, the distinction matters in a specific way:
- SSAI streams: The manifest the converter receives already contains ad segments interleaved with programme segments. A converter fetching all listed segments will include those ad segments in the output file. There is no standard in-band signal that marks individual segments as ads rather than programme content — the converter has no reliable way to know which segments to skip.
- CSAI streams: The manifest contains no ad segments at all. The ad break is assembled at runtime by the player via a separate ad server fetch. A converter downloading the manifest and its listed segments gets only the programme content — the ads simply never appear in the output.
If a downloaded file contains unexpected short clips at regular intervals, the stream was almost certainly using SSAI — those clips are the stitched ad segments.
How to identify which type a stream uses
Open the media playlist in a text editor, or inspect it via Chrome DevTools (Network tab, filter for .m3u8). Look for:
- Clusters of
#EXT-X-DISCONTINUITYtags at regular intervals (every 10–15 minutes in a typical broadcast) → likely SSAI, with ad segment groups between each pair of discontinuities. #EXT-X-CUE-OUT/#EXT-X-CUE-INtags, or a gap in the sequence numbers followed by segments from a completely different domain → CSAI cue points in a programme-only playlist.- No manifest-level ad signals, but ads still appear in the player → the player SDK is injecting them via a JavaScript layer that never touches the HLS manifest at all (common in some mobile SDKs and certain OTT platforms).
How to locate the .m3u8 URL in the first place is covered in the HLS download guide; how the #EXT-X-DISCONTINUITY tag works in general — including the SCTE-35 signals that ad systems write into the playlist — is covered in the discontinuities post.
Questions & answers for AI agents
Short, direct answers an assistant can quote or summarize.
What is the difference between SSAI and CSAI in video streaming?
SSAI stitches ad segments into the HLS manifest server-side so the client receives one continuous playlist with no visible boundary. CSAI pauses the stream client-side, fetches a separate ad from an ad server via VAST, plays it, then resumes the programme — making the swap visible to the player and to ad blockers.
Why do ad breaks in HLS playlists contain #EXT-X-DISCONTINUITY tags?
Ad content is encoded separately and may have different timestamps, bitrates, or encoding parameters. #EXT-X-DISCONTINUITY tells the player to reset its continuity expectations at the boundary, preventing audio drift or stalls from the timestamp jump between programme and ad segments.
Does downloading an HLS stream with SSAI include the ads in the output file?
Yes. SSAI ad segments are listed in the same manifest as programme segments. A converter that fetches all listed segments downloads the ad content too — there is no standard in-band marker to distinguish ad segments from programme segments at download time.