Zum Inhalt springen
Core Web Vitals specialists
Frontend-Performance

fetchpriority: Speed Up LCP with Priority Hints

13 min read
fetchpriorityPriority HintsLCPCore Web VitalsFrontend

A page's most important image, the hero, is usually also its slowest. The reason lies in how browsers treat images: by default they start every image at low priority (web.dev), because most images are needed further down the page or in hidden menus. This very behavior disadvantages the one image that shapes the first visible impression and thus the Largest Contentful Paint. The fetchpriority attribute corrects this misjudgment with a single declaration in the markup. In documented tests it moved LCP from 2.6 to 1.9 seconds (web.dev) and in another case from 4.2 to 1.9 seconds (DebugBear) -- with no new infrastructure and no build rework. This article shows the correct use, the interplay with preload and srcset, and the most common mistakes. As a declarative quick win, the priority hint is among the first steps in our frontend optimization.

fetchpriority="high": load the LCP image soonerBrowser load order without and with the priority hint on the hero imageWITHOUT fetchpriorityHTML + CSSscripts (high priority)LCP image waits (low)LCP image loads lateLCP 4.2 sWITH fetchpriority="high"HTML + CSSLCP image loads at onceLCP 1.9 s-2.3secondsLCP in test(DebugBear)4.2 s to 1.9 sThree rules for the priority hint1Exactly one elementOnly the LCP image getshigh - nothing below it.More high = nothing prioritized2Never lazy-load itloading="lazy" on the LCPimage slows it down.Load the hero image eagerly3Pair it with preloadPreload finds the image,high raises its priority.srcset stays on the img tagImages start at low priority in the browser (web.dev) - the LCP image is treated like a minor one.Use of fetchpriority for the LCP image rose to 15 percent of mobile pages (Web Almanac 2024).A declarative attribute, no new infrastructure - a quick win of frontend optimization.

Key takeaways

  • Browsers start images at low priority and only raise them after layout -- which disadvantages the LCP image that should actually load first.
  • fetchpriority='high' on the LCP image signals its importance to the browser immediately, so it does not queue the download behind lower-rated images.
  • In tests the hint improved LCP from 2.6 to 1.9 seconds and from 4.2 to 1.9 seconds -- on some pages lab values reached 20 to 30 percent faster LCP.
  • A strict rule applies: exactly one element gets high. Marking several images up creates bandwidth competition and slows down precisely the important image.
  • The LCP image should generally stay out of lazy loading -- loading='lazy' on the hero delays exactly the content fetchpriority is meant to speed up.

Why the Browser Underrates the LCP Image

When loading a page the browser is a planner that assigns each resource a priority and decides what loads first. For images it applies a blanket assumption: they start at low priority, because many images sit below the visible area or are hidden in collapsible menus. Only once the browser has computed the layout and recognizes that an image is visible in the viewport does it raise the priority afterwards (web.dev). That promotion, however, comes late -- the browser must first process the CSS and compute the layout before it knows which image is visible.

For the LCP image this is a problem. It is the largest and therefore most important image for the first impression, yet it is initially treated like any other. In the network waterfall this shows as a long gray bar: the browser already knows the resource but has not begun the download because other, higher-rated resources take precedence (DebugBear). Only after the first render does the priority switch from low to high -- and precious time has passed before the most important image even begins to load.

What Determines the Largest Contentful Paint

LCP measures when the largest visible content element is rendered -- on most pages that is a hero image, a product photo or a large headline. Until that element appears, the page feels unfinished to the user. The threshold considered good is 2.5 seconds (web.dev). In practice, competitive pages set themselves a stricter internal budget, often toward 2.0 seconds, to land safely in the green even on slow mobile networks.

fetchpriority='high': the One Correction

The fetchpriority attribute tells the browser the relative importance of a resource before it has computed the layout. The value high pulls a resource forward, low pushes it back, auto leaves the default decision to the browser. Set on the LCP image, fetchpriority='high' makes the browser recognize its importance immediately and load the image right after the document request, instead of queuing it behind lower-rated resources. In the waterfall the long gray waiting bar disappears, and the priority no longer switches from low to high -- it is high from the start (DebugBear).

