Chrome Extension Tabs API — Complete Guide to Managing Browser Tabs

11 min read

Chrome Extension Tabs API — Complete Guide to Managing Browser Tabs

The Chrome Tabs API is one of the most frequently used APIs in extension development. It provides powerful methods for querying, creating, updating, and removing browser tabs, along with event listeners to respond to tab state changes. This guide covers all the essential operations you’ll need to build feature-rich extensions that manage tabs effectively.

Understanding Tab Objects

Each tab in Chrome is represented by a Tab object containing properties like id, windowId, title, url, active, pinned, favIconUrl, status, and index. Tab IDs are unique within a browser session but may be reused after a tab closes. Always handle cases where a tab ID might no longer be valid.

Querying Tabs with chrome.tabs.query

The chrome.tabs.query() method is your primary tool for finding tabs that match specific criteria. It returns an array of Tab objects based on the query parameters you provide.

// Get all tabs in the current window
chrome.tabs.query({ currentWindow: true }, (tabs) => {
  tabs.forEach(tab => console.log(tab.title, tab.url));
});

// Get only active tabs
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
  const activeTab = tabs[0];
  console.log('Active tab:', activeTab.title);
});

// Query tabs by multiple properties
chrome.tabs.query({
  url: 'https://*.google.com/*',
  pinned: false,
  status: 'complete'
}, (tabs) => {
  console.log(`Found ${tabs.length} loaded Google tabs`);
});

// Using async/await with manifest V3
const tabs = await chrome.tabs.query({ audible: true });

Common query properties include: active, pinned, audible, muted, incognito, highlighted, currentWindow, lastFocusedWindow, status, title, url, and windowId.

Creating New Tabs

Use chrome.tabs.create() to open new tabs with specified properties:

// Basic tab creation
chrome.tabs.create({ url: 'https://example.com' });

// Open in specific position
chrome.tabs.create({ url: 'https://example.com', index: 0 });

// Open in a new window
chrome.tabs.create({ url: 'https://example.com', windowId: newWindowId });

// Create and activate
chrome.tabs.create({ url: 'https://example.com', active: true });

// Create pinned tab
chrome.tabs.create({ url: 'https://example.com', pinned: true });

// Open with custom title (via HTML file)
chrome.tabs.create({ url: 'chrome-extension://extId/popup.html' });

// Callback returns the created tab
chrome.tabs.create({ url: 'https://example.com' }, (tab) => {
  console.log('Created tab ID:', tab.id);
});

Updating Tabs

The chrome.tabs.update() method modifies existing tab properties:

// Navigate tab to new URL
chrome.tabs.update(tabId, { url: 'https://new-url.com' });

// Activate a tab
chrome.tabs.update(tabId, { active: true });

// Pin or unpin a tab
chrome.tabs.update(tabId, { pinned: true });

// Mute/unmute audio
chrome.tabs.update(tabId, { muted: true });

// Change tab's title (only if extension has permissions)
chrome.tabs.update(tabId, { title: 'New Title' });

// Set favicon (extension-provided only)
chrome.tabs.update(tabId, { favIconUrl: 'path/to/icon.png' });

You can also use chrome.tabs.reload() to refresh a tab and chrome.tabs.goBack() / chrome.tabs.goForward() for navigation history.

Removing Tabs

Close tabs using chrome.tabs.remove():

// Close single tab
chrome.tabs.remove(tabId);

// Close multiple tabs
chrome.tabs.remove([tabId1, tabId2, tabId3]);

// Close all tabs in a window
chrome.tabs.query({ windowId: targetWindowId }, (tabs) => {
  const tabIds = tabs.map(t => t.id);
  chrome.tabs.remove(tabIds);
});

Listening to Tab Activations

The chrome.tabs.onActivated event fires when the user switches between tabs:

// Basic activation listener
chrome.tabs.onActivated.addListener((activeInfo) => {
  console.log('Switched to tab:', activeInfo.tabId);
  console.log('Window ID:', activeInfo.windowId);
});

// Using async handler in manifest V3
chrome.tabs.onActivated.addListener(async (activeInfo) => {
  const tab = await chrome.tabs.get(activeInfo.tabId);
  console.log('New active tab URL:', tab.url);
});

Note that onActivated only fires when switching between tabs within the same window. Use chrome.windows.onFocusChanged to detect window switches.

Listening to Tab Updates

The chrome.tabs.onUpdated event fires when a tab’s properties change:

// Listen for all tab updates
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  console.log('Tab updated:', tabId);
  console.log('Changed properties:', changeInfo);
  console.log('Current tab state:', tab.status, tab.url);
});

// Filter by specific changes
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  // Page finished loading
  if (changeInfo.status === 'complete') {
    console.log('Page loaded:', tab.url);
  }
  
  // URL changed (including redirects)
  if (changeInfo.url) {
    console.log('URL changed to:', changeInfo.url);
  }
  
  // Title updated
  if (changeInfo.title) {
    console.log('Title updated:', changeInfo.title);
  }
});

// Track specific tabs
const watchedTabId = 123;
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (tabId === watchedTabId && changeInfo.status === 'complete') {
    console.log('Target tab finished loading');
  }
});

The changeInfo object contains only the properties that changed. Common properties include: status, url, title, favIconUrl, pinned, muted, and audible.

Moving and Reordering Tabs

Use chrome.tabs.move() to reposition tabs within or between windows:

// Move tab to specific position in same window
chrome.tabs.move(tabId, { index: 0 });

// Move tab to another window (opens at end by default)
chrome.tabs.move(tabId, { windowId: targetWindowId, index: 0 });

// Move multiple tabs
chrome.tabs.move([tabId1, tabId2], { index: 5 });

// Callback returns moved tab(s)
chrome.tabs.move(tabId, { index: 0 }, (tabs) => {
  console.log('Tab moved to index:', tabs[0].index);
});

Note that the index parameter is zero-based. Setting index: -1 places the tab at the end of the window.

Working with Tab Groups

Chrome’s Tab Groups API (available in Chrome 87+) allows you to organize tabs into color-coded groups:

// Create a new tab group
chrome.tabs.group({ tabIds: [tabId1, tabId2] }, (groupId) => {
  console.log('Created group:', groupId);
});

// Add tabs to existing group
chrome.tabs.group({ groupId: existingGroupId, tabIds: [newTabId] });

// Remove tabs from group (ungroup)
chrome.tabs.ungroup([tabId1, tabId2]);

// Get group details
chrome.tabGroups.get(groupId, (group) => {
  console.log('Group color:', group.color);
  console.log('Group title:', group.title);
});

// Update group properties
chrome.tabGroups.update(groupId, {
  title: 'Work Tabs',
  color: 'blue'
});

// Move group (all tabs move together)
chrome.tabs.moveInGroup(groupId, { index: 0 });

Tab group colors include: grey, blue, red, yellow, green, pink, purple, cyan, and orange.

Practical Examples

Close Duplicate Tabs

chrome.tabs.query({}, (tabs) => {
  const urlCounts = {};
  tabs.forEach(tab => {
    const url = tab.url;
    if (!urlCounts[url]) urlCounts[url] = [];
    urlCounts[url].push(tab.id);
  });
  
  Object.values(urlCounts).forEach(tabIds => {
    if (tabIds.length > 1) {
      // Keep first, close duplicates
      chrome.tabs.remove(tabIds.slice(1));
    }
  });
});

Tab Switcher with Preview

chrome.tabs.onActivated.addListener(async (activeInfo) => {
  const tab = await chrome.tabs.get(activeInfo.tabId);
  // Update extension popup or side panel with tab preview
  sendToSidePanel({ type: 'tab-switch', tab });
});

Best Practices

Always request only the minimum permissions your extension needs. The tabs permission grants access to sensitive URL and title data for all tabs, while activeTab provides temporary access only when the user invokes your extension. Use chrome.tabs.query() with specific filters instead of fetching all tabs and filtering in JavaScript. Handle the asynchronous nature of all Tabs API methods properly, especially in manifest V3 where callbacks are replaced with promises in many cases. Always check if a tab still exists before performing operations, as tab IDs can become invalid between the time you query them and when you use them.

Conclusion

The Chrome Tabs API provides a comprehensive set of tools for managing browser tabs in your extensions. Master these core operations—querying, creating, updating, removing, and listening to events—and you’ll be able to build powerful tab management features that significantly enhance user productivity.

No previous article
No next article