How HTTP Works

Header · not registered

< Link: </app.css>; rel=preload; as=style

Early-Hints

Learn how 103 Early Hints allows servers to send preload hints while preparing the main response. Improve page load performance with early resource loading.

Reviewed 3 min readadvanced5 sourcesTry itMarkdown
Direction
Response
Category
Preloading
Spec
RFC 8297
Status
Not a real header: 103 Early Hints is a status code; it carries Link headers
On this page

TL;DR: Early Hints is the 103 status, not a header. The server sends it while it’s still building the page, with Link headers that tell the browser to preload a stylesheet or preconnect to an origin. Browsers can ignore 103, so repeat the same links in the final response or HTML.

What is Early-Hints?

Server think time is wasted time for the browser. RFC 8297 defines 103 to fill that gap: the server sends some headers early, and the browser can start fetching a hinted stylesheet before the HTML arrives. A 103 has no body, and it doesn’t commit the server to anything. The final response can have a different status and different headers.

Example

Here’s a trimmed HTTP/1.1 exchange where the connection closes after the HTML:

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Link: </style.css>; rel=preload; as=style
Connection: close

<!doctype html><link rel="stylesheet" href="/style.css"><p>Hello</p>

The blank line ends the 103. The HTML belongs to the final 200, which repeats the Link header for clients that skipped the 103.

What to Send in 103

Hint resources you know every response for that page needs, before you’ve generated it: the main stylesheet, a critical font, the origin your API lives on. For a stylesheet, as=style tells the browser what it’s fetching. Font preloads need crossorigin to match the CORS fetch the page will make later, even for same-origin fonts. Check that each hint gets used before adding more.

Implementation

On Cloudflare Workers, you don’t build the 103 yourself. Enable Early Hints for the zone and return preload links in the final response, as in Cloudflare’s Worker example:

export default {
  async fetch() {
    return new Response(
      '<!doctype html><link rel="stylesheet" href="/style.css"><p>Hello</p>',
      {
        headers: {
          'Content-Type': 'text/html; charset=utf-8',
          Link: '</style.css>; rel=preload; as=style',
        },
      },
    );
  },
};

Serve /style.css separately. Cloudflare caches the Link headers from this response and uses them to send 103s on later requests, so the request that sets the header won’t necessarily get a 103 itself.

In Node, response.writeEarlyHints() sends the 103 directly. This server sends the hint, then reads the page from disk, and also serves the stylesheet it hinted:

import http from 'node:http';
import { readFile } from 'node:fs/promises';

http.createServer(async (req, res) => {
  if (req.url === '/style.css') {
    res.writeHead(200, { 'Content-Type': 'text/css' });
    res.end('body { font-family: sans-serif; }');
    return;
  }
  if (req.url !== '/') {
    res.writeHead(404);
    res.end();
    return;
  }
  const link = '</style.css>; rel=preload; as=style';
  res.writeEarlyHints({ link });
  try {
    const html = await readFile(new URL('./index.html', import.meta.url));
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', Link: link });
    res.end(html);
  } catch {
    res.writeHead(500);
    res.end();
  }
}).listen(8084, '127.0.0.1');

Save it as hints-demo.mjs next to an index.html that links /style.css, then run node hints-demo.mjs. curl -sS -D - http://127.0.0.1:8084/ prints both response blocks. Delete index.html and you’ll see a 103 followed by a 500: the hint goes out before the server knows whether the page will work.

Implementation Notes

Cloudflare’s zone implementation only sends 103 over HTTP/2 and HTTP/3, never HTTP/1.1. It handles preload and preconnect links, and skips the 103 when the final response is already available. It only generates hints for URIs ending in .html, .htm, .php, or with no extension, where the final status is 200, 301, or 302.

Cloudflare Pages has a separate integration that builds hints from <link> elements in your HTML. A Cloudflare zone reads Link headers instead, so check what your CDN actually looks at.

For browser support, see MDN’s compatibility table.

Common Mistakes

The most common mistake is sending an Early-Hints: ... header, which does nothing. The second is putting Link only in the 103, so clients that ignore 103 never see the hint. Also, Cloudflare keys hints by URI without the query string and can send them before authentication runs, so keep sensitive URLs out of hints that every visitor shares.

To inspect the edge response, use an HTTP/2-capable curl build:

curl --http2 -sS -D - -o /dev/null https://example.com/

Look for a 103 header block before the final status. Then open the browser’s Network panel to confirm the hinted resource was fetched early and what started the fetch.

Early Hints vs HTTP/2 Server Push

Early Hints sends only metadata, and the browser decides whether to fetch. HTTP/2 server push sent the resource itself on a separate stream, whether or not the browser already had it cached. With 103 you only win if a fetch the page needs starts earlier than it otherwise would.

Frequently asked questions

What are Early Hints?

Early Hints is the 103 status code, an interim response that carries Link headers before the real response is ready. There is no Early-Hints header.

How do Early Hints improve performance?

While the server is still building the page, the browser can start fetching hinted resources such as stylesheets. How much time that saves depends on the page, the resource and the browser, so measure it.

Which browsers support Early Hints?

Check the current MDN compatibility table, and test the specific hint type you rely on. A browser that supports 103 may act on preconnect hints but not preload.

How do I implement Early Hints?

Use a server or CDN that can emit 103. In Node, call response.writeEarlyHints(). Cloudflare zone Early Hints builds hints from Link headers on your responses, while Cloudflare Pages has a separate integration that reads HTML link elements.

Sources

  1. MDN Web Docs: 103 Early Hintsdeveloper.mozilla.org
  2. RFC 8297: Early Hintsrfc-editor.org
  3. Cloudflare: Early Hintsdevelopers.cloudflare.com
  4. Cloudflare Workers: 103 Early Hintsdevelopers.cloudflare.com
  5. Cloudflare Pages: Early Hintsdevelopers.cloudflare.com

Keep going

Browse /search