HttpFixerBlogPerformance → HTTP Link Header Preload — Reduce LCP Without Changing Your HTML
Performance

HTTP Link Header Preload — Reduce LCP Without Changing Your HTML

Updated April 2026

Reading this? Verify your fix in real-time. Run a live PageSpeed audit → SpeedFixer

Your HTML tells the browser what to load. The HTTP Link header tells it what to preload before it even reads the HTML. For fonts, hero images, and critical CSS, this difference translates directly into a faster Largest Contentful Paint.

How it works

When a browser receives an HTTP response, it reads the headers before parsing the body. If a Link header specifies a preload, the browser starts fetching that resource immediately — while still downloading and parsing the HTML. For a font that would normally be discovered only after the CSS is parsed, this saves hundreds of milliseconds.

The Link header syntax

# Preload a font
Link: </fonts/inter.woff2>; rel=preload; as=font; crossorigin

# Preload a hero image
Link: </images/hero.webp>; rel=preload; as=image

# Preload critical CSS
Link: </css/critical.css>; rel=preload; as=style

# Preload a script
Link: </js/app.js>; rel=preload; as=script

# Multiple resources — separate with comma
Link: </fonts/inter.woff2>; rel=preload; as=font; crossorigin, </images/hero.webp>; rel=preload; as=image

Config by stack

Nginx

server { listen 443 ssl http2; server_name yourapp.com; location = / { # Add Link headers for your homepage's critical resources add_header Link "</fonts/inter.woff2>; rel=preload; as=font; crossorigin" always; add_header Link "</images/hero.webp>; rel=preload; as=image" always; add_header Link "</css/critical.css>; rel=preload; as=style" always; }
}

Vercel (vercel.json)

{ "headers": [ { "source": "/", "headers": [ { "key": "Link", "value": "</fonts/inter.woff2>; rel=preload; as=font; crossorigin, </images/hero.webp>; rel=preload; as=image" } ] } ]
}

Express / Node.js

app.get("/", (req, res) => { res.setHeader("Link", [ "</fonts/inter.woff2>; rel=preload; as=font; crossorigin", "</images/hero.webp>; rel=preload; as=image", "</css/critical.css>; rel=preload; as=style" ].join(", ")); res.sendFile("index.html");
});

Cloudflare (Transform Rules)

Rules → Transform Rules → Modify Response Headers → Set header: Link = your preload value. Apply to source matching your homepage path.

The as= attribute — get it right

Resource typeas= valueExtra attributes
Font file (.woff2)fontcrossorigin (required even for same-origin fonts)
Image (.webp, .jpg, .png)imageimagesrcset and imagesizes for responsive images
CSS filestyleNone needed
JavaScript filescriptNone needed
Video filevideoNone needed
Do not preload resources you are not using on that page. An unused preload wastes bandwidth and can hurt performance. Preload only the 2-3 most critical above-the-fold resources.

HTTP/2 Server Push vs Link preload

HTTP/2 Server Push actively sent resources to the browser before it asked. It was deprecated and removed from Chrome in 2022 because it often pushed resources the browser already had cached. Link preload is better — the browser decides whether to fetch based on its cache state. Always prefer Link preload over Server Push.

Verify it is working

# Check headers are being sent
curl -I https://yoursite.com/ | grep -i link

# In DevTools Network tab:
# Preloaded resources show "Initiator: Link" and appear before other resources
# LCP resources should show fetchpriority="high"
Run a live PageSpeed audit → SpeedFixer
Visualise your Cache-Control header → Cache-Control Simulator