Skip to main content
Build a small download manager with the downloads API. The background script starts and cancels downloads, and a popup lists live progress.

What you build

Manifest

manifest.json

Start and cancel downloads

The filename is relative to the browser’s downloads directory. Subfolders are allowed, absolute paths and .. segments are not.
background.js
The API also offers pause, resume, and erase for full manager behavior.

Show progress in the popup

onChanged fires for state transitions, but it does not stream byte counts. Poll search() for items in progress and read bytesReceived and totalBytes from the results.
popup.html
popup.js

Can an extension download in parallel?

The browser owns the network queue, and an extension cannot change that. Chromium already runs several downloads at once but caps concurrent connections per server, and it queues the rest. An extension cannot raise those limits, and it cannot split one file into segments like a download accelerator. What an extension can do is orchestrate: start a batch with several download() calls, watch onChanged, and start the next item when one completes. That gives you an ordered queue with progress, which is what most “parallel download” requests actually need.

Run it

Trigger a download from the background console, and open the popup to watch progress.

Firefox notes

  • Firefox supports the same API as browser.downloads with promises, and the chrome.downloads alias also works.
  • Firefox does not support chrome.downloads.setUiOptions, which hides Chrome’s download UI.
  • The onChanged delta shape and the search() query shape match across both browsers.
See Cross-browser compatibility for the shared API surface.

Start from a template

The action template ships the background plus toolbar-popup layout that this recipe uses.
Repository: extension-js/examples/action

Best practices

  • Namespace filenames under one folder, so users can find your files.
  • Stop the setInterval poll when no download is in progress.
  • Handle interrupted state and surface item.error to the user.
  • Keep saveAs: false only for files that the user explicitly requested.
  • Use erase to clean history entries, not to delete files.

Next steps