Request header
> Expect: 100-continueExpect Header: 100-continue, curl Delays and 417
Expect: 100-continue asks the server to approve a request before the body is sent. Why curl adds it past 1 MB, the 1s delay, -H "Expect:", and 417.
- Direction
- Request
- Category
- Connection management
- Spec
- RFC 9110 §10.1.1
- JS can set it
- No: forbidden header name
On this page
TL;DR:
Expect: 100-continuelets a client send only the headers, wait for100 Continue(or a final error) from the server, and then send the body. curl adds it by itself for HTTP/1.1 bodies over 1 MiB or of unknown size and waits one second for the answer, which is the classic “uploads stall for exactly 1s” bug.-H 'Expect:'turns it off.
The exchange
PUT /videos/42 HTTP/1.1
Host: origin.example.com
Content-Type: video/mp4
Content-Length: 734003200
Expect: 100-continue
If the server accepts the headers (auth passed, size acceptable):
HTTP/1.1 100 Continue
and the client then sends the 700 MB body. If not, the server answers with a final status right away and the client never sends the body:
HTTP/1.1 401 Unauthorized
HTTP/1.1 413 Content Too Large
That is the whole point: failing fast before a large upload. RFC 9110 section 10.1.1 defines the field and section 15.2.1 the interim response. The client must not wait forever; it sends the body after a timeout, because a server may not support the mechanism.
The one-second delay in curl
From the libcurl source, EXPECT_100_THRESHOLD is 1024 * 1024, and the header is added when the request body is larger than that or its length is unknown. It applies only to HTTP/1.1. curl then waits for the interim response, one second by default:
curl -v -T bigfile.bin https://api.example.com/upload
> PUT /upload/bigfile.bin HTTP/1.1
> Host: api.example.com
> Content-Length: 5242880
> Expect: 100-continue
>
* Done waiting for 100-continue
If you see Done waiting for 100-continue followed by a roughly one-second gap, the hop in front of you did not send 100 Continue. Older curl releases used a smaller threshold, so a script that was fine on one machine can start stalling on another; check curl --version rather than assuming.
Fixes, in order of preference:
- Make the server side answer
100 Continue. Most current servers do, so a stall usually means a proxy, WAF or legacy appliance in between swallowing the header. - Tell curl not to send it:
curl -H 'Expect:' -T bigfile.bin https://api.example.com/upload
- Keep the header but shorten the wait:
curl --expect100-timeout 0.2 -T bigfile.bin https://api.example.com/upload
Other clients: .NET’s HttpClient has ExpectContinue on the request headers, and Go’s http.Transport has ExpectContinueTimeout.
417 Expectation Failed
HTTP/1.1 417 Expectation Failed
A server or intermediary that does not implement the expectation answers with 417 (see 417). Because 100-continue is the only expectation in common use, the cause is nearly always an old HTTP/1.0 proxy or server that rejects the header instead of ignoring it. The fix is the same: send Expect: empty, and the request goes through without the handshake.
Server and proxy side
- A server that sees
Expect: 100-continueshould send100 Continuewhen it is willing to read the body, or a final status if it is not. In Go’snet/httpserver this happens automatically the first time the handler reads the request body, so a handler that rejects before reading never sends the 100 and the client just gets the final response. - An intermediary may answer the 100 itself on behalf of the origin. RFC 9110 permits that, which means a 100 does not prove the origin accepted the request, only that the proxy did.
- A 100 is an interim response: the final status still follows after the body. See 100 Continue.
- Size limits belong in the first response. Rejecting with 413 before the body arrives saves the upload; rejecting after is just wasted bandwidth.
Related
Frequently asked questions
Why does my curl upload pause for one second?
curl sent Expect: 100-continue and is waiting for a 100 Continue interim response. By default it waits one second (--expect100-timeout), then sends the body anyway. A server or proxy that ignores the header causes exactly that pause. Disable the header with -H "Expect:" or raise nothing and fix the server.
When does curl send Expect: 100-continue automatically?
On HTTP/1.1 requests when the body is larger than 1 MiB, or when the size is unknown, for example chunked or streamed input. The cutoff is the EXPECT_100_THRESHOLD constant in libcurl source, currently 1024 * 1024 bytes. It is not sent for HTTP/2, and not for small bodies, so tiny POSTs never show the delay.
How do I stop curl sending Expect: 100-continue?
Pass an empty Expect header: curl -H "Expect:" ... removes the header entirely. In libcurl set CURLOPT_HTTPHEADER with "Expect:". You can also shorten the wait with --expect100-timeout 0.2 instead of removing it.
What does 417 Expectation Failed mean?
The server or an intermediary cannot meet the expectation in the Expect header. Today the only defined expectation is 100-continue, so a 417 usually comes from an old proxy or server that does not understand it. Remove the header and retry.
Do browsers send Expect: 100-continue?
MDN notes that none of the more common browsers send it, and it is a forbidden request header name for fetch and XMLHttpRequest, so page JavaScript cannot set it. It shows up from command-line tools and server-side HTTP clients.
Sources
Related
100 Continue
The server received the request headers and the client should proceed to send the body. Learn when and how to use 100 Continue for efficient large uploads.
HTTP POST Method: Complete Guide with Examples
Learn how the HTTP POST method works. Understand when to use POST requests, request bodies, form submissions, and API calls with practical examples.
413 Payload Too Large (Content Too Large): Causes and Fixes
413 Content Too Large (formerly Payload Too Large): find which layer rejected the upload and raise the limit in nginx, Apache, Cloudflare, Express and more.
417 Expectation Failed: Expect 100-continue
417 Expectation Failed means a server or proxy rejected your Expect header, usually Expect: 100-continue. Learn the causes and fixes for curl, .NET and Squid.