lcp-image.html
<!-- Load the LCP image directly at high priority -->
<img src="/img/hero.avif" alt="Product view"
     fetchpriority="high" width="1200" height="600">

The effect is documented in several cases. In a test with a flight search the hint improved the Largest Contentful Paint from 2.6 to 1.9 seconds (web.dev), a 0.7-second gain. DebugBear documents a case in which the LCP image loaded immediately after the document request once the attribute was set and LCP dropped from 4.2 to 1.9 seconds (DebugBear). Addy Osmani reports that priority hints sped up the LCP of a large commerce platform by 4 percent (Addy Osmani) and that some pages reached 20 to 30 percent (Addy Osmani) faster LCP values in their lab tests. The exact saving depends on how late the browser would otherwise have discovered the image -- the larger the waterfall in front of it, the bigger the lever.

The Core in One Sentence

fetchpriority='high' removes a wrong default assumption from the browser: instead of treating the LCP image as incidental and promoting it only after layout, it loads it immediately. A single attribute declaration that acts exactly where the perceived page build happens.

An important caveat: fetchpriority is a hint, not a directive. The browser tries to follow the developer's preference but may weigh it against its own heuristics to resolve conflicts (web.dev). In practice this means the effect is most reliable where the browser would otherwise have made a recognizably wrong decision -- such as the late-promoted LCP image. If, on the other hand, you have already preloaded the image as one of the first elements in the document head, the additional gain from fetchpriority is smaller, because the browser has already triggered the download early. We look at exactly this interplay of preload and fetchpriority in detail below.

Exactly One Element: Why More Is Not Faster

The most important principle of the priority hint is: exactly one element gets high. The temptation is great to mark several important images up at once -- the hero, the slider images, the logos. But that tips the effect into its opposite. Bandwidth is limited, especially on mobile networks. If several resources are requested as high priority at the same time, they compete for the same line and slow each other down. DebugBear describes a case in which seven slider images below the visible area carried fetchpriority='high': only when the attribute was removed from them and kept only on the LCP image did that one load faster -- LCP improved in total by almost 4 seconds (DebugBear).

If you mark everything up, you prioritize nothing in the end. The value of fetchpriority does not come from as many high declarations as possible, but from the one that tells the browser which element is truly needed first.

Project experience from 50+ performance projects

The high therefore belongs exclusively on the element that determines the Largest Contentful Paint. Which one that is cannot be guessed, only measured -- a lab test or the field data show which element counts as LCP on most devices. With responsive layouts this can vary by screen size; here field data help identify which image serves as the LCP element across the large majority of visits. How lab and field data sensibly complement each other is explored in our article on RUM, CrUX and performance budgets.

fetchpriority='low' as the Counterpart

Just as effective as raising priority is deliberately holding it back. Scripts or images that do not count for the first impression can be pushed back with fetchpriority='low', so they steal no bandwidth from the LCP path. That way the one important element gets a clear lane while everything incidental waits -- the two values work together.

Keep the LCP Image out of Lazy Loading

Lazy loading is one of the most effective techniques for images below the visible area: with loading='lazy' the browser loads an image only when it scrolls near the viewport. On a page with ten images, of which only the first -- the LCP element -- is visible in the first viewport, lazy-loading the remaining nine images can even speed up loading the first (MDN), because they no longer steal its bandwidth. But this is exactly where the trap lies: the LCP image itself should specifically not be lazy-loaded.

If loading='lazy' is accidentally set on the hero image -- for example because a theme or plugin lazy-loads all images across the board -- it delays exactly the content fetchpriority is meant to speed up. The browser then waits until it knows whether the image is in the viewport, instead of loading it immediately. The LCP image therefore belongs loaded eagerly, that is, without the lazy attribute, and additionally marked with fetchpriority='high'. This combination is the standard case: the most important image eager and high-priority, all the others lazy.

In practice this single mistake -- the lazy-loaded hero image -- is one of the most common reasons for an unnecessarily high LCP. Many content management systems and theme builders now enable lazy loading across all images by default, because below the fold it usually helps. For the one image in the visible area, however, the benefit reverses. That is why, in every optimization, we first check whether the LCP image is accidentally stuck in lazy loading before we even think about the priority hint -- because a high attribute on a lazy-loaded image cancels itself out.

