Content-Length

The HTTP Content-Length header indicates the size of the message body in bytes, appearing in both requests and responses.

Usage

The Content-Length header communicates the exact byte size of the HTTP message body. Clients rely on this value to know when a response has been fully received, making the connection available for reuse in persistent connections under HTTP/1.1.

When a server sends a response with a known body size, the Content-Length header allows the client to allocate the right amount of memory and display accurate progress indicators during downloads. A mismatch between the declared length and the actual body size signals a truncated or corrupted transfer.

This header is mutually exclusive with chunked Transfer-Encoding. When a server streams a response of unknown size, chunked encoding replaces a fixed content length. Under HTTP/2 and HTTP/3, framing handles message boundaries at the protocol level, but Content-Length remains valid for body size validation.

The value is a single non-negative integer representing the number of octets (bytes) in the message body.

Example

A server returns a 3,495-byte JSON response. The client reads exactly 3,495 bytes before considering the message complete.

Content-Length: 3495

A POST request sends a form body. The Content-Length header tells the server how many bytes to expect in the request body.

POST /submit HTTP/1.1
Host: example.re
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

field=value&other=something

A response using chunked transfer encoding omits the Content-Length header entirely. The Transfer-Encoding header takes precedence.

Transfer-Encoding: chunked

Troubleshooting

Transfer failures and connection errors often trace back to an incorrect or conflicting Content-Length value.

  1. Transfer interrupted or partial download. The client receives fewer bytes than Content-Length declares and reports a truncated response. Common causes: the origin closes the connection early, a proxy timeout cuts the transfer, or the server miscalculates the body size. Run curl -v https://example.re/file and compare the Content-Length header value with the actual bytes received (shown in the transfer summary). A mismatch confirms the issue.

  2. Chunked encoding and Content-Length both present. Sending both Transfer-Encoding: chunked and Content-Length in the same response violates the HTTP specification. Clients must ignore Content-Length when Transfer-Encoding is present, but not all implementations follow this rule. Remove Content-Length when using chunked encoding. In nginx, chunked encoding is applied automatically when the body size is unknown, and nginx omits Content-Length in that case. Custom application code or middleware that sets both headers needs correction.

  3. Content-Length wrong after middleware modifies the body. Middleware that injects content (analytics scripts, security tokens, debug toolbars) changes the body size without updating Content-Length. The browser either truncates the visible content or waits for bytes that never arrive. Move Content-Length calculation to the final stage after all body modifications complete. In Express.js, the compression middleware handles this automatically. In custom setups, remove Content-Length and rely on chunked encoding instead.

  4. HEAD response carries wrong Content-Length. A HEAD response must include the same Content-Length the corresponding GET response would carry, but with no body. Some frameworks generate HEAD responses with a Content-Length of 0 or omit the header entirely. Verify by comparing curl -I https://example.re/resource (HEAD) with curl -s -o /dev/null -w '%{size_download}' https://example.re/resource (GET body size). Mismatched values break download managers and caching proxies that rely on HEAD to determine resource size.

  5. Diagnosing Content-Length issues with curl. Run curl -v https://example.re/resource to see the Content-Length header and the transfer byte count in the verbose output. The line Content-Length: N shows the declared size. At the end, bytes received shows the actual transfer. Add -o /dev/null to discard the body and focus on headers. For compressed responses, remember that Content-Length reflects the compressed size, not the original size.

See also

Last updated: April 4, 2026