activeTab permission

The activeTab permission gives an extension temporary access to the tab a user is working in. It is granted in response to an explicit user action, such as clicking the extension's toolbar button. Access is limited to that tab and lasts until the user navigates elsewhere.

Its purpose is to enable extensions to fulfill the common use case of "do something to the current page when the user asks", without the extension needing broad privileges. For example, consider an extension that wants to run a script in the current page when the user clicks its toolbar button. Without activeTab, the extension would have to request the host permission <all_urls>, which gives it far more power than it needs: the ability to execute scripts in any tab, at any time, rather than in the active tab only and only in response to a user action.

Because activeTab provides limited access, browsers don't display a permission warning when the user installs the extension.

Request the activeTab permission

Your extension requests activeTab using the permissions manifest key:

json
"permissions": ["activeTab"]

activeTab is an API permission, not a host permission.

It's also possible to include activeTab in optional_permissions and request it at runtime using permissions.request(). It's one of the permissions granted silently, without a user prompt.

Note: activeTab grants privileges for a tab. It doesn't, by itself, grant access to an API. For example, to inject a script, your extension needs the "scripting" permission to use the scripting API.

How activeTab is granted

The browser grants activeTab when the user interacts with the extension. These interactions are known as user actions and include the user:

Usually, the tab granted activeTab is the active tab. There is one exception: an extension can use the menus API to create a menu item that displays when the user context-clicks a tab in the tab strip. If the user selects this menu item, activeTab is granted for the tab clicked, even if it isn't the active tab.

What activeTab grants

While activeTab is granted for a tab, the extension can:

Scope of the access

activeTab grants scripting access to the top-level page in the tab and to same-origin frames within it. Running scripts or modifying styles inside cross-origin frames requires additional host permissions.

The restrictions and limitations that apply to particular sites and URI schemes also apply to activeTab. Some special pages don't allow script injection, including reader view, view-source, the PDF viewer, and other built-in browser UI pages.

When the access ends

The extension can only access the tab, or the data, that existed when the user interaction occurred. When the tab navigates away, the extension loses permission to access it. This means that the extension must complete its work with the tab, or capture the data it needs, during the granted period. If the extension needs access again, the user must repeat the user action.

The point at which access ends varies by browser browser_compatibility.

Example

This extension injects a script into the current page when the user clicks its toolbar button. It needs no host permissions.

manifest.json:

json
{
  "manifest_version": 3,
  "name": "Heading highlighter",
  "version": "1.0",
  "permissions": ["activeTab", "scripting"],
  "action": {
    "default_title": "Highlight headings"
  },
  "background": {
    "scripts": ["background.js"]
  }
}

background.js:

js
function highlightHeadings() {
  for (const heading of document.querySelectorAll("h1, h2, h3")) {
    heading.style.backgroundColor = "yellow";
  }
}

browser.action.onClicked.addListener((tab) => {
  // activeTab is granted for `tab` because the user clicked the toolbar button.
  browser.scripting.executeScript({
    target: { tabId: tab.id },
    func: highlightHeadings,
  });
});

The same click also makes the privileged tab properties readable, so tab.url and tab.title hold real values rather than being undefined.

Further examples

These further examples showing the use of declare the activeTab permission are available in the repository of example extensions at https://github.com/mdn/webextensions-examples. :

Example How activeTab is used
apply-css A page action click grants access to inject or remove CSS on the active tab (tabs.insertCSS() and tabs.removeCSS()).
beastify A browser action click grants access for scripting.executeScript() and scripting.insertCSS() on the active tab.
context-menu-copy-link-with-types A context menu click on a link unlocks access to the page so the link can be copied to the clipboard.
history-deleter Reads the active tab's URL to determine the domain whose history is to be deleted.
menu-demo A menu item click unlock the active tab for the menu manipulation demo.
menu-remove-element A menu item click unlocks page access to inject a script that removes the element under the cursor.

Browser compatibility

Firefox, Safari, and Chromium-based browsers, including Chrome and Edge, support activeTab. However, when it's granted, what it enables, and when it's revoked vary.

Actions that grant activeTab

User action Chrome Firefox Safari
Clicking the extension's toolbar button Yes Yes Yes
Selecting the extension's context menu item Yes Yes Yes
Activating the extension's keyboard shortcut Yes From Firefox 63 Yes
Accepting an address bar (omnibox) suggestion Yes From Firefox 142 No, Safari doesn't support the omnibox API
Selecting a menu item on a tab in the tab strip From Chrome 150 From Firefox 63 No, Safari doesn't support the tab value of menus.ContextType

Capabilities granted

Capability Chrome Firefox Safari
Programmatic script and stylesheet injection Yes Yes Yes
Sensitive tabs.Tab properties (url, title, favIconUrl) Yes Yes Yes
tabs.captureVisibleTab() Yes From Firefox 126 Yes
Intercepting the tab's network requests with the webRequest and declarativeNetRequest APIs Yes, for the tab's main frame origin No (Firefox bug 1617479) Unknown

Also, the access browsers grant with activeTab differs:

  • Firefox and Safari grant access to the active tab only.
  • Chrome grants the host permissions derived from the tab's URL.

Chrome's logic can provide more access than Firefox's, for example:

  • Another tab with the same origin can be scripted in Chrome, but not in Firefox.
  • An extension script (such as a background script or a popup's script) can make a cross-origin request to the tab's URL in Chrome, but not in Firefox.
  • The cookies API requires host permissions to access cookies for specific domains. Chrome allows this with activeTab, while Firefox doesn't.

This list isn't exhaustive.

When access is revoked

In all browsers, closing the tab revokes access. However, same-document navigations, such as a fragment (hash) change or a History.pushState() call, don't: the document and its origin are unchanged, so access is preserved.

For navigations that load a new document, the behavior differs:

  • Chrome: access persists while the tab stays on the same origin, including across reloads. It's revoked when the tab navigates to a different origin.
  • Safari: access persists while the tab stays on the same host, including across reloads. It's revoked when the tab navigates to a different host.
  • Firefox: access is tied to the document that was in the tab when the user action occurred. Loading a new document, including on a reload or a same-origin navigation, ends the access, and the user must repeat the user action. If that document returns from the back/forward cache, its access is restored.

Other differences

  • Permission prompts: Firefox and Chrome grant an extension's requested host permissions on installation, so activeTab avoids an install-time warning. Safari, by contrast, defaults host permissions to "ask", and prompts the user the first time the extension tries to access a site, offering Allow for One Day or Always Allow. Using activeTab avoids this prompt, as Safari treats the user's interaction with the extension as the grant.
  • Manifest V2 and V3: activeTab works the same way in both manifest versions in all browsers except that in Firefox Manifest V3 activeTab doesn't enable scripting.executeScript in an iframe with a different origin (see Bug 1839200). In Manifest V3, the scripting API replaces tabs.executeScript() and tabs.insertCSS(), and the "scripting" permission is needed alongside activeTab.

See also