103 Early Hints
Informational response defined by RFC 8297.
Last updated July 27, 2026
Common causes at a glance
- A CDN or origin deliberately sending preload or preconnect hints before the final response
- Cloudflare Early Hints or a similar CDN feature enabled on the zone
- A framework emitting hints from a route's known critical assets
- Hints being stripped because an intermediary or the client negotiated HTTP/1.0
Reproduce it
curl -i --http1.1 https://www.example.com/What 103 Early Hints means
The point of 103 is to reclaim server think time. If your origin takes
200 ms to render a page, the browser spends that entire window idle because it has
not yet seen the HTML that references the stylesheet and font it needs. With 103 the
server can immediately emit the Link: </app.css>; rel=preload
headers it already knows about, and the browser fetches those subresources in
parallel with the origin’s work.
It is a pure optimisation. Nothing breaks if a client ignores it.
What the spec says
RFC 8297 defines 103 in a very short document. Two constraints
matter in practice. First, the hints are exactly that: hints. The final response is
not obliged to reference any of the hinted resources, and a client must not treat the
103 headers as the final response’s headers. Second, a server may send multiple 103
responses before the final one. The Link header itself and its
rel values are defined by RFC 8288 and the
HTML specification’s preload semantics.
What actually causes it
103 only appears when someone turned it on. The failure mode is not seeing it: HTTP/1.0 intermediaries, older reverse proxies, and any hop that buffers the whole response before forwarding will collapse the interim response away. Some CDNs generate hints automatically by learning which subresources a page loads, which means the hints can go stale after a deploy and point at hashed filenames that no longer exist. That costs a wasted request per hint rather than an error, but it is worth checking after a bundler upgrade changes your asset names.
How to debug it
curl shows interim responses in verbose mode, but the terse way to check is to grep the raw status lines:
curl -sv --http1.1 https://www.example.com/ 2>&1 | grep -E '^< (HTTP|link)'
A healthy result shows < HTTP/1.1 103 Early Hints with one or more
link: headers, then < HTTP/1.1 200 OK. In Chrome DevTools
the hinted requests appear to start before the document response completes, which is
the visible payoff.
Verify each hinted URL still resolves after a deploy — a preload for a hashed asset that 404s is wasted bandwidth. The header inspector is a quick way to see the final response’s headers side by side with the hints.
Working examples
curl
# Interim responses only show up in verbose output. HTTP/1.1 keeps it readable.
curl -sv --http1.1 https://www.example.com/ 2>&1 | grep -E '^< (HTTP|link)'
# Expected shape:
# < HTTP/1.1 103 Early Hints
# < link: </app.css>; rel=preload; as=style
# < HTTP/1.1 200 OK
Python (requests)
import requests
# requests drops 1xx responses, so early hints are invisible at this layer.
# To observe them, drop to http.client which exposes the interim response.
import http.client
conn = http.client.HTTPSConnection("www.example.com")
conn.request("GET", "/")
resp = conn.getresponse()
print(resp.status, resp.getheader("Link")) # final status; hints already consumed
# Practical check: confirm each hinted asset actually exists.
print(requests.head("https://www.example.com/app.css", timeout=10).status_code)
Node (fetch)
// fetch() cannot see 103. node:http emits it as an "information" event.
import http from "node:http";
const req = http.request({ host: "www.example.com", path: "/" }, (res) => {
console.log("final:", res.statusCode);
res.resume();
});
req.on("information", (info) => {
if (info.statusCode === 103) console.log("hints:", info.headers.link);
});
req.end();Reference and tooling
The authoritative list of assigned status codes is theIANA HTTP Status Code Registry. For a searchable copy with the semantics summarised, use theHTTP status code reference on this site. To see exactly what a server is sending, theheader inspector shows the raw status line and response headers, and thecurl builder assembles the request flags for you.