Expect: 100-continue in curl (tested)
If a large curl upload is about 1 second slower than it should be, Expect: 100-continue is the usual cause. We measured exactly when curl 8.14.1 sends it, how long it waits, how to turn it off, and what other clients do.
1. What Expect: 100-continue does
The client sends the request headers with Expect: 100-continue and then pauses before the body. The server can answer HTTP/1.1 100 Continue ("send it"), or a final status like 401 or 413 ("don't bother"). This saves uploading a large body that would be refused anyway. If the server says nothing, the client gives up waiting after a timeout and sends the body anyway.
2. When curl 8.14.1 adds the header
| Request (HTTP/1.1, plain http) | Expect sent? | Total time, server ignores Expect |
|---|---|---|
--data-binary 1,024 / 1,025 bytes | No | 0.001 s |
--data-binary 1,048,576 bytes (exactly 1 MiB) | No | 0.005 s |
--data-binary 1,048,577 bytes | Yes | 1.004 s |
--data-binary 5,000,000 bytes | Yes | about 1.05 s |
-F file=@ 5 MB (multipart) | Yes | 1.047 s |
-T 5 MB file (PUT) | Yes | 1.025 s |
-T - or --data-binary @- from stdin, 5 MB, chunked | Yes | 1.053 s |
Any size with -0 (HTTP/1.0) | No | 0.022 s for 5 MB |
1,024 bytes with -H 'Expect: 100-continue' | Yes (forced) | 1.001 s |
So in curl 8.14.1 the threshold is a body larger than 1 MiB (1,048,576 bytes), not the 1,024 bytes many older answers mention. Older curl versions used a much lower limit, so if you see the header on small uploads, check curl --version.
With the server ignoring the header, curl's verbose output shows the wait:
> Expect: 100-continue
>
* Done waiting for 100-continue
* upload completely sent off: 5000000 bytes
< HTTP/1.1 200 OK
3. How to disable it (or shorten the wait)
# remove the header: body is sent right away
curl -H 'Expect:' --data-binary @big.bin https://example.com/upload
# keep the header but wait less (seconds, decimals allowed)
curl --expect100-timeout 0.2 --data-binary @big.bin https://example.com/upload
Measured with a 5 MB body and a server that ignores Expect: default 1.05 s, --expect100-timeout 0.2 0.247 s, -H 'Expect:' 0.094 s. An empty Expect: header tells curl to drop the header completely; the server log showed no Expect line at all. In PHP and other libcurl bindings the same trick is setting the header list entry Expect: (doc-based, same libcurl mechanism, not tested here).
4. When the server does answer
- 100 Continue: curl sent the body right after it. A 5 MB POST took 0.085 s, no delay.
- 413 before the body: curl stopped, printed status 413, and
%{size_upload}was 0. No body bytes were sent. This is the whole point of the header: a size or auth check can fail fast. - 417 Expectation Failed: curl 8.14.1 returned the 417 with 0 bytes uploaded. It did not retry without the header in our test. Re-run with
-H 'Expect:'.
If your server reads the request headers and then waits for the body without ever replying 100, every big curl upload pays the 1 second timeout. Most real HTTP servers answer 100 Continue automatically; a hand-written socket server or some proxies may not.
5. Other clients
| Client (5 MB POST) | Sent Expect? | Time |
|---|---|---|
| Python requests 2.32.3 | No | 0.023 s |
| Python urllib.request (3.13) | No | 0.033 s |
| Node 24.21.0 fetch (undici) | No | 0.080 s |
Node 24.21.0 http.request with Expect: 100-continue set by hand | Yes | 0.028 s (body sent from the 'continue' event) |
None of these added the header on their own, so the 1 second delay is mostly a curl and libcurl issue. In Node's http module, when you set the header yourself you must send the body in the req.on('continue', ...) handler.
6. Related
A body that is too large is often rejected by a size limit, and request header limits are a separate thing: see HTTP header size limits. For how the body length is signalled, see Transfer-Encoding chunked vs Content-Length and Content-Length mismatch errors. To see what a server sends back, use the free HTTP headers checker.
Frequently asked questions
When does curl send Expect: 100-continue?
In curl 8.14.1, for HTTP/1.1 uploads with a body larger than 1 MiB (1,048,576 bytes); a 5 MB chunked upload from stdin also got it (a tiny one did not). A 1,048,576-byte POST had no Expect header; 1,048,577 bytes did. It also applied to -F multipart and -T PUT uploads.
Why is my curl upload 1 second slow?
curl sent Expect: 100-continue and the server never replied 100 Continue, so curl waited its default 1 second before sending the body. In our test a 1,048,577-byte POST took 1.004 s versus 0.005 s for 1,048,576 bytes.
How do I disable Expect: 100-continue in curl?
Add -H 'Expect:' (an empty value). curl then removes the header and sends the body at once. A 5 MB POST went from 1.05 s to 0.094 s against a server that ignored Expect.
What does --expect100-timeout do?
It sets how long curl waits for 100 Continue before sending the body anyway. With --expect100-timeout 0.2 a 5 MB POST took 0.247 s instead of 1.05 s.
Do Python requests or Node fetch send Expect: 100-continue?
No. Python requests 2.32.3, Python urllib (3.13) and Node 24.21.0 fetch sent 5 MB bodies without an Expect header and with no delay.
Written with AI assistance. Measured on 2026-10-01 with curl 8.14.1 (Debian, libcurl 8.14.1) against a raw Python 3.13 socket server on 127.0.0.1 that logs request headers and either ignores Expect, answers 100 Continue, or rejects with 413/417 before reading the body. Also checked Python requests 2.32.3, Python urllib (3.13) and Node 24.21.0 fetch (undici) and http.request. nginx was not available on the test box and was not tested. PlainHeaders is our extension; the other methods are free.