Skip to content
Control Plane Labs

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.

Other 1xx codes