Draft Versions
Supported drafts
Section titled “Supported drafts”moqtap supports MoQT drafts 07 through 23. Draft-23 is the latest and most relevant version as of late 2026.
How a draft is identified on the wire changes partway through the range, so the table below has two different kinds of identifier in one column. See Version negotiation for why.
| Draft | Identified by | Notes |
|---|---|---|
| draft-07 | version 0xff000007 | Legacy; namespace discovery uses SUBSCRIBE_ANNOUNCES (as in drafts 08–12) |
| draft-08 – draft-13 | versions 0xff000008 – 0xff00000d | Intermediate drafts with incremental changes |
| draft-14 | version 0xff00000e | Widely deployed; separate CLIENT_SETUP / SERVER_SETUP. The last draft to carry a version number on the wire |
| draft-15 | ALPN moqt-15 | Transitional; CLIENT_SETUP loses its version list |
| draft-16 | ALPN moqt-16 | REQUEST_UPDATE replaces SUBSCRIBE_UPDATE; SUBSCRIBE_NAMESPACE gets its own stream and is answered with NAMESPACE / NAMESPACE_DONE |
| draft-17 | ALPN moqt-17 | Unified SETUP message; every request on its own bidirectional stream |
| draft-18 | ALPN moqt-18 | See the draft-18 changes post for breaking wire-format changes (Required Request ID Delta removed, SUBSCRIBE_NAMESPACE/SUBSCRIBE_TRACKS split, REDIRECT, FETCH delta encoding) |
| draft-19 | ALPN moqt-19 | See the draft-19 changes post for breaking wire-format changes (Range Filters added, Request ID removed from GOAWAY, DUPLICATE_SUBSCRIPTION error removed, multiple concurrent subscriptions per Track) |
| draft-20 | ALPN moqt-20 | See the draft-20 changes post for breaking wire-format changes (FETCH rewritten with Fetch Type removed and namespace/name inline, Joining FETCH replaced by fill fetch streams via FILL_PARAMETERS, PUBLISH_STATE_NOTIFY and INCLUDE_PROPERTIES added, Type becomes a validated Type Flags bitfield, Property registry codepoints reassigned) |
| draft-21 | ALPN moqt-21 | A restructure of draft-20 that changes nothing on the wire: every message, field and code point keeps its value, width and order. Only the section numbering (200 sections became 214) and the ALPN differ |
| draft-22 | ALPN moqt-22 | See the draft-22 changes post. One wire change: LOCATION_FILTER (0x21) carries an explicit Location Filter Type (0x00–0x05) that selects which fields follow, replacing the length-inferred encoding of draft-20 and draft-21. Under it a start of {0, 0} is absolute and the Next Object is type 0x05. Every other message, field and code point is unchanged from draft-21 |
| draft-23 | ALPN moqt-23 | Latest. Breaking wire-format changes: every control message’s Length becomes a variable-length integer, capped by the new MAX_CONTROL_MESSAGE_SIZE setup option; FETCH_OK is removed and FETCH is answered by REQUEST_OK; FORWARD (0x10) becomes PAUSED (0x11) with the meaning inverted; REQUEST_ERROR carries Error Details, among them REDIRECT; NAMESPACE gains parameters; fetch streams mark End of Group, End of Track and End of Gone Range. The error codes it adds, removes and renames are listed in the draft-23 error codes |
Version negotiation
Section titled “Version negotiation”MoQT negotiates its version two different ways, and draft-15 is the dividing line.
Drafts 07 – 14 — negotiated in the setup messages. Every draft in this range used
the constant ALPN moq-00 and settled the version afterwards, in-band:
- moqtap sends
CLIENT_SETUPcarrying a list of supported versions (0xff000007…0xff00000e) - The relay responds with
SERVER_SETUPselecting one of them - moqtap loads the version-specific codec for the selected version
Drafts 15 and later — negotiated before the first byte of MoQT. The draft number
moved into the transport’s own protocol negotiation, and the version field was deleted
from the setup messages: draft-15’s CLIENT_SETUP carries parameters and nothing else.
Per draft-23 Section 6.2, MoQT uses ALPN over raw QUIC and
WT-Available-Protocols over WebTransport, with the identifier formed by appending
the draft number to moqt- — so draft-23 is moqt-23.
There is therefore no 0xff0000NN version number on the wire from draft-15 onward.
A tool that reports one for a draft-15+ session is displaying a value it derived, not
one it observed. Where the negotiated identifier is not visible to it — a browser
extension cannot read the ALPN of a WebTransport connection — the honest answer is the
protocol string the application offered, not a synthesized version number.
The negotiated draft is displayed prominently in all moqtap tools — the CLI output and the browser extension’s DevTools panel.
What changes between drafts
Section titled “What changes between drafts”| Aspect | Example changes |
|---|---|
| Setup messages | Separate CLIENT_SETUP / SERVER_SETUP in drafts 07–16; one SETUP (0x2F00) sent by both sides in drafts 17–23 |
| Response pattern | Per-request OK and error messages (e.g., SUBSCRIBE_ERROR, FETCH_ERROR) in drafts 07–14; REQUEST_OK / REQUEST_ERROR from draft-15 (FETCH keeps FETCH_OK through draft-22) |
| Message names | SUBSCRIBE_UPDATE in drafts 07–15, REQUEST_UPDATE from draft-16; TRACK_STATUS is the response through draft-12 and the request from draft-13 |
| Message type IDs | IDs shift between drafts (e.g., CLIENT_SETUP is 0x40 in drafts 07–10 and 0x20 in drafts 11–16; SUBSCRIBE_NAMESPACE is 0x11 in drafts 13–17 and 0x50 in drafts 18–23) |
| Feature availability | PUBLISH exists from draft-12; NAMESPACE from draft-16; SUBSCRIBE_TRACKS from draft-18; PUBLISH_STATE_NOTIFY from draft-20 |
| Data streams | Object status 0x1 (Object Does Not Exist) exists only in drafts 07–15; End of Track is 0x4 from draft-11 |
| Namespace discovery | SUBSCRIBE_ANNOUNCES in drafts 07–12, SUBSCRIBE_NAMESPACE from draft-13 |
| Error codes | Code values and meanings shift between drafts; see the error code reference |
Multi-draft support across tools
Section titled “Multi-draft support across tools”| Tool | Drafts supported | How |
|---|---|---|
| moqtap CLI | 07–23 | --draft flag; auto-detection in peek mode |
| Browser Extension | 07–23 | Auto-detects draft from the setup message’s wire bytes |
| @moqtap/codec (JS) | 07–23 | Subpath imports: @moqtap/codec/draft07 through @moqtap/codec/draft23 |
| moqtap-codec (Rust) | 07–23 | Feature flags: draft07..draft23, all-drafts (default) |
| moqtap-client (Rust) | 07–23 | Feature flags: draft07..draft23, all-drafts (default) |
Adding new draft versions
Section titled “Adding new draft versions”moqtap’s codecs use a DraftVersion enum (Rust) or per-draft subpath exports (JS). Adding a new draft version is additive — implement the version-specific parser alongside existing ones. The version abstraction isolates draft-specific logic so existing drafts remain unaffected.