HTTP/2 frame header (9 bytes fixed)
Length
24 bit
Type
8 bit
Flags
8 bit
Stream ID
31 bit
Payload (0 to max frame size, default 16 KB)
Stream ID 0 = connection-level. Client streams: odd IDs (1,3,5…). Server push: even IDs (2,4…).
Frame types
| Type | Purpose | Stream 0? |
| HEADERS | HTTP request/response headers — HPACK compressed | No |
| DATA | Request/response body — actual payload bytes | No |
| SETTINGS | Connection config — max streams, window size | Yes |
| WINDOW_UPDATE | Flow control — increase receive buffer | Both |
| RST_STREAM | Abort one stream without killing connection | No |
| PING | RTT measurement / keepalive | Yes |
| GOAWAY | Graceful shutdown — last processed stream ID | Yes |
| PUSH_PROMISE | Server announces incoming push on new stream | No |
| PRIORITY | Stream dependency + weight for scheduling | No |
Wire — 3 streams multiplexed
Frames on the wire — stream IDs interleaved
SETTINGS [s:0]
HEADERS [s:1] GET /
HEADERS [s:3] GET /css
HEADERS [s:5] GET /js
DATA [s:1] END
DATA [s:3] END
DATA [s:5] part 1
DATA [s:5] part 2
DATA [s:5] END
Stream 5 (large JS) splits across 3 DATA frames. Streams 1 and 3 finish first. Client reassembles each stream independently using stream ID.
HPACK header compression
# HTTP/1.1 — sends full headers every request (~400 bytes)
GET /api/users HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X...)
Accept-Encoding: gzip, deflate, br
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Cookie: session=abc123; theme=dark
# HTTP/2 — first request: sends full headers once
# Subsequent requests: only send what changed
:method GET :path /api/users/42 ← ~50 bytes
(Host, UA, Auth, Cookie all indexed — not resent)
HTTP/2 vs HTTP/3 key differences
| Aspect | HTTP/2 | HTTP/3 |
| Transport | TCP | QUIC (UDP) |
| Header compression | HPACK | QPACK (stateless per stream) |
| Stream independence | No — TCP HOL | Yes — QUIC streams |
| Encryption | TLS 1.3 over TCP | TLS 1.3 inside QUIC |
| Handshake cost | TCP (1.5RTT) + TLS (1RTT) | QUIC 1RTT or 0-RTT |
| Connection ID | No — IP:port pair | Yes — 64-bit opaque ID |