# Expect 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.

Source: https://howhttpworks.com/headers/expect
Last reviewed: 2026-10-04

> **TL;DR:** `Expect: 100-continue` lets a client send only the headers, wait for `100 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

```http
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
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
HTTP/1.1 401 Unauthorized
```

```http
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:

```bash
curl -v -T bigfile.bin https://api.example.com/upload
```

```text
> 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:

1. 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.
2. Tell curl not to send it:

```bash
curl -H 'Expect:' -T bigfile.bin https://api.example.com/upload
```

3. Keep the header but shorten the wait:

```bash
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
HTTP/1.1 417 Expectation Failed
```

A server or intermediary that does not implement the expectation answers with 417 (see [417](https://howhttpworks.com/status-codes/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-continue` should send `100 Continue` when it is willing to read the body, or a final status if it is not. In Go's `net/http` server 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](https://howhttpworks.com/status-codes/100).
- Size limits belong in the first response. Rejecting with [413](https://howhttpworks.com/status-codes/413) before the body arrives saves the upload; rejecting after is just wasted bandwidth.

## Related

- [100 Continue](https://howhttpworks.com/status-codes/100), [417 Expectation Failed](https://howhttpworks.com/status-codes/417), [413 Content Too Large](https://howhttpworks.com/status-codes/413), [POST](https://howhttpworks.com/methods/post)