ElementloadingfetchpriorityReasoning
LCP image (hero)eager (no lazy)highDetermines LCP, must load first
Images below the foldlazyautoOnly needed on scroll, save bandwidth
Decorative background imageeagerautoRarely LCP, no precedence needed
Incidental script-lowShould steal no bandwidth from the LCP path

Interplay with preload and srcset

fetchpriority and preload solve two different sub-problems and unfold their full effect together. The problem of late discovery -- the browser finds an image only late in the markup, or because it is loaded as a CSS background -- is solved by preload, which triggers the download early. The problem of wrong priority is solved by fetchpriority. If an image is only preloaded, it keeps its low default priority; only fetchpriority='high' on the preload tag raises it. The two therefore belong together when the LCP element is discovered late, such as a CSS background image.

preload-lcp.html
<!-- Preload the LCP background image AND prioritize it -->
<link rel="preload" href="/img/hero.avif" as="image"
      fetchpriority="high">

<!-- If the image is an img in the markup, the attribute suffices: -->
<img src="/img/hero.avif" alt="Hero" fetchpriority="high">

For responsive images with srcset and sizes the attribute belongs on the img element itself, not on the surrounding picture element (DebugBear). The browser first selects the matching image variant based on srcset and sizes and then loads it at high priority. That way the LCP image can be served responsively and prioritized at the same time -- the two optimizations do not exclude each other. Anyone who also shrinks the LCP image, for example with a modern format, gains twice: an image saved as AVIF at 80 percent quality reached a 95 percent (MDN) saving in one example, shrinking from 1 MB to 46 KB.

img in the Markup

If the LCP image is an img tag directly in the HTML, fetchpriority='high' on the tag suffices. The browser discovers it early and now also loads it at high priority instead of promoting it afterwards.

CSS Background Image

If the LCP image is loaded via CSS background, the browser discovers it late. Combine preload with as='image' and fetchpriority='high' here, so it loads early and with precedence.

Responsive with srcset

With srcset and sizes, fetchpriority belongs on the img element, not on picture. The browser picks the matching variant and loads it high-priority -- responsive and fast at once.

The Most Common Mistakes with the Priority Hint

The first and most consequential mistake is over-prioritizing: setting several images to high at once. As described, they then compete for bandwidth and slow down the truly important image. The second mistake is accidentally lazy-loading the LCP image, often caused by a theme or plugin that lazy-loads all images across the board. The third mistake is setting the attribute on the wrong element -- not every hero image is the LCP element on every device, and without measurement it is easy to miss here.

The fourth mistake is viewing fetchpriority in isolation. The hint speeds up the moment the browser loads the image -- but it does not replace the other building blocks of a fast LCP. A slow server response delays every resource equally, as our article on TTFB optimization shows. An oversized, uncompressed image loads slowly even at high priority. And a layout that still shifts after the image loads does not hurt LCP but stability, which we cover in the article on the Visual Stability Index as the CLS successor. The priority hint is a building block, not a substitute for the whole picture.

  • Measure the LCP element first, do not guess -- determine it via lab test and field data
  • Mark exactly one element with fetchpriority='high', rather than several at once
  • Load the LCP image eagerly, so no loading='lazy' on the hero
  • For CSS background images, combine preload and fetchpriority='high'
  • With srcset, set the attribute on the img element, not on picture
  • Deliberately hold back incidental resources with fetchpriority='low'
  • Verify the effect in the field data after the change, not only in the lab

The great advantage of fetchpriority is that it is purely declarative in the markup. It needs no new infrastructure, no additional build step and no server configuration -- one attribute on one element suffices. This makes the priority hint one of the cheapest measures to improve the Largest Contentful Paint, and at the same time one with the best ratio of effort to effect. In our frontend optimization it is usually one of the first moves once we have identified the LCP element beyond doubt.

Sources and Studies

This article is based on data from: web.dev (Optimize resource loading with the Fetch Priority API, Optimize LCP), MDN Blog (Fix your website's Largest Contentful Paint by optimizing image loading), DebugBear (The fetchpriority=high Attribute, Avoid Overusing fetchpriority=high), Addy Osmani (Use fetchpriority=high to load your LCP hero image sooner) and Web Almanac 2024 (HTTP Archive, Performance). All statistics cited were checked at the time of publication.