Extensions

Browser extension development: a Manifest V3 guide

By Bilal Ahmed, Lead Chrome Extension Developer

Technically reviewed by Imran Shah, Cross-Browser Extension Lead

Published Last updated 8 min read

Stock photo: close-up of syntax-highlighted PHP template code on a monitor

If you are migrating an extension from Manifest V2 or starting a new one, three MV3 changes shape the architecture: a background service worker that Chrome stops after 30 seconds without activity, declarativeNetRequest in place of blocking webRequest, and a ban on remotely hosted code. This guide covers each one, then what differs in Chrome, Edge, Brave, Firefox and Safari. For the migration itself, step by step with before and after code, use our Manifest V2 to V3 migration checklist.

Where Manifest V2 stands

Chrome no longer runs Manifest V2 extensions. Chrome 139 (2025) removed MV2 support, including the enterprise policy that had kept it available, and the Chrome Web Store no longer lists MV2 extensions. Other Chromium-based browsers inherit the change unless they carry their own patches. Firefox is the exception: it still supports MV2 and keeps blocking webRequest in MV3. Any MV2 extension your users still need in Chrome has to be rebuilt on MV3.

What changed in Manifest V3

Manifest V2 compared with Manifest V3
AreaManifest V2Manifest V3
Background logicPersistent background page, kept alive continuouslyEvent-driven service worker, stopped when idle (Firefox uses non-persistent event pages)
Network blockingBlocking webRequest, arbitrary code per requestdeclarativeNetRequest, a bounded rules engine; Firefox also keeps blocking webRequest
Remote codeCommonly allowed, including remotely hosted scriptsNot allowed; all code ships inside the package
Host permissionsMixed into permissions; optional host permissions possible but rarely usedSeparate host_permissions; users can withhold site access, so code must handle not having it
Toolbar buttonbrowser_action and page_actionOne unified action API (chrome.action)
Script injectiontabs.executeScriptThe scripting API (chrome.scripting)

Each change closes a specific class of problem: background pages that held memory indefinitely, request-blocking code that could see and alter every request, and remotely hosted code that could change behavior after an extension had passed review.

Designing around the service worker lifecycle

Chrome stops an idle extension service worker after 30 seconds without events or extension API calls, and cuts off a single event or API call that runs longer than 5 minutes. Anything held only in a variable is gone. Two rules prevent most migration bugs:

  • Register every event listener synchronously at the top level of the worker script, not inside a promise or callback. Otherwise the events that wake the worker can be missed.
  • Persist state in chrome.storage or IndexedDB, and reload what you need each time the worker starts.
  1. Event wakes the worker

    A toolbar icon click (chrome.action), alarm, message or network event starts the service worker if it is not already running.

  2. Worker reloads its state

    On startup, the worker reads what it needs from chrome.storage or IndexedDB rather than assuming in-memory state survived.

  3. Work runs to completion

    Asynchronous work stays inside the event’s lifetime where possible, with chrome.alarms instead of setTimeout for anything long-running.

  4. Worker goes idle

    With no pending events, Chrome stops the worker after about 30 seconds. Nothing important should depend on it staying resident.

In practice: persist anything that matters, avoid long-lived timers in the background context, and use chrome.alarms for scheduled work instead of a setInterval that assumes the worker will still be running later.

What the service worker cannot do

A service worker has no DOM, no window object and no XMLHttpRequest (use fetch). For DOM parsing, audio playback or clipboard access, create an offscreen document with chrome.offscreen.

How a Manifest V3 extension fits together

Popup, side panel, options

The interface users see. Talks to the background through messages.

Service worker (background)

Handles events, alarms and network rules. Chrome stops it when idle, so state must live in storage.

Content script

Runs inside pages you choose. Can read and change the page, in an isolated JavaScript world.

Chrome extension APIs

tabs, storage, scripting, alarms, declarativeNetRequest, identity, native messaging

Web page

Content you do not control. Treat everything from it as untrusted input.

The popup, service worker and content scripts talk through messages. Only the content script touches the page.

Network rules without blocking webRequest

declarativeNetRequest replaces most blocking uses of webRequest with rules the browser evaluates itself: match a URL pattern, then block, redirect or modify headers. It is fast and keeps request contents away from your code, which is also why it cannot express everything a custom callback could.

  • Ad and tracker blocking by URL pattern maps onto declarativeNetRequest cleanly.
  • Rules that depend on request bodies, or on per-request decisions from external state, need a different design, often moved into a content script or a native messaging host.
  • Dynamic and session rules can be added and removed at runtime, so the rule set does not have to be static, but it is still a rules engine rather than code in the request path.
  • The rules engine has limits. Chrome guarantees each extension at least 30,000 static rules and caps dynamic and regular-expression rules, so check Chrome’s current limits before you design a large rule set.

Blocking webRequest has not disappeared everywhere. Chrome still allows it for extensions force-installed by enterprise policy, and Firefox allows it for all extensions.

Permissions: ask for less, at the right time

Manifest V3 separates host permissions from API permissions, and users can withhold site access after install, so your code has to handle not having it. Store reviewers and users both read the permissions list as a signal of how much an extension can see, and a narrower list is a better user experience and a smoother path through review.

A reasonable default approach

Request the narrowest permission that covers the current feature, use optional permissions for anything only some users need, and explain in the extension’s own UI why a permission prompt is about to appear before the browser shows it.

Chrome, Edge, Brave, Firefox and Safari are not one target

Manifest V3 was defined by Google for Chrome, and Edge and Brave inherit it through Chromium. Firefox and Safari implement their own versions of MV3, each with its own differences. Safari is the furthest outlier.

Where the same extension code needs to diverge
BrowserExtension platformWhat is different
Chrome, Edge and BraveManifest V3 (Chromium)The same core APIs; store policies and review times differ per vendor
FirefoxWebExtensions, MV2 and MV3MV3 background scripts run as event pages, not service workers; blocking webRequest is still available; addons.mozilla.org requires a data collection declaration in the manifest
SafariSafari Web ExtensionsShips inside a macOS or iOS app, built in Xcode or uploaded as a ZIP to App Store Connect’s Safari extension packager

If one extension needs to reach all of these, plan a shared core with a small per-browser packaging and manifest layer, rather than one manifest file that works unmodified everywhere. Our pages on Chrome, Microsoft Edge, Brave, Firefox and Safari extension development cover what changes for each target.

Before you submit for review

For the submission itself, from developer account to live listing, follow our step-by-step guide on how to publish a Chrome extension. Before you get there, check these:

  • Confirm the extension works with the service worker stopping between events, not just in a long local dev session where it happens to stay alive.
  • Read the permissions list as a store reviewer would, and remove anything no shipped feature uses.
  • Test the update path: users update in place, and a service worker rewrite that silently drops stored state on upgrade is a common source of support tickets.
  • Run a full QA pass on every browser you target, not just the one you built it in.

If you want an outside pass, our browser and extension QA and extension security audit teams do this before submission. If you are still planning the budget, see how much it costs to build a Chrome extension.

When an extension stops being enough

Extensions are the right tool for most browser feature work, but the platform has limits. If a requirement needs browser UI that extension APIs do not expose, network or process behavior that declarativeNetRequest cannot express, or policy enforcement across managed devices beyond what enterprise extension controls allow, the work usually belongs in a custom browser build instead. Our guide to Chromium covers how that decision plays out.

Final takeaway

Manifest V3 is stricter about background lifetime, network interception and remote code. Extensions designed around those limits from the start, rather than ported line by line, pass review with fewer round trips and are easier to maintain.

Frequently asked questions

How long does Chrome Web Store review take?

Most reviews finish within a few days, but Google does not guarantee a time. Broad host permissions, large code changes and updates to extensions with many users can take longer. Keep permission requests narrow and explained, and build review time into your release plan.

Can a Manifest V3 extension still run remote code?

No. All code must ship inside the extension package, and the extension’s content security policy blocks eval and remotely hosted scripts. Remote configuration (data, not code) is still allowed. For scripts that users write themselves, Chrome offers the userScripts API, which users must explicitly allow.

Should we keep a Manifest V2 build for Firefox?

Usually not. Firefox supports Manifest V3 as well, so one MV3 codebase with a small Firefox-specific manifest layer is easier to maintain. Keep an MV2 build for Firefox only if you depend on something its MV3 support does not offer.

Building or migrating an extension?

We build and migrate extensions for Chrome, Edge, Firefox, Brave and Safari, and can review an existing Manifest V2 codebase before you commit to a migration plan. Start with our Chrome extension development service.

Send a project brief