Huffman Coding
HPACKRFC 7541HPACK uses a static Huffman code (RFC 7541 Appendix B) to compress header string values. The Huffman table is fixed – the same for every HTTP/2 connection in the world – and was generated from a large corpus of HTTP/1.1 headers. Common characters like lowercase letters get short codes; rare characters get long codes. Huffman-encoded strings are 20-30% shorter than ASCII for typical HTTP headers. The first bit of the string length field indicates Huffman encoding (H bit = 1).
Details
HPACK's Huffman code is a static canonical Huffman table derived from HTTP/1.1 traffic statistics.
Fixed table: Unlike adaptive Huffman coding, HPACK's table never changes per-connection. Both endpoints know it from the RFC. No dynamic probability model is maintained.
H bit: When encoding a header string, the encoder sets the H (Huffman) bit in the string prefix byte if Huffman encoding is used. The decoder checks this bit. If H=0, the string is plain ASCII. If H=1, decode as Huffman.
When Huffman is beneficial: Header values consisting primarily of lowercase ASCII letters (like domain names, paths, common values) compress well. Numbers and uppercase letters get longer codes in some cases. A well-implemented encoder checks whether Huffman encoding actually reduces size before applying it.
Huffman code examples (from RFC 7541 Appendix B): 'e' = 0000 (4 bits, most common) 'a' = 0001 0 (5 bits) 't' = 0001 11 (6 bits) ' ' (space) = 0001 000 (7 bits) 'A' = 111 1110 00 (9 bits, uppercase, less common) ':' = 0111 (4 bits) '/' = 0000 11 (6 bits) 'z' = 1111 1110 011 (11 bits, rare letter)
EOS symbol: The EOS (end-of-string) symbol has the code 0x3fffffff (30 bits, all ones). Used to pad the last byte of a Huffman-encoded string to a full byte boundary.
Huffman + dynamic table: These two techniques combine. A header value is Huffman-encoded on first occurrence, then added to the dynamic table. Future references use a 1-byte index instead of the Huffman-encoded string.
Wire example
# Huffman encoding of "www" (common URL prefix) # Huffman codes from RFC 7541 Appendix B: # 'w' = 1111 1010 (8 bits = 0xFA) # "www" = FA | FA | FA = 3 bytes # ASCII "www" = 77 77 77 = 3 bytes # (no saving for "www" specifically, but longer strings compress significantly) # Huffman encoding of "gzip" (Accept-Encoding value): # g = 0110 0110 (8 bits) # z = 1111 1110 011 (11 bits) -- padded with EOS bits # i = 0110 1011 (8 bits) # p = 1010 0000 (8 bits) # ASCII "gzip" = 4 bytes; Huffman "gzip" ≈ 3.5 bytes (rounded up to 4) # Huffman-encoded string in HEADERS frame: # String length byte with H bit set: 86 # 0x86 = H=1, length=6 62 9c bf ... # Huffman-encoded bytes for "api.example.com" (15 ASCII chars → ~12 bytes)