Every time a live broadcast cuts cleanly to a commercial and returns without a stutter, something invisible made that switch possible. That something is usually SCTE-35 — the signaling standard that tells downstream systems exactly where an ad break, a program boundary, or a blackout begins and ends. If you run a streaming platform, a FAST channel, or any ad-supported service, SCTE-35 is the quiet protocol underneath your monetization. This guide explains what SCTE-35 is, how a cue message is actually built, the two command types that matter, and how those cues ride across MPEG-TS, HLS, and DASH to reach the ad systems that turn them into revenue.
Think of a SCTE-35 marker as a note scribbled in the margin of a script: it doesn’t contain the advertisement itself, and it doesn’t play anything. It simply says, “an opportunity starts here, and it lasts this long.” What happens at that mark — insert a national ad, swap in a regional feed, black out a game — is decided by other systems reading the note. Keeping that distinction clear is the key to understanding everything below.
What is SCTE (the organization)?
SCTE stands for the Society of Cable Telecommunications Engineers, a non-profit standards body founded in 1969 that develops technical standards for the cable and wider video industry. Its catalog runs to hundreds of standards, but the one that shapes modern streaming monetization is SCTE-35. You can browse the organization and its standards library at scte.org.
What is SCTE-35?
SCTE-35 is the core signaling standard for advertising and program control across broadcast and streaming. First published in 2001 as “Digital Program Insertion Cueing Message for Cable,” it has been revised repeatedly and extended well beyond cable into OTT workflows — recent revisions even dropped “for Cable” from the title. At its heart, SCTE-35 defines a compact binary cue message that identifies upcoming splice points: national and local ad breaks, chapter and program boundaries, and content that must be blacked out or replaced. For background and revision history, the SCTE-35 entry on Wikipedia is a useful neutral reference.
Originally these cues were physical tones that dedicated cable hardware detected. Today they are embedded as metadata inside the stream — typically on their own identifier within an MPEG-TS feed — and later translated into manifest markers that HLS and DASH players and ad systems can act on. That translation step is where a CDN and packager earn their keep.
What SCTE-35 is used for
Ad insertion is the headline use case, but the standard signals several distinct event types. The most common are:
- Ad breaks — the splice points where national, local, or individually targeted ads are inserted. Precise signaling is the foundation for both server-side ad insertion (SSAI) and the newer server-guided approach (SGAI).
- Program boundaries — start/end of programs, chapters, and credits. In live-to-VOD workflows these double as edit points, letting you strip ads for paying subscribers or auto-trigger the next episode.
- Blackouts and alternate content — regional restrictions common in live sports, where a feed must be replaced or withheld in certain territories. Respecting these is a contractual and legal necessity, not a nicety.
- Program extensions — when a live event runs long, cues let automation gracefully extend the window instead of cutting away mid-action.
A concrete way to picture the difference: imagine a live football match on a national network. A time_signal cue marks the two-minute break at the referee’s whistle; a segmentation descriptor labels it a distributor placement opportunity so each regional affiliate can fill it with local ads; and a separate blackout cue tells one particular region to hide the feed entirely because the game is subject to a local broadcast restriction. Three different outcomes, all driven by the same underlying standard — the network operator never touches a switch manually. That is the automation SCTE-35 exists to enable, and it scales from one channel to thousands.

Anatomy of a SCTE-35 message

A SCTE-35 message is a structure called the splice_info_section. Stripped to essentials, it contains a handful of fields wrapping one splice command and an optional loop of descriptors:
- table_id — identifies the section as SCTE-35 (0xFC).
- splice_command_type — which of the command types below this message carries.
- splice command — the payload itself (e.g. a splice_insert or time_signal), including timing expressed as a PTS value.
- descriptor_loop — zero or more descriptors; the segmentation_descriptor is the important one, carrying intent and IDs.
- CRC_32 — integrity check so downstream systems can reject corrupted cues.
Timing hangs on the PTS (Presentation Time Stamp) — the same clock used to schedule audio and video — which is what makes frame-accurate splicing possible. A cue that is a few frames off produces a visible glitch, so PTS alignment is where a lot of real-world integration effort goes.
Two design choices in this structure matter more than they first appear. First, the message deliberately carries no advertising content — only a reference to an opportunity. That separation is why the same cue can drive a national ad on one feed, a regional ad on another, and a blackout on a third, without ever re-encoding the source. Second, the descriptor loop is open-ended: a single cue can carry multiple descriptors, so one splice point can simultaneously say “this is a break,” “it is a provider placement opportunity,” and “here is the unique ID to report against.” Downstream systems read whichever descriptors they understand and ignore the rest, which is what has let the standard survive twenty-plus years of change without breaking older equipment.
SCTE-35 command types: the five, and the two that matter
The specification defines five splice command types. Three are legacy; two carry essentially all modern OTT workflows.

