All browsers have the same baseline support for namespace (browser.*) and promises:
- Firefox and Safari supported the
browser.*namespace and promises from inception. - Chromium-based browsers (such as Chrome, Opera, and Microsoft Edge) introduced promises with Manifest V3 in their
chrome.*namespace. Support for thebrowser.*namespace was added in 2026, along with promise support in all asynchronous methods.
While work continues to standardize the browser extension APIs, differences remain among the Firefox, Safari, and Chromium-based browsers. These differences, summarized on this page, include:
- API support: JavaScript API support varies among browsers.
- Manifest key support: Support for
manifest.jsonkeys differs among browsers. - Variations due to differences in browser behavior.
For information on building an extension that works on multiple browsers and accounts for these differences, see Building a cross-browser extension.
Namespace and asynchronous methods
You reference all extensions APIs using a namespace. For example, browser.alarms.create({delayInMinutes}); creates an alarm that goes off after the time specified in delayInMinutes.
All major browsers now support the browser namespace and promises for asynchronous methods. Chromium-based browsers (such as Chrome, Opera, and Microsoft Edge) originally used the chrome namespace with callbacks. They progressively included support for promises in the chrome namespace, completing the full implementation along with support for the browser namespace in mid-2026.
As a porting aid, Firefox supports chrome using callbacks, alongside browser using promises. This means that many older Chrome extensions work in Firefox without changes, unless they use Chrome-specific APIs that don’t exist in Firefox.
To target older Chromium-based browsers with extensions written using the browser namespace and promises, use the webextension-polyfill.
Promises
JavaScript provides several ways to handle asynchronous events. The extensions API standard is to use the promise object. The promise approach offers significant advantages when handling chained asynchronous event calls.
Firefox has always used the promise object. Chromium-based browsers historically supported callbacks through the chrome namespace, which is why many extensions and samples use callbacks. Chromium-based browsers now support promises through the browser namespace, so you no longer need to design around this for current browser versions.
So, extensions and samples written against the older, callback-only Chrome APIs use the chrome namespace, with callbacks to return values, and runtime.lastError to communicate errors:
function logCookie(c) {
if (chrome.extension.lastError) {
console.error(chrome.extension.lastError);
} else {
console.log(c);
}
}
chrome.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie);
The equivalent code using the browser namespace and promises:
function logCookie(c) {
console.log(c);
}
function logError(e) {
console.error(e);
}
var setCookie = browser.cookies.set({ url: "https://developer.mozilla.org/" });
setCookie.then(logCookie, logError);
If you are unfamiliar with how JavaScript can handle asynchronous events or promises, take a look at Getting to know asynchronous JavaScript: Callbacks, Promises and Async/Await or the MDN Using promises page.
API coverage
The differences in the extensions API function implementations among the browsers fall into two broad categories:
-
Variations in the support for features within a function. For example, at the time of writing, Firefox doesn’t support the notification function method
onButtonClickedwhile Firefox is the only browser that supportsonShown. -
Proprietary functions, supporting browser-specific features. For example, at the time of writing, containers is a Firefox-specific feature supported by the
contextualIdentitiesfunction.
Full details of the differences in API support are provided in Browser support for JavaScript APIs on MDN. Where there are caveats regarding support for an API feature, there is a drop down below the version number that expands to show details of the caveat. The API features reference page also explains the caveat.
Manifest keys
The differences in the supported manifest.json keys among the browsers fall broadly into two categories:
- Extension information attributes. For example, at the time of writing, Firefox and Opera include the developer key enabling the addition of details about the developer of the extension, as well as the author, to be recorded.
- Extension features. For example, at the time of writing, Edge did not support the commands key that enables shortcut keys to be defined for an extension.
Full details of the differences in key support are provided in the Browser compatibility section of the manifest.json page on MDN. Where there are caveats regarding support for a manifest key, there is a drop down below the version number that expands to show details of the caveat. The manifest key reference page also explains the caveat.
Variations due to browser behavior
While a web extension API may be compatible between Firefox and the Chromium-based browsers, variations in the browser behavior may mean that the outcome for an extension or to the user are not identical.
Cases where the extension behavior may be affected include:
- URLs in CSS: Firefox resolves URLs in injected CSS files relative to the CSS file itself, rather than to the page it's injected into.
- Web accessible resources: These assets use a URL with a browser-specific scheme where the authority is an extension-specific identifier, where:
- Firefox uses the internal UUID, a unique identifier assigned randomly to an extension when it's installed.
- Safari uses the internal ID, a unique identifier assigned randomly to an extension per browser session.
- Extensions for Chromium-based browsers use an ID assigned to the extension when it is published. However, the key property can be used to set this ID.
- Content script requests context: In Chromium-based browsers, when a request is called (for example, using
fetch())to relative a URL, such as/api, from a content script, it is sent tohttps://example.com/api. Firefox uses absolute URLs. - Native messaging: there are variations in the command-line arguments, manifest key names, and manifest location between Firefox and the Chromium-based browsers.
For example, in Firefox notifications are cleared immediately when the user clicks them. This is not the case in Chrome.
Details of these variations are documented as part of the API feature reference pages.
More information
You can find more detailed information about the differences in the supported browser extensions API features in:
Up Next
Develop
Browser Extension Development Tools
Develop
Choosing a Firefox version for extension development
Develop