How to Use fetchpriority for Scripts and fetch() Requests

This guide extends priority hints beyond the familiar LCP image, within Resource Hints & Early Hints and Advanced Caching Strategies & CDN Architecture. Browsers assign every request a priority based on its type and position: render-blocking CSS and fonts high, scripts in the head high, async scripts low, images low until they are known to be in the viewport, fetch() high by default. Those defaults are good guesses, but the browser cannot know that one async script drives your first render while another is analytics, or that a fetch() for the main content matters more than three fetch()s for recommendations.

The fetchpriority attribute (on <script>, <link>, <img>, <iframe>) and the priority option in fetch() let you say so. Raising the priority of critical requests and lowering non-critical ones changes the order in which they compete for bandwidth and connection slots — most valuable on congested mobile connections where everything cannot download at once.

Default browser priorities and useful overrides Default priorities for common request types in Chromium and when to override them with fetchpriority. Default browser priorities and useful overrides Request Default Useful override Script in head (blocking) High rarely needed async / defer script Low high for first-render scripts fetch() call High low for non-critical data preload as=script High low for late-needed modules Image (not yet in viewport) Low high for LCP image

Rapid Diagnosis

  • Show the Priority column in the Network panel (right-click the header). Note priorities of requests that finish before LCP.
  • Find critical async scripts. An async script that renders above-the-fold content but loads at Low priority behind images is a candidate.
  • Find non-critical high-priority fetches. Analytics, recommendations and prefetch fetch() calls default to High and compete with critical data.
  • Look at contention. On a throttled profile, if the critical request starts early but finishes late, it is competing with others.

Root Cause Analysis

1. Async scripts default to Low. A script that renders the hero via client-side rendering competes poorly with images.

2. fetch() defaults to High. Every data request — critical or not — competes equally.

3. Preloads at High for everything. Preloading late-needed resources pulls bandwidth from critical ones.

4. Late-discovered critical requests. Priority cannot fix discovery; a request that starts late still finishes late.

Main content fetch competing with secondary fetches Timelines comparing a critical data fetch sharing bandwidth with secondary fetches at equal priority versus with secondary fetches lowered. Main content fetch competing with secondary fetches Equal priority main content (shared bandwidth) Prioritised main content Secondary (low) recs + analytics 0ms 100ms 200ms 300ms 400ms 500ms 600ms 700ms 800ms 900ms

Step-by-Step Resolution

1. Raise critical async scripts

html
<script src="/assets/hero-render.7a1c.js" async fetchpriority="high"></script>
<script src="/assets/analytics.2b9d.js" async fetchpriority="low"></script>
<!-- trade-off: high-priority async scripts can delay images, including the LCP
     image, if bandwidth is scarce. Raise only scripts the first render depends on. -->

2. Lower non-critical fetches

javascript
// Critical: main content (default High, or explicit).
const product = fetch(`/api/products/${id}`, { priority: 'high' }).then((r) => r.json());
// Non-critical: lower so they do not compete.
fetch(`/api/recommendations/${id}`, { priority: 'low' }).then(renderRecs);
navigator.sendBeacon?.('/rum', payload);         // beacons are already low priority
// trade-off: 'low' requests may be delayed noticeably on congested connections.
// Do not lower anything the user is actively waiting for.

Expected outcome: the main content request finishes sooner under contention.

3. Lower late-needed preloads

html
<link rel="preload" href="/assets/below-fold-carousel.js" as="script" fetchpriority="low">
<!-- trade-off: a low-priority preload still starts early but yields bandwidth;
     if the resource is needed soon after load, low priority can delay it. -->

4. Fix discovery first

Priority helps requests that are already in flight compete better. If a critical request starts late because it is discovered late, move it into the HTML or preload it first — see diagnosing LCP resource load delay.

Raise, lower or leave? Decision sequence for setting fetchpriority on a request. Raise, lower or leave? Needed for the first render or LCP? Raise (or keep High) yes no Analytics, prefetch, below-the-fold data? Lower to low yes no Discovered late? Fix discovery first — priority cannot help yes no Leave the browser default

Verification

In the Network panel, priorities should reflect your intent. On a throttled profile, critical requests should complete earlier relative to secondary ones. Measure LCP (for client-rendered content) or time-to-main-content with User Timing before and after; on congested connections the improvement can be several hundred milliseconds, on fast ones close to zero.

Worked Example: A Client-Rendered Product Page

A client-rendered product page issued six fetch() calls at startup — product, inventory, reviews, recommendations, personalised offers and an A/B config — all at High priority. On mobile, the product request finished at 1.4s because it shared bandwidth with the others. Marking reviews, recommendations and offers as priority: 'low' and raising the product request explicitly brought it to 0.8s; LCP p75 for the template fell by about 450ms. Total data loaded was unchanged; only the order improved.

How Priorities Interact With HTTP/2 and HTTP/3

Browser priorities are communicated to the server: HTTP/2 uses stream priorities (largely replaced by the simpler Extensible Priorities scheme), and HTTP/3 uses the Priority header and frames. Whether your server or CDN honours them determines how much fetchpriority changes delivery order on a shared connection. Most major CDNs implement prioritisation; some origins and proxies ignore it, in which case the browser's own scheduling (when to issue requests) still helps but in-flight bandwidth sharing does not change. Test on your real stack rather than assuming.

A Priority Plan for a Typical Page

Write down the intended order of the first second of loading, then make the hints express it. For a server-rendered product page it might be: HTML; critical CSS; the LCP image; the heading font; the hydration entry script; the product API refresh; everything else. Compare that plan with the Priority column and request start times in a throttled waterfall. Requests that should be early but start late need discovery fixes (preload, Early Hints); requests that start on time but finish late need priority changes; requests that are early but unimportant need lowering or deferral. Revisit the plan when templates change — a new carousel or widget quietly adds high-priority requests that reorder everything.

Common Mistakes

  • Marking everything high. Priorities are relative; if everything is high, nothing is.
  • Using fetchpriority to fix late discovery. It cannot start a request earlier.
  • Lowering resources the user waits for. Users notice slow data more than slow analytics.
  • Ignoring server support. Without server-side prioritisation, the effect on shared connections is smaller.

Edge Cases

Iframes. fetchpriority on iframes affects the iframe document's request priority, useful for deprioritising embeds.

Service workers. Requests made from a service worker carry their own priority; passing through event.request preserves it.

Safari support. Priority hints are supported in recent Chromium, Safari and Firefox versions; the attribute is ignored safely where unsupported.

Speculative loading. Prefetches and speculation rules already run at low priority; no hint needed.

FAQ

Is fetchpriority the same as preload?

No. Preload makes the browser start a request early; fetchpriority changes how a request competes once started. They combine well: preload the LCP image and give it fetchpriority="high".

Does fetchpriority help on fast connections?

Less. With ample bandwidth, requests do not compete much and order matters little. The biggest gains are on congested mobile networks.

Can I lower the priority of third-party scripts I do not control?

Only if you load them — add fetchpriority="low" to the script tag you write. Scripts injected by a tag manager inherit whatever the injecting code sets.

What priority does sendBeacon use?

Beacons are sent at low priority by design, which is why they are suitable for analytics.

Should fonts get fetchpriority?

Fonts are already high priority when discovered. Preloading the critical font is more useful than adjusting its priority.

How do I confirm the server honours priorities?

Compare a throttled waterfall with and without the hints on the real stack. If completion order changes, prioritisation is effective end to end.

Does fetchpriority change the order of script execution?

No. Execution order is governed by script type (defer scripts run in document order; async scripts run when they arrive). Priority only affects how quickly the bytes arrive, which can change when an async script happens to run.

Can a low-priority request be starved entirely?

Rarely on modern browsers — low-priority requests still proceed, just after higher-priority ones on contended connections. On very slow connections they can be delayed by seconds, which is acceptable for analytics and prefetches but not for anything visible.