TL;DR / The
fetchpriorityattribute lets developers override the browser's default resource loading priorities, signaling which resources are critical (LCP image) and which can be deferred (below-fold images).
How It Works
┌───────────────┐ ┌──────────────────┐ ┌──────────┐
│ HTML Parser │───────→│ Resource Queue │───┐───→│ "high" │ loaded first
└───────────────┘ └──────────────────┘ │ └──────────┘
│
│ ┌──────────┐
│───→│ "auto" │ browser decides
│ └──────────┘
│
│ ┌──────────┐
└───→│ "low" │ deferred
└──────────┘
Browsers assign default priorities to resources based on type and position in the document. Scripts in the <head> are high priority. Images are low priority until the layout engine determines they are in the viewport, at which point they are promoted to medium. Stylesheets are highest priority because they block rendering. These heuristics work well in general but fail in specific, performance-critical scenarios.
The Priority System
When the HTML parser encounters a resource (via <img>, <script>, <link>, fetch()), it assigns an internal priority before making the network request. This priority determines the order in which resources are sent over the connection. HTTP/2 and HTTP/3 use stream priorities to allow the server and intermediaries to schedule responses optimally -- high-priority resources get more bandwidth.
The fetchpriority attribute accepts three values: "high", "low", and "auto" (the default). Setting fetchpriority="high" boosts the resource above its default priority for that resource type. Setting "low" demotes it. "auto" uses the browser's default heuristic.
The attribute works on <img>, <link>, <script>, and <iframe> elements, and as an option in the fetch() API's RequestInit object ({ priority: "high" }). It maps to the internal Chromium priority levels: Highest, High, Medium, Low, Lowest.
The LCP Problem
The most impactful use case is the Largest Contentful Paint (LCP) image. By default, browsers assign images a low initial priority. The browser does not know which image is the LCP element until layout completes -- it needs to parse the HTML, download CSS, compute styles, and run layout to determine which image is largest and above the fold. By that time, other resources may have already consumed available bandwidth.
Adding fetchpriority="high" to the LCP image tells the browser to prioritize it immediately, before layout determines its viewport position. This can reduce LCP by hundreds of milliseconds on bandwidth-constrained connections because the image starts downloading earlier in the waterfall.
Conversely, fetchpriority="low" on below-fold images prevents them from competing with the LCP image for bandwidth. Without this, the browser may start downloading several above-fold and below-fold images simultaneously, splitting bandwidth across all of them.
Interaction with Loading Attributes
fetchpriority is orthogonal to loading="lazy". The loading attribute controls when the request is made (eagerly or when near the viewport). The fetchpriority attribute controls the priority of that request once it is made. Setting fetchpriority="high" loading="lazy" is contradictory -- you are saying "defer this request, but when you do make it, make it high priority." It is not an error, but it signals confused intent.
The useful combinations are: fetchpriority="high" on the LCP image (no loading attribute, so it loads eagerly with high priority), and loading="lazy" on below-fold images (with implicit fetchpriority="auto" or explicit "low").
<link rel="preload"> also interacts with priority hints. A preloaded resource already has high priority by default. Adding fetchpriority="high" to a preload bumps it to the highest internal level. This is useful when you have multiple preloads and need to order them: fetchpriority="high" on the most critical preload, fetchpriority="auto" on the rest.
Script Priority
Scripts have complex default priorities rules. Parser-blocking scripts in the <head> are high priority. async scripts are low priority (they do not block parsing). defer scripts are low priority (executed after parsing). Module scripts follow their own dependency resolution.
Setting fetchpriority="low" on a non-critical <script> in the head reduces its priority without changing its execution semantics. The script still blocks parsing (unless async or defer), but its download is deprioritized relative to other resources. This is useful for analytics or monitoring scripts that need to be in the head for early execution but should not delay critical resource downloads.
The fetch() API
In JavaScript, fetch('/api/data', { priority: 'high' }) signals that this network request is more important than other concurrent fetches. This is particularly relevant for SPAs that make multiple API calls on route change. The call that fetches data needed for the initial render should be high priority, while prefetch calls for likely-next navigations should be low.
Measurement
Priority hints do not guarantee a specific loading order -- they are hints, not directives. The browser's network scheduler considers bandwidth, connection limits, resource size, and server scheduling. Chrome DevTools' Network panel shows the "Priority" column revealing the effective priority assigned to each resource.
Gotchas
- Setting everything to
fetchpriority="high"is equivalent to setting nothing -- if all resources are high priority, the browser has no differentiation signal and falls back to its default ordering. Usehighsparingly on 1-2 critical resources. fetchprioritydoes not overrideloading="lazy"-- a lazy-loaded image withfetchpriority="high"still waits until it approaches the viewport before the request is made. The priority only applies once the request is initiated.- Browser support is not universal -- Safari added support later than Chrome and Firefox. Unsupported browsers silently ignore the attribute, so it is safe to use as a progressive enhancement.
- HTTP/1.1 connections cannot use stream prioritization -- without HTTP/2 or HTTP/3 multiplexing, priority hints primarily affect the request scheduling order in the browser's network stack, not the server's response ordering.
- Preloaded resources are already high priority -- adding
fetchpriority="high"to a<link rel="preload">provides marginal benefit over the preload's default priority. The bigger win is usingfetchpriority="low"on competing resources.