How HTTP Works
4xx · Client error
< HTTP/1.1 411 Length Required

411 Length Required: Why It Happens

411 Length Required: the server wants a Content-Length and got chunked or none. Fix it in curl, Node, Python and fetch, and on nginx and Google Frontend.

Reviewed 3 min readintermediate4 sourcesTry itMarkdown
Cacheable
Only with explicit freshness
Retry?
Yes, with a Content-Length header
Usually sent by
Web server or proxy
Spec
RFC 9110 §15.5.12
On this page

TL;DR: 411 means the server (or a proxy in front of it) refuses a request body unless it comes with a Content-Length. The usual triggers are chunked uploads and empty POSTs with no Content-Length: 0. Send an explicit length, or move to HTTP/2.

What it means

An HTTP/1.1 request body is delimited either by Content-Length or by Transfer-Encoding: chunked (RFC 9112 §6). Many servers handle both. Some refuse chunked requests, some require a length for specific methods, some want it to enforce size limits before reading. RFC 9110 §15.5.12 lets them answer 411.

PUT /uploads/video.mp4 HTTP/1.1
Host: storage.example.com
Transfer-Encoding: chunked

HTTP/1.1 411 Length Required
Content-Length: 0
Connection: close

The cases people actually hit

1. Empty POST with no length. curl -X POST https://api.example.com/jobs/42/cancel sends no body and no Content-Length. Some stacks do not infer zero and answer 411. Google Frontend’s HTML error is the best-known version:

411. That's an error.
POST requests require a Content-length header. That's all we know.

Fix it with -d '' or -H 'Content-Length: 0'.

2. Chunked upload to something that cannot take chunks. Any HTTP client that streams a body of unknown size on HTTP/1.1 switches to Transfer-Encoding: chunked. Examples: piping stdin to curl (cat file | curl -T - ...), passing a generator to Python requests, piping a stream into Node’s http.request without a length, or fetch with a ReadableStream body (which requires duplex: 'half'). Targets that answer 411: S3 (MissingContentLength, “You must provide the Content-Length HTTP header”), older nginx versions in front of an app, some CDNs and WAFs, and many reverse proxies in front of legacy endpoints.

3. A proxy that buffers or strips. A gateway converts HTTP/2 or HTTP/3 to HTTP/1.1, the client had no length, and the next hop refuses chunked.

4. WAF or API gateway policy. Some gateways require a declared length so they can reject oversized bodies before reading them.

Fix it

Give the length, which means knowing it before sending:

# curl: let it measure the file
curl -T video.mp4 https://storage.example.com/uploads/video.mp4
curl --data-binary @payload.json -H 'Content-Type: application/json' https://api.example.com/v1/events

# stdin forces chunked; avoid, or force the length yourself
cat payload.json | curl -X POST --data-binary @- https://api.example.com/v1/events   # curl reads all of stdin first
import requests, os

# generator body -> chunked -> 411 on strict servers
# requests.put(url, data=chunks())

# file object: requests sets Content-Length from the file
with open("video.mp4", "rb") as f:
    requests.put(url, data=f)
import { request } from 'node:http'
import { createReadStream, statSync } from 'node:fs'

const size = statSync('video.mp4').size
const req = request(
  { host: 'storage.example.com', method: 'PUT', path: '/uploads/video.mp4',
    headers: { 'Content-Length': size } },
  (res) => console.log(res.statusCode)
)
createReadStream('video.mp4').pipe(req)

If the body size really is unknown (a live stream, a computed archive), options are: buffer to disk or memory to learn the size, use S3 multipart upload (each part has a known size), or talk HTTP/2 to the endpoint.

If you operate the server

nginx has accepted chunked request bodies since 1.3.9, so a 411 from an up-to-date nginx is rare and normally comes from an app behind it. When nginx proxies to an upstream that cannot take chunked requests, proxy_request_buffering on; (the default) makes nginx read the whole body and forward it with a Content-Length. If you have set proxy_request_buffering off; for streaming, that is where chunked starts reaching the upstream.

location /uploads/ {
    proxy_pass http://legacy_backend;
    proxy_request_buffering on;   # default; buffers and sets Content-Length
    client_max_body_size 100m;
}

Reproduce it

curl -v -X POST -H 'Transfer-Encoding: chunked' -d 'hello' https://api.example.com/v1/events
# > Transfer-Encoding: chunked
# < HTTP/1.1 411 Length Required

Frequently asked questions

What does 411 Length Required mean?

The server insists on knowing the size of the request body up front, via a Content-Length header, and your request did not provide one. This usually happens with Transfer-Encoding: chunked uploads or with POST/PUT requests that carry no body and no Content-Length: 0.

How do I fix 411 in curl?

For a POST with no body, send -d "" or -H "Content-Length: 0". For uploads, use --data-binary @file or -T file, which let curl compute the length, rather than piping from stdin, which makes curl fall back to chunked encoding.

Why do I get "POST requests require a Content-length header" from Google?

Google Frontend, which fronts Google Cloud services and many Google APIs, answers 411 with that text when a POST or PUT arrives with neither a body length nor chunked encoding, typically an empty POST sent without Content-Length: 0.

Does HTTP/2 need Content-Length?

No. HTTP/2 frames carry the data and mark the end of the stream, so there is no chunked encoding and a length header is optional. A 411 therefore points to an HTTP/1.1 hop, often a proxy or origin that is not HTTP/2-aware, converting the request.

Should my own API return 411?

Only if you cannot stream the body, for example because you must validate the size before accepting it. Otherwise rely on a body-size limit and return 413 when it is exceeded.

Sources

  1. MDN Web Docs: 411 Length Requireddeveloper.mozilla.org
  2. RFC 9110 Section 15.5.12: 411 Length Requiredrfc-editor.org
  3. RFC 9112 Section 6: Message Body Lengthrfc-editor.org
  4. Amazon S3 error responses: MissingContentLengthdocs.aws.amazon.com

Keep going

Browse /search