| Command | Status | What it does |
|---|---|---|
| splice_null | Legacy | Heartbeat / bandwidth reservation placeholder; carries no splice. |
| splice_schedule | Legacy | Pre-announces future splices; rarely used in streaming. |
| splice_insert | Active | Marks an immediate or scheduled splice with precise PTS and duration — the classic ad in/out. |
| time_signal | Active (preferred) | A timed cue that, paired with segmentation descriptors, expresses rich intent (ad pod, chapter, blackout). |
| bandwidth_reservation | Niche | Reserves capacity in some satellite paths; irrelevant to most OTT. |
splice_insert
splice_insert marks a splice event — content out to an ad, or ad back to content — with presentation timestamps pinning the exact frame. It is simple, widely supported, and still common for straightforward ad in/out signaling. A splice_insert can be immediate (splice now) or scheduled (splice at a future PTS), and it carries a splice_event_id so the out and the matching in can be paired. Its limitation is expressiveness: it says “splice here for this long” but carries none of the richer intent — provider vs distributor, chapter vs ad, addressable vs fixed — that modern ad decisioning wants. For a basic mid-roll on a single feed it is perfectly adequate; for targeted, multi-region monetization it runs out of vocabulary.
time_signal
time_signal is the modern workhorse. On its own it just marks a moment, but combined with segmentation descriptors it can label what that moment means — a provider ad opportunity, a distributor ad, a chapter, a blackout — giving downstream ad systems far more to work with than a bare splice. Because the meaning lives in the descriptors rather than the command, a single time_signal cue can describe complex scenarios: nested breaks, overlapping segments, or an ad pod with a precise duration the ad server uses to plan how many spots to fill. This is why virtually all new OTT and addressable-TV workflows standardize on time_signal plus segmentation descriptors, and treat splice_insert mainly as a compatibility path for legacy sources.
Segmentation descriptors and UPIDs (where the real intelligence lives)
A time_signal becomes powerful because of the segmentation_descriptor attached to it. This is the field that tells an ad decision system not just “something starts here” but “this is a two-minute provider ad pod, uniquely identified, and here’s where it ends.” The key sub-fields:
- segmentation_event_id — a unique ID linking the start and end of the same segment.
- segmentation_type_id — what kind of boundary this is (see the table below).
- segmentation_duration — how long the opportunity lasts, so systems can plan the pod.
- segmentation_upid — a Unique Program Identifier: an ad-ID, content ID, or other reference the ad server maps to a campaign or a blackout rule.

The most frequently encountered segmentation_type_id values in ad workflows are:
| type_id (hex) | Meaning | Typical use |
|---|---|---|
| 0x10 / 0x11 | Program Start / End | Program boundaries; live-to-VOD edit points |
| 0x20 / 0x21 | Chapter Start / End | Chapters and segments within a program |
| 0x22 / 0x23 | Break Start / End | Generic ad break window |
| 0x30 / 0x31 | Provider Ad Start / End | Content owner’s ad opportunity |
| 0x32 / 0x33 | Distributor Ad Start / End | Distributor’s ad opportunity |
| 0x34 / 0x35 | Provider Placement Opportunity | Addressable / dynamic ad pod (provider) |
| 0x36 / 0x37 | Distributor Placement Opportunity | Addressable / dynamic ad pod (distributor) |
Placement-opportunity types (0x34–0x37) are the ones most associated with dynamic, targeted insertion, because they explicitly frame a slot the ad system is expected to fill per-viewer. Getting these right is what separates “we show an ad” from “we show the right ad, and count it correctly.”
Decoding a real SCTE-35 payload
In manifests, SCTE-35 cues usually appear as base64-encoded binary. A short one looks like this:
/DAvAAAAAAAA///wBQb+dGKQoAAZAhdDVUVJ/////4AAAAAAAAAAAAAAAAAAAAA=
That opaque string is a full splice_info_section. Decoded, it resolves into the command type, the PTS, and any descriptors — exactly the fields described above. You don’t have to parse it by hand: paste a payload into an open-source parser such as Comcast’s scte35-js tool to see the whole structure expanded. Being able to decode a cue is the single most useful debugging skill when an ad break fires late, early, or not at all.
A decoded payload typically shows you: the splice_command_type (is this a time_signal or a splice_insert?), the PTS value (does the break fire at the moment you expect?), and each segmentation_descriptor with its type ID and UPID (is this labeled as the right kind of opportunity, and does the ID match what your ad server is configured for?). Ninety percent of real integration bugs become obvious the instant you read those three things. If the PTS is wrong, your timing is off at the source; if the type ID is unexpected, the ad server is filtering the cue out; if the UPID is empty when it shouldn’t be, the upstream system isn’t populating it. Decoding turns “the ads don’t work” into a specific, fixable fault in seconds.
How SCTE-35 travels across formats

MPEG-TS (contribution and backhaul)
In an MPEG-TS feed, SCTE-35 cues ride in-band on their own PID (packet identifier) alongside audio and video. These feeds are usually contribution or backhaul links — encoder to cloud, or site to site — not something a viewer plays directly. They travel over dedicated satellite or fiber, or over the public internet using a secure transport like SRT. Preserving the cue PID intact through ingest and transcoding is essential; lose it and every downstream ad decision disappears with it.
The PID approach has a practical consequence worth understanding. Because the cue travels as its own elementary stream referenced in the program map table, a transcoder that isn’t explicitly configured to pass SCTE-35 through will often drop it — the video and audio arrive perfectly while the monetization signal silently vanishes. This is one of the most common reasons a workflow “works” in testing but shows no ad breaks in production. The fix is to confirm SCTE-35 pass-through at every hop, and to validate that the PID still carries cues after transcoding and repackaging, not just at the encoder output. For contribution over lossy networks, the transport’s reliability features (SRT’s retransmission, for example) also protect the cue packets, so a marker isn’t lost to a dropped packet at exactly the wrong moment.
HLS
When a packager produces HLS for playback, it maps SCTE-35 cues into manifest tags. Which tag you use depends on what the downstream SSAI service expects — its documentation states the supported flavor. The common variants:
| HLS tag | Carries | Notes |
|---|---|---|
| #EXT-X-CUE-OUT / -IN | Break duration + return point | Simple, widely supported ad in/out |
| #EXT-OATCLS-SCTE35 | Base64 raw cue bytes | Preserves the full original message |
| #EXT-X-SPLICEPOINT-SCTE35 | Base64 raw cue bytes | Splice-point-oriented signaling |
| #EXT-X-SCTE35 | Base64 raw cue bytes | Generic raw-payload carriage |
| #EXT-X-DATERANGE | ID, start time, hex cue bytes | Standards-track tag in RFC 8216; increasingly preferred |
The #EXT-X-DATERANGE tag is defined in the HLS specification itself — IETF RFC 8216 — which is why it has become the most portable option for new deployments. A minimal CUE-OUT/CUE-IN pair looks like this in the playlist:
#EXTINF:4.0,
seg_18188.ts
#EXT-X-CUE-OUT:120.000
…
#EXTINF:4.0,
seg_18218.ts
#EXT-X-CUE-IN
MPEG-DASH
DASH expresses cues differently. Rather than inline playlist tags, an ad opportunity is signaled as an EventStream within a Period in the MPD, carrying the binary SCTE-35 payload. Some workflows also split the timeline into separate Periods for content and ad, using a discontinuity boundary between them. For the underlying model, see the MPEG-DASH overview. A trimmed example:
<Period start=”PT32S” id=”2″>
<EventStream schemeIdUri=”urn:scte:scte35:2014:xml+bin” timescale=”90000″>
<Event duration=”2520000″ id=”1″>
<Signal><Binary>/DAlAAAAAAAAAP/wFAU…</Binary></Signal>
</Event>
</EventStream>
</Period>
Whether the stream is HLS or DASH, the packaging format is increasingly CMAF-based, letting a single set of segments serve both — but the SCTE-35 signaling still has to be expressed in each manifest’s own idiom.
From marker to money: SCTE-35, SSAI and SGAI

SCTE-35 only marks the opportunity. Turning that into a delivered, counted ad is the job of an ad-insertion workflow. In server-side ad insertion, the SSAI service reads the cue, queries an ad decision server with a VAST or VMAP request, transcodes the chosen ad to match the stream, and stitches it into the manifest so the viewer sees one seamless, ad-blocker-resistant stream. The newer server-guided ad insertion (SGAI) approach keeps content and ads as separate manifest interstitials, giving more flexibility and personalization while easing some of the transcode burden — a direction gaining real traction in 2026.
In all cases the chain is the same: a clean, accurately-timed SCTE-35 cue in, a correctly-stitched and measurable ad out. If the cue is wrong, everything after it is wrong too — which is why the standard, dull as it looks, sits at the center of streaming revenue.
It’s worth being precise about the division of labor, because it’s a frequent source of confusion. SCTE-35 does not choose an ad, does not know your fill rate, and does not measure anything — it is purely the signaling layer. The ad decision server chooses; the SSAI or SGAI engine stitches or sequences; the player or measurement layer counts. SCTE-35’s only job is to make the opportunity unambiguous and precisely timed so those systems can do theirs. When operators say “our SCTE-35 is broken,” the real fault is almost always one layer up or down — a mismatched HLS tag, a dropped PID, or an ad server timeout — while the cue itself was fine. Understanding that boundary is what makes SCTE-35 problems fast to diagnose instead of a guessing game across four vendors.
Common SCTE-35 implementation pitfalls
- PTS / segment-boundary misalignment — cues that don’t land on a segment boundary cause visible glitches; packagers often snap or insert a keyframe to fix this.
- Lost cue PID on ingest — transcoding or repackaging that drops the SCTE-35 PID silently kills monetization; verify pass-through end to end.
- Tag mismatch with the SSAI provider — sending #EXT-X-CUE-OUT when the provider expects #EXT-X-DATERANGE means the break never fires.
- Missing discontinuity handling — without proper discontinuity signaling, players stumble at the content-to-ad transition.
Delivering SCTE-35 cleanly with 5centsCDN
SCTE-35 only works if the markers survive the whole delivery path and land as the right manifest tags for your ad system. 5centsCDN supports SCTE-35 pass-through, CDN-level marker insertion when your ingest doesn’t carry cues, and SSAI-ready HLS output — across live, linear, and VOD. If you’re planning ad-supported delivery, our team can help you set it up. For the hands-on configuration steps, see our SCTE-35 support & SSAI implementation guide.
Frequently asked questions
What is SCTE-35 in simple terms?
SCTE-35 is a signaling standard that marks where ad breaks, program boundaries, and blackouts occur in a video stream. It doesn’t contain the ad itself — it’s a cue that tells downstream systems when to act.
What is the difference between splice_insert and time_signal?
splice_insert marks a specific splice with a precise timestamp and duration — the classic ad in/out. time_signal marks a moment and, combined with segmentation descriptors, expresses richer intent like a provider ad pod, chapter, or blackout. time_signal is preferred in modern OTT workflows.
Where do SCTE-35 markers live in a stream?
In MPEG-TS, cues ride in-band on their own PID. For playback, they’re translated into manifest-level markers: HLS tags like #EXT-X-CUE-OUT or #EXT-X-DATERANGE, and DASH EventStreams inside a Period.
What are segmentation descriptors and UPIDs?
A segmentation_descriptor adds meaning to a cue: a type ID (ad, chapter, blackout), a duration, a unique event ID, and a UPID that the ad server maps to a campaign or rule. They’re what let ad systems select the right ad and report on it accurately.
Does SCTE-35 work for both live and VOD?
Yes. It began live-centric, but modern workflows support SCTE-35 in VOD manifests and during packaging for SSAI and targeted ad logic.
How does SCTE-35 relate to SSAI?
SCTE-35 marks the ad opportunity; SSAI acts on it — reading the cue, calling an ad decision server, and stitching the ad into the stream. Clean SCTE-35 signaling is a prerequisite for reliable server-side ad insertion.
What is #EXT-X-DATERANGE and why is it preferred?
#EXT-X-DATERANGE is a standards-track HLS tag defined in RFC 8216 that carries the cue ID, start time, and raw payload. Because it’s part of the HLS spec itself, it’s the most portable option for new deployments.
Can a CDN insert SCTE-35 markers if my encoder doesn’t?
Yes. When the source stream has no SCTE-35 cues, marker insertion can happen at the CDN or packaging layer based on a schedule or manual trigger, so you can still monetize through downstream ad systems.