Chrome Extension Download Management — Developer Guide

5 min read

Download Management in Chrome Extensions

chrome.downloads API Overview

Starting Downloads

chrome.downloads.download({
  url: 'https://example.com/file.pdf',
  filename: 'custom-name.pdf',      // relative to Downloads folder
  saveAs: false,                      // true = show Save As dialog
  conflictAction: 'uniquify',        // 'overwrite' | 'uniquify' | 'prompt'
  headers: [{ name: 'Authorization', value: 'Bearer ...' }]
}, (downloadId) => {
  console.log('Started download:', downloadId);
});

Monitoring Download Progress

chrome.downloads.onChanged.addListener((delta) => {
  if (delta.state) {
    console.log(`Download ${delta.id}: ${delta.state.previous} -> ${delta.state.current}`);
    // States: "in_progress" | "interrupted" | "complete"
  }
  if (delta.filename) {
    console.log(`Saving to: ${delta.filename.current}`);
  }
});

chrome.downloads.onCreated.addListener((downloadItem) => {
  // New download started (by extension or user)
});

chrome.downloads.onDeterminingFilename.addListener((downloadItem, suggest) => {
  // Override filename before download begins
  suggest({ filename: 'custom/' + downloadItem.filename });
});

Searching & Querying Downloads

// Find downloads by query
chrome.downloads.search({
  query: ['report'],
  state: 'complete',
  limit: 10,
  orderBy: ['-startTime']
}, (results) => {
  results.forEach(item => {
    console.log(item.filename, item.fileSize, item.url);
  });
});

// Get specific download
chrome.downloads.search({ id: downloadId }, ([item]) => {
  console.log(item.state, item.bytesReceived, item.totalBytes);
});

Controlling Downloads

// Pause, resume, cancel
chrome.downloads.pause(downloadId);
chrome.downloads.resume(downloadId);
chrome.downloads.cancel(downloadId);

// Open completed download
chrome.downloads.open(downloadId);         // Opens file
chrome.downloads.show(downloadId);         // Shows in folder
chrome.downloads.showDefaultFolder();      // Opens download dir

// Remove from history (not disk)
chrome.downloads.erase({ id: downloadId });
// Delete from disk
chrome.downloads.removeFile(downloadId);

Download Progress Badge

// Show download progress on extension icon
chrome.downloads.onChanged.addListener((delta) => {
  if (delta.state?.current === 'in_progress') {
    updateBadge();
  }
});

async function updateBadge() {
  const active = await chrome.downloads.search({ state: 'in_progress' });
  chrome.action.setBadgeText({ text: active.length > 0 ? String(active.length) : '' });
  chrome.action.setBadgeBackgroundColor({ color: '#4CAF50' });
}

Storing Download History

import { createStorage, defineSchema } from '@theluckystrike/webext-storage';

const storage = createStorage(defineSchema({
  recentDownloads: 'string' // JSON array of {url, filename, date}
}), 'local');

// Save last 50 downloads
async function trackDownload(item) {
  const raw = await storage.get('recentDownloads');
  const list = raw ? JSON.parse(raw) : [];
  list.unshift({ url: item.url, filename: item.filename, date: Date.now() });
  await storage.set('recentDownloads', JSON.stringify(list.slice(0, 50)));
}

Common Patterns

Common Mistakes

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.