# Background Fetch: downloading large files that survive tab closure

> How the Background Fetch API hands a long-running download to the browser itself, which shows the user progress and a cancel control and wakes the service worker with an event once the download finishes.

**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

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

Feature-detect, then call `backgroundFetch.fetch()` on the service worker registration:

```js
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

| 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

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

- [ ] Feature-detect with `"BackgroundFetchManager" in self` before calling `fetch()`, 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 `downloadTotal` to the total download size in bytes; `BackgroundFetchRegistration.failureReason` can report `"download-total-exceeded"` as one of its possible failure values, alongside `"aborted"`, `"bad-status"`, `"fetch-error"`, and `"quota-exceeded"`.
- [ ] Handle `backgroundfetchsuccess` and `backgroundfetchfail` in the service worker to process or clean up after the download.
- [ ] Handle `backgroundfetchclick` to 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

- [Periodic background sync](/reference/service-worker/periodic-background-sync/) — a related service worker API for background operations