Transfer-EncodingTransfer-Encoding is a hop-by-hop header specifying the encoding applied to safely transfer the message body over the network. Its main value, `chunked`, splits the body into size-prefixed pieces and enables streaming when the total size isn't known in advance.
`chunked` breaks the body into chunks, each prefixed with a hexadecimal size, ending with a zero-size chunk. This lets a server start streaming before the whole response is ready and express message boundaries without Content-Length for dynamic content whose size can't be precomputed. So when you use chunked you don't use Content-Length (they are mutually exclusive).
This is fundamentally different from the end-to-end Content-Encoding. Transfer-Encoding is merely the transfer format between two adjacent nodes, so a proxy may reassemble chunks and forward with a different framing to the next hop. Consequently caches and ETags are unaffected by Transfer-Encoding.
In HTTP/1.1, when Content-Length and Transfer-Encoding both appear in one message, servers and proxies may disagree on which delimits the body — the classic HTTP request smuggling vulnerability. HTTP/2 and HTTP/3 use a different framing and forbid chunked Transfer-Encoding entirely.
Transfer-Encoding: <coding>[, <coding>]* (chunked | gzip | ...)e.g. Transfer-Encoding: chunked
chunked | Sends the body as size-prefixed chunks; for streaming or unknown length. The final chunk has size 0. |
gzip | gzip-compress the body for transfer (hop-by-hop). |
compress | Legacy LZW compression (rarely used). |