Service Worker · Concept
Background Fetch: downloading large files that survive tab closure
Published
In one line: Background Fetch provides a method for managing downloads that may take a significant amount of time, such as movies, audio files, and software — the browser performs the fetch in a user-visible way, showing progress and a cancel option, and wakes the service worker once it completes.
The problem it solves
Section titled “The problem it solves”When a web app requires the user to download large files, the user normally needs to stay connected to the page for the download to complete — closing the tab or navigating away stops it. Background Fetch tells the browser to perform the fetches in the background instead: “The browser then performs the fetches in a user-visible way, displaying progress to the user and giving them a method to cancel the download. Once the download is complete the browser then opens the service worker, at which point your application can do something with the response if required.”
It also handles connectivity changes: the fetch can be started while offline and will begin once the user is connected; if the user goes offline mid-fetch, the process pauses until they are back online.
This is distinct from the Background Synchronization API, which “can’t be used for long running tasks such as downloading a large file” because it requires the service worker to stay alive until the fetch completes, and the browser will eventually terminate that task to conserve battery.
Registering a fetch
Section titled “Registering a fetch”Feature-detect, then call backgroundFetch.fetch() on the service worker registration:
async function regularDownloadFallback(urls) { // Not supported (or unavailable): download each file with a normal // fetch instead, and trigger a browser save for each response. for (const url of urls) { const response = await fetch(url); if (!response.ok) { throw new Error(`Fallback download failed for ${url}: ${response.status}`); } const blob = await response.blob(); const objectUrl = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = objectUrl; link.download = url.split("/").pop(); link.click(); URL.revokeObjectURL(objectUrl); }}
const filesToFetch = ["/ep-5.mp3", "ep-5-artwork.jpg"];
if (!("BackgroundFetchManager" in self)) { regularDownloadFallback(filesToFetch);} else { navigator.serviceWorker.ready.then(async (swReg) => { if (!("backgroundFetch" in swReg)) { // Registration exists but backgroundFetch is unavailable: fall back. await regularDownloadFallback(filesToFetch); return; }
const bgFetch = await swReg.backgroundFetch.fetch( "my-fetch", filesToFetch, { title: "Episode 5: Interesting things.", icons: [ { sizes: "300x300", src: "/ep-5-icon.png", type: "image/png", }, ], downloadTotal: 60 * 1024 * 1024, }, ); });}A single fetch() call can request multiple files together (for example, a podcast episode and its artwork) as one user-visible package. It returns a promise that resolves with a BackgroundFetchRegistration.
Key interfaces
Section titled “Key interfaces”| Interface | Description |
|---|---|
ServiceWorkerRegistration.backgroundFetch |
Returns a reference to the BackgroundFetchManager for this registration. |
BackgroundFetchManager |
A map where the keys are background fetch IDs and the values are BackgroundFetchRegistration objects. |
BackgroundFetchRegistration |
Represents a single Background Fetch operation. |
BackgroundFetchRecord |
Represents an individual fetch request and response within a registration. |
Service worker events
Section titled “Service worker events”The service worker global scope defines four background-fetch event types. Exactly one of backgroundfetchsuccess, backgroundfetchfail, or backgroundfetchabort fires when an operation settles; backgroundfetchclick fires separately, only if the user activates the browser’s UI for the operation:
| Event | Fires when |
|---|---|
backgroundfetchsuccess |
All of the requests in a background fetch operation have succeeded. |
backgroundfetchfail |
At least one of the requests in a background fetch operation has failed. |
backgroundfetchabort |
The background fetch operation has been canceled by the user or the app. |
backgroundfetchclick |
The user has clicked on the browser’s UI for a background fetch operation. |
backgroundfetchsuccess and backgroundfetchfail are BackgroundFetchUpdateUIEvent instances; backgroundfetchabort and backgroundfetchclick are BackgroundFetchEvent instances. These four are not progress events — ongoing download progress is reported separately, through the progress event on BackgroundFetchRegistration, which fires whenever uploaded, downloaded, result, or failureReason changes.
Practical checklist
Section titled “Practical checklist”- Feature-detect with
"BackgroundFetchManager" in selfbefore callingfetch(), and branch to a fallback (not just a comment) when it’s unsupported. - Group files that belong together (e.g. media plus artwork) into a single
fetch()call so they appear as one user-visible download. - Set
downloadTotalto the total download size in bytes;BackgroundFetchRegistration.failureReasoncan report"download-total-exceeded"as one of its possible failure values, alongside"aborted","bad-status","fetch-error", and"quota-exceeded". - Handle
backgroundfetchsuccessandbackgroundfetchfailin the service worker to process or clean up after the download. - Handle
backgroundfetchclickto bring the user to a relevant screen when they tap the browser’s download notification. - Do not use Background Fetch for short tasks that don’t need user-visible progress — reach for it specifically for large, long-running downloads.
Cross-references
Section titled “Cross-references”- Periodic background sync — a related service worker API for background operations
Specifications
| Specification | Status |
|---|---|
| None. | |