Early Hints
ActiveHTTP 103 Early Hints is an informational response that sends preliminary headers (typically Link preload directives) before the final response. Defined in RFC 8297. Allows browsers to begin fetching critical resources while the server is still generating the final 2xx response.
Description
The 103 Early Hints status code is an informational response used to send preliminary HTTP headers to the client before the server has finished generating the final response. The primary use case is sending Link headers with rel=preload or rel=preconnect directives, enabling the browser to start fetching critical sub-resources (stylesheets, scripts, fonts) while the origin server is still computing the page.
Unlike other informational responses (100 Continue), 103 is explicitly designed for performance optimization. The server sends one or more 103 responses containing Link headers, and the browser immediately begins resource fetches. When the final response (typically 200 OK) arrives, it supersedes the 103 headers entirely. This creates a pipeline effect: the browser's network stack stays busy during the server's think time, eliminating the sequential dependency between page generation and resource discovery.
The specification is deliberately minimal. Only Link headers are meaningful in a 103 response — the client SHOULD ignore other headers to prevent security issues like premature Content-Security-Policy application. Multiple 103 responses can be sent before the final response, and the server may include headers in 103 that differ from the final response. The final response is authoritative; 103 headers are hints, not commitments.
103 Early Hints fundamentally changes the performance equation for server-rendered pages. Traditional flow: client requests → server computes (500ms) → server responds with HTML → browser parses HTML → browser discovers CSS/JS/font URLs → browser fetches those resources. With 103: client requests → server immediately sends 103 with Link headers → browser begins fetching CSS/JS/fonts → server finishes computing → server sends 200 with HTML → resources already in flight or cached. The savings compound on high-latency connections.
Cloudflare popularized 103 by automatically generating Early Hints from Link headers observed in previous responses for the same URL. This means existing applications gain 103 support without code changes — Cloudflare memorizes which resources a page links to and proactively hints them on subsequent requests. Chrome (v103+), Firefox (v102+), and Edge support 103 natively, though Safari support remains limited as of 2024.
Examples
GET /dashboard HTTP/1.1
Host: app.example.com
Accept: text/html
Accept-Encoding: gzip, brHTTP/1.1 103 Early Hints
Link: </assets/styles.css>; rel=preload; as=style
Link: </assets/app.js>; rel=preload; as=script
Link: </fonts/inter.woff2>; rel=preload; as=font; crossorigin
Link: <https://api.example.com>; rel=preconnectHTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 8192
Link: </assets/styles.css>; rel=preload; as=style
Link: </assets/app.js>; rel=preload; as=script
Cache-Control: private, max-age=0
<!DOCTYPE html>
<html>...</html>HTTP/1.1 103 Early Hints
Link: </css/critical.css>; rel=preload; as=style
HTTP/1.1 103 Early Hints
Link: </css/critical.css>; rel=preload; as=style
Link: </js/vendor.js>; rel=preload; as=script
Link: </js/app.js>; rel=preload; as=script
HTTP/1.1 200 OK
Content-Type: text/html
<!DOCTYPE html>...GET /checkout HTTP/1.1
Host: shop.example.com
Accept: text/htmlHTTP/1.1 103 Early Hints
Link: <https://payments.stripe.com>; rel=preconnect
Link: <https://cdn.example.com>; rel=preconnect
Link: </checkout/styles.css>; rel=preload; as=style
Link: </checkout/bundle.js>; rel=preload; as=scriptEdge Cases
- •Only Link headers are semantically meaningful in 103 responses — clients SHOULD ignore other headers like Content-Security-Policy or Set-Cookie to prevent security vulnerabilities from premature header application.
- •The final response is authoritative. If a 103 response preloads /old.css but the final 200 references /new.css, the preloaded resource is wasted bandwidth. Ensure 103 hints match what the final response will actually use.
- •HTTP/1.1 intermediaries (proxies, load balancers) that don't understand 103 may buffer or discard it, preventing the client from receiving early hints. This works best over HTTP/2 or HTTP/3 where intermediaries are 103-aware.
- •Sending too many Link headers in 103 can backfire — the browser has limited concurrent connections, and preloading low-priority resources may delay critical ones. Limit to 3-5 truly critical resources.
- •If the server sends 103 Early Hints but the final response is a redirect (301/302), the preloaded resources from 103 are discarded. The browser must restart discovery after following the redirect.
- •Cross-origin preloads in 103 require the crossorigin attribute when fetching fonts or resources that need CORS. Omitting it causes a double fetch — one without CORS (from 103) and one with CORS (from the actual page).
- •Cloudflare's automatic 103 implementation caches Link headers from previous responses. If your page changes its resource URLs (cache-busted filenames), the stale hints persist until Cloudflare observes the new response, causing wasted preloads during the transition.
When You'll See This
- →Server-rendered pages with known CSS/JS dependencies that take 200-500ms to generate
- →E-commerce product pages where the server queries inventory/pricing while the browser can preload the layout assets
- →CDN edge nodes sending 103 based on previously observed Link headers for the same URL
- →Dashboard applications with heavy JavaScript bundles that benefit from early preloading during API aggregation
- →Pages behind authentication where the server validates the session while simultaneously hinting static resources
- →Multi-step checkout flows where preconnecting to payment processor origins saves connection setup time
- →Next.js applications using experimental earlyHints config to send 103 before React server-side rendering completes
Implementation References
| Language | Constant |
|---|---|
| Go | http.StatusEarlyHints |
| Rust | http::StatusCode::EARLY_HINTS |
| Python | http.HTTPStatus.EARLY_HINTS |
| Node.js | http.STATUS_CODES[103] |
| .NET | HttpStatusCode.EarlyHints |
| Java | 103 (no standard constant; define as custom) |
| PHP | Response::HTTP_EARLY_HINTS (Symfony) |
| Ruby | :early_hints (Rack) |
History
Proposed by Kazuho Oku (Fastly) and published as RFC 8297 in December 2017. Remained largely unimplemented until Cloudflare announced automatic Early Hints support in September 2022, followed by Chrome 103 (June 2022) and Firefox 102 (June 2022) shipping client-side support. The convergence of CDN and browser support in 2022 transformed 103 from a theoretical optimization into a practical performance tool.
Related Status Codes
Related Headers
FAQ
How does 103 Early Hints differ from preload Link headers in the final response?
Link headers in the final 200 response arrive AFTER the server has finished processing — the browser only starts preloading when it receives the response. With 103, the Link headers arrive immediately while the server is still computing. The time savings equals the server's processing time (typically 100-500ms). On a page that takes 300ms to generate and needs 3 CSS/JS files, 103 gives the browser a 300ms head start on fetching those resources, which compounds with network latency on slow connections.
Do I need to change my application code to support 103 Early Hints?
Not necessarily. Cloudflare automatically generates 103 responses by caching Link headers from previous responses for the same URL — no code changes required. For self-hosted setups: Node.js supports res.writeEarlyHints() since v18.11, Next.js has experimental earlyHints config, and Nginx/Apache require module-level support or custom configurations. The key architectural requirement is that your server or proxy must be able to send headers before the response body is ready.
What happens if the browser doesn't support 103 Early Hints?
Browsers that don't understand 103 simply ignore it and wait for the final response — there's zero downside. The final response contains all necessary information regardless of whether 103 was processed. This makes 103 a pure progressive enhancement: supporting browsers get faster loads, non-supporting browsers behave exactly as before. The only cost is the small overhead of sending the extra 103 response bytes over the wire.