Back to results for “Streams & Buffers”
Node.js › HTTP & Web Servers

What is the purpose of the Content-Length and Transfer-Encoding: chunked headers, and why can't a response use both simultaneously?

Intermediate

Answer

Content-Length tells the client exactly how many bytes to expect in the response body, requiring the server to know the complete size upfront before sending anything. Transfer-Encoding: chunked instead sends the response in a series of independently-sized chunks without needing to know the total size in advance, letting the server begin sending data before it's finished generating the complete response -- the two are mutually exclusive because Content-Length promises an exact total size, which is fundamentally incompatible with a chunked response whose total length isn't known until the last chunk is sent.
// Content-Length: server knows the exact size upfront
const body = JSON.stringify(data);
res.writeHead(200, { 'Content-Length': Buffer.byteLength(body) });
res.end(body);

// Transfer-Encoding: chunked (Express sets this automatically when streaming
// without an explicit Content-Length, via multiple res.write() calls)
res.write(chunk1);
res.write(chunk2);
res.end();
Real-world example A streaming report-generation endpoint necessarily uses chunked transfer encoding (by simply calling res.write() multiple times without setting Content-Length) since the total size of the generated report genuinely isn't known until the entire generation process has finished.

Common follow-ups: What happens if a server mistakenly sends both a Content-Length header and uses chunked encoding at the same time?;How does HTTP/2 handle the concept of framing data differently, given it doesn't actually use chunked transfer encoding the way HTTP/1.1 does?