MoQT explained
The MoQT SUBSCRIBE message
A SUBSCRIBE in Media over QUIC Transport is not a one-shot GET —
it is a standing request for a track. Its structure answers three questions:
which track (Track Namespace + Track Name), from where
(the Location Filter), and how (Forward, Subscriber Priority, Group Order — all
carried as parameters). The relay
replies with exactly one SUBSCRIBE_OK
or REQUEST_ERROR,
and objects then flow on their own streams.
Field layout below reflects draft-ietf-moq-transport-18 and
-19. For byte-exact ordering in one draft, see the
message-type reference.
SUBSCRIBE fields
| Field | Type | What it does |
|---|---|---|
| Request ID | varint · body | Client-assigned identifier for this request. The SUBSCRIBE_OK / REQUEST_ERROR, later REQUEST_UPDATEs, and teardown are all keyed to it. draft-19 allows several concurrent subscriptions to one track, each with its own Request ID. |
| Track Namespace | tuple · body | Ordered tuple of byte-string components identifying the namespace, e.g. ["sports","live"]. |
| Track Name | bytes · body | Byte string naming the specific track within the namespace, e.g. "video". Matched exactly. |
| Subscriber Priority | param · 0x20 | SUBSCRIBER_PRIORITY parameter. How this subscription ranks against the subscriber’s other subscriptions on the same connection. Lower value = higher priority (0 is highest). |
| Group Order | param · 0x22 | GROUP_ORDER parameter. Requested delivery order: Ascending (0x1, oldest-first) or Descending (0x2, newest-first). SUBSCRIBE_OK reports what was actually chosen. |
| Forward | param · 0x10 | FORWARD parameter. Initial Forward State: 1 = deliver objects now; 0 = establish the subscription but send no objects until flipped with REQUEST_UPDATE. |
| Location Filter | param · 0x21 | LOCATION_FILTER parameter (named SUBSCRIPTION_FILTER before draft-19). Where in the track to start: Largest Object, Next Group Start, AbsoluteStart, or AbsoluteRange (see below). Absolute filters carry explicit Group/Object location fields. |
| Other parameters | KVP[] | Authorization Token (0x03), delivery-timeout parameters, and — in draft-19 — Range Filter parameters (0x25–0x29) that further restrict which objects pass. |
Only Request ID, Track Namespace and Track Name are
fixed fields in the message body. Since draft-15, Subscriber Priority, Group
Order, Forward and the filter are carried as parameters (draft-13/14 had them as fixed
fields), and the Track Alias is assigned by the publisher in
SUBSCRIBE_OK — it is not sent in SUBSCRIBE.
The two identifiers people most often confuse are Track Namespace vs Track Name. The namespace is a tuple that groups tracks; the name addresses one track inside it.
The Filter Type: where delivery starts
The filter is the most consequential field. It answers from which point in the track do I want objects? — in terms of groups, because a group boundary is the only safe place to start decoding.
| Filter | Code | Start location | End | Use it when |
|---|---|---|---|---|
| Largest Object | 0x2 | {Largest.Group, Largest.Object + 1} | open | Join a live track now and get everything from here on |
| Next Group Start | 0x1 | {Largest.Group + 1, 0} | open | Join live at the next clean group boundary (next IDR) |
| AbsoluteStart | 0x3 | explicit {Group, Object} | open | Everything from a known point forward |
| AbsoluteRange | 0x4 | explicit {Group, Object} | explicit End Group | A bounded window of the track |
The filter travels in the LOCATION_FILTER parameter (0x21) — renamed from
SUBSCRIPTION_FILTER in draft-19. The 0x2 /
0x1 filter names have been Largest Object / Next Group Start
since well before draft-17 (much older drafts called 0x2 Latest Object).
draft-19 adds five Range Filter parameters (0x25–0x29) that further restrict which objects within
the range are delivered. The full filter walkthrough is in
How MoQT subscriptions work.
A SUBSCRIBE, sketched
SUBSCRIBE (Type 0x3)
Request ID = 4
Track Namespace = ["sports","live","game42"]
Track Name = "video"
Parameters:
SUBSCRIBER_PRIORITY (0x20) = 0
GROUP_ORDER (0x22) = Ascending (0x1)
FORWARD (0x10) = 1
LOCATION_FILTER (0x21) = Next Group Start (0x1)
DELIVERY_TIMEOUT = 2000ms
─► SUBSCRIBE_OK (Type 0x4)
Track Alias = 1
Group Order = Ascending
Largest Location = {group 812, object 4}
Expires = 0 How SUBSCRIBE changed across drafts
draft-15 Moved Subscriber Priority, Group Order, Forward, and the Filter out of fixed SUBSCRIBE fields and into parameters (draft-13/14 carried them as fixed fields). From here on the SUBSCRIBE body is just Request ID + Track Namespace + Track Name + Parameters, and the Track Alias is assigned by the publisher in SUBSCRIBE_OK.
draft-17 Added a Required Request ID Delta field to every request message, including SUBSCRIBE.
draft-18 Removed Required Request ID Delta again (every request is one byte shorter). Split namespace subscription into SUBSCRIBE_NAMESPACE + SUBSCRIBE_TRACKS.
draft-19 Added Range Filter parameters (SUBGROUP_FILTER 0x25, OBJECTID_FILTER 0x26, PRIORITY_FILTER 0x27, OBJECT_PROPERTY_FILTER 0x28, TRACK_PROPERTY_FILTER 0x29) that select which objects within the subscription pass. Renamed the SUBSCRIPTION_FILTER parameter to LOCATION_FILTER (0x21). Allowed multiple concurrent subscriptions to the same track.
Full per-draft diffs: draft-18 changes and draft-19 changes.
Frequently asked questions
What is the structure of the MoQT SUBSCRIBE message?
What is the difference between Track Namespace and Track Name in a SUBSCRIBE?
How did the SUBSCRIBE message change in draft-18 and draft-19?
What are the MoQT subscription filter types?
What does the relay send back to a SUBSCRIBE?
Related
- Track Namespace vs Track Name
- SUBSCRIBE_NAMESPACE and track namespace prefix matching
- How MoQT subscriptions work: filters, forwarding, and lifecycle
- MoQT message-type reference (field-level detail)
- MoQT spec — the SUBSCRIBE message (draft-19, normative text)
- Subscribing to tracks — hands-on guide
Decode SUBSCRIBE on the wire
moqtap shows the exact filter, forward state, priority, and Largest Location your implementation sent and received — so you can see whether a stalled subscription is your filter, your auth, or the publisher.