Draft Versions
Supported drafts
Section titled “Supported drafts”moqtap supports MoQT drafts 07 through 20. Draft-20 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; uses SUBSCRIBE_ANNOUNCES instead of SUBSCRIBE_NAMESPACE |
| 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 | Introduces message framing changes |
| draft-17 | ALPN moqt-17 | Unified SETUP message, consolidated response pattern |
| 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 | Latest — 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) |
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-20 Section 3.1, 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-20 is moqt-20.
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 draft-14 → unified SETUP (0x2F00) in draft-17 |
| Response pattern | Per-message error types (e.g., SUBSCRIBE_ERROR, FETCH_ERROR) in draft-14 → consolidated REQUEST_OK / REQUEST_ERROR in draft-17 |
| Message names | SUBSCRIBE_UPDATE → REQUEST_UPDATE; SUBSCRIBE_ERROR → REQUEST_ERROR; 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: 0x40 in early drafts, 0x20 in draft-14, part of SETUP 0x2F00 in draft-17) |
| Feature availability | FETCH didn’t exist in early drafts; PUBLISH is new in draft-14; PUBLISH_BLOCKED and NAMESPACE are new in draft-17 |
| Data streams | Object status codes changed (e.g., End of Group: 0x1 in draft-16, 0x3 in draft-17); subgroup stream header uses bitfield flags in draft-17 |
| Namespace discovery | SUBSCRIBE_ANNOUNCES in draft-07 → SUBSCRIBE_NAMESPACE in draft-14+ |
| Error codes | Code values and meanings have shifted |
Multi-draft support across tools
Section titled “Multi-draft support across tools”| Tool | Drafts supported | How |
|---|---|---|
| moqtap CLI | 07–20 | --draft flag; auto-detection in peek mode |
| Browser Extension | 07–20 | Auto-detects draft from CLIENT_SETUP wire bytes |
| @moqtap/codec (JS) | 07–20 | Subpath imports: @moqtap/codec/draft07 through @moqtap/codec/draft20 |
| moqtap-codec (Rust) | 07–20 | Feature flags: draft07..draft20, all-drafts (default) |
| moqtap-client (Rust) | 07–20 | Feature flags: draft07..draft20, 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.