Supporting Edge, Opera and Brave

Ship an MV3 Chrome extension to Chromium-based browsers: Edge Add-ons ids and review, Opera's add-ons store, Brave and Vivaldi installing from the Chrome Web Store, and the API differences that still matter.

Published October 2, 2026 Updated October 2, 2026 7 min read
Table of Contents

Your Chrome extension already runs in Edge, Opera, Brave and Vivaldi — they are all Chromium, and most of their users can install from the Chrome Web Store. So why do support tickets mention Edge-specific sign-in failures, Brave users report a feature that never works, and an enterprise customer insists on the Microsoft Edge Add-ons store? Chromium browsers share an engine but not identity services, policy defaults, privacy features or stores. Supporting them well is mostly about knowing those differences. This guide covers each. It belongs to cross-browser API compatibility.

Same engine, different products

Every Chromium-based browser implements the extension APIs from the shared Chromium codebase, so chrome.storage, tabs, scripting, declarativeNetRequest, sidePanel and the rest behave as in Chrome at the same Chromium version. Differences come from what each vendor adds, removes or configures. Google-specific services are the biggest: chrome.identity.getAuthToken is backed by the Google account signed into Chrome and is unavailable or different elsewhere. Privacy-focused browsers change defaults — Brave’s Shields block trackers and some third-party requests that your extension’s pages might make. Stores differ: Edge has its own Add-ons store with its own extension ids; Opera has an add-ons site and can also install from the Chrome Web Store with a helper; Brave and Vivaldi install directly from the Chrome Web Store. And Chromium versions lag Chrome’s by days to weeks, which matters if you depend on brand-new APIs.

Chromium browsers at a glanceStore, extension id source, getAuthToken support, notable defaults and version cadence for Edge, Opera, Brave and Vivaldi.BrowserStoreExtension idgetAuthTokenNotable differenceEdgeEdge Add-ons (+ C…Own id on Edge st…No Google accountEnterprise policy…OperaOpera add-ons (+ …Own id on Opera s…NoSidebar featuresBraveChrome Web StoreSame as ChromeNoShields block req…VivaldiChrome Web StoreSame as ChromeNoCustom UI chrome
The engine is shared; identity, stores and privacy defaults are not.

Step-by-step: first-class support for Chromium browsers

1. Replace getAuthToken with launchWebAuthFlow

1// sw.js — works in every Chromium browser and in Firefox
2export async function signIn() {
3  const redirect = chrome.identity.getRedirectURL();          // https://<id>.chromiumapp.org/
4  const url = new URL("https://accounts.example.com/oauth/authorize");
5  url.search = new URLSearchParams({ client_id: CLIENT_ID, response_type: "code", redirect_uri: redirect,
6                                     code_challenge: await pkceChallenge(), code_challenge_method: "S256" });
7  const result = await chrome.identity.launchWebAuthFlow({ url: url.href, interactive: true });
8  return exchangeCode(new URL(result).searchParams.get("code"));
9}

Execution context: the service worker. getAuthToken depends on the Google account signed into Chrome and does not work the same way in Edge, Brave or Opera. launchWebAuthFlow works in all of them because it runs a standard OAuth flow in a browser-managed window. Each store’s build has a different extension id and therefore a different redirect URL — register all of them with your OAuth provider. See choosing between getAuthToken and launchWebAuthFlow.

2. Account for different extension ids per store

1// shared/ids.js
2export const EXTENSION_IDS = {
3  chromeWebStore: "abcdefghijklmnopabcdefghijklmnop",
4  edgeAddons:     "ponmlkjihgfedcbaponmlkjihgfedcba",
5  operaAddons:    "mnopabcdefghijklmnopabcdefghijkl",
6};

Execution context: shared configuration for your website and backend. Anything that recognises the extension by id — externally_connectable calls from your website, native messaging host manifests, OAuth redirect allow-lists, server-side origin checks — must list every store’s id. A user who installed from Edge Add-ons has a different id from one who installed the same build from the Chrome Web Store in Edge.

One build, several store identitiesThe same package is uploaded to the Chrome Web Store, Edge Add-ons and Opera add-ons; each store assigns its own id; your website, OAuth provider and native host must recognise all of them.Chrome Web Storeid AEdge Add-onsid BOpera add-onsid Cevery external system needs all threeOAuth redirects<id>.chromiumapp.orgWebsite messagingexternally_connectableNative hostallowed_origins
One codebase, one package, three ids to register everywhere ids matter.

3. Publish to Edge Add-ons

1# Edge Add-ons API (v1.1) — upload a new package for an existing product
2curl -X POST "https://api.addons.microsoftedge.microsoft.com/v1/products/$PRODUCT_ID/submissions/draft/package" \
3  -H "Authorization: ApiKey $EDGE_API_KEY" -H "X-ClientID: $EDGE_CLIENT_ID" \
4  -H "Content-Type: application/zip" --data-binary @dist/chrome.zip

Execution context: CI with Partner Center API credentials. The same zip you upload to the Chrome Web Store usually works unchanged. Edge review is separate and has its own policies, notably around privacy disclosures and search-setting changes. Enterprises that manage Edge often allow only Edge Add-ons sources, so a listing there matters for business users. See publishing to Microsoft Edge Add-ons.

4. Test with Brave’s Shields on

1// Detect Brave without user-agent sniffing
2const isBrave = (await navigator.brave?.isBrave?.()) === true;
3if (isBrave) console.info("[env] Brave detected — check Shields interaction with extension pages");

Execution context: an extension page. Brave’s Shields can block requests from extension pages to third-party analytics or CDNs, and its fingerprinting protections alter some web APIs’ results. Detection is useful for diagnostics, not for changing behaviour. Test your extension’s network calls, especially from popups and options pages, with Shields at their default and aggressive settings.

A Chromium-browser bug report: where to lookDecision tree for triaging a bug reported only in one Chromium browser: sign-in problems point to getAuthToken, blocked requests to privacy features, id mismatches to store-specific ids, and new-API errors to version lag.What fails?sign-inIdentity servicegetAuthTokenlaunchWebAuthFlowregister redirectrequests blockedPrivacy featuresBrave ShieldsFirst-party endpointsfewer third partiessite can't talk to extDifferent idEdge/Opera storeList all idssite + backendAPI undefinedVersion lagolder ChromiumFeature-detectset minimum
Most single-browser bugs trace back to one of four differences.

5. Feature-detect new APIs because of version lag

1if (chrome.sidePanel?.setOptions) {
2  await chrome.sidePanel.setOptions({ path: "panel.html", enabled: true });
3} else {
4  await chrome.action.setPopup({ popup: "panel.html" });
5}

Execution context: the service worker. Each browser ships a Chromium version on its own schedule, and some vendors disable or modify specific features. A feature added in Chrome last month may not exist yet in Opera. minimum_chrome_version applies to every Chromium browser (they report Chromium’s version), so it gates installation consistently; feature detection covers the rest.

6. Write support documentation per browser

Users in non-Chrome browsers often cannot find the equivalent of Chrome’s menus: where the extensions page is (edge://extensions, brave://extensions, opera://extensions), how to pin the toolbar icon, where site access controls live. A short per-browser section in your help pages — with the browser’s own URL schemes and screenshots — removes most “it does not work in Edge” tickets.

7. Track usage by browser

1const brand = navigator.userAgentData?.brands
2  ?.map((b) => b.brand)
3  .find((b) => /Edge|Opera|Brave|Vivaldi|Chrome/.test(b)) ?? "other";

Execution context: the service worker, feeding consented, aggregate usage metrics. userAgentData.brands lists the browser’s brand (Brave reports itself here only in some versions). Knowing that, say, 18% of active users are on Edge justifies the time to maintain an Edge Add-ons listing and test there.

Common mistakes

  • Relying on getAuthToken. Sign-in breaks for every non-Chrome Chromium user.
  • One id in your backend. Edge and Opera store installs have different ids.
  • Ignoring privacy features. Brave blocks third-party requests your extension pages may need.
  • Assuming the latest Chromium. Vendors lag; feature-detect new APIs.
  • Chrome-only help docs. Users cannot find the equivalent menus.

Cross-browser variation

  • Edge: Edge Add-ons store with its own id and review; strong enterprise policy support; no Google identity.
  • Opera: Opera add-ons store; can also install from the Chrome Web Store with a helper extension; its own sidebar features.
  • Brave / Vivaldi: install from the Chrome Web Store with Chrome’s id; Brave’s Shields and fingerprinting protections affect web APIs and requests.

Verification

  1. Install from each store and confirm chrome.runtime.id matches the id registered with your OAuth provider and website.
  2. Sign in from Edge, Brave and Opera using launchWebAuthFlow.
  3. Test the popup and options page in Brave with Shields on; confirm no blocked requests break features.
  4. Load the extension in the oldest Chromium version among your target browsers and confirm feature detection handles missing APIs.

FAQ

Do I need separate builds for Edge or Opera?

Usually not. The same package works; only the store listing and the resulting id differ.

Can Edge users install from the Chrome Web Store?

Yes, after enabling “Allow extensions from other stores” in Edge. Many enterprise policies disable that, which is why an Edge Add-ons listing matters.

Does Brave support all MV3 APIs?

Brave follows Chromium closely, but some features are modified or disabled for privacy. Feature-detect and test.

Other Core APIs & Cross-Browser Data Management Resources