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

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
| Area | Manifest V2 | Manifest V3 |
|---|---|---|
| Background logic | Persistent background page, kept alive continuously | Event-driven service worker, stopped when idle (Firefox uses non-persistent event pages) |
| Network blocking | Blocking webRequest, arbitrary code per request | declarativeNetRequest, a bounded rules engine; Firefox also keeps blocking webRequest |
| Remote code | Commonly allowed, including remotely hosted scripts | Not allowed; all code ships inside the package |
| Host permissions | Mixed into permissions; optional host permissions possible but rarely used | Separate host_permissions; users can withhold site access, so code must handle not having it |
| Toolbar button | browser_action and page_action | One unified action API (chrome.action) |
| Script injection | tabs.executeScript | The 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.storageor IndexedDB, and reload what you need each time the worker starts.
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.
Worker reloads its state
On startup, the worker reads what it needs from chrome.storage or IndexedDB rather than assuming in-memory state survived.
Work runs to completion
Asynchronous work stays inside the event’s lifetime where possible, with chrome.alarms instead of setTimeout for anything long-running.
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.
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.
| Browser | Extension platform | What is different |
|---|---|---|
| Chrome, Edge and Brave | Manifest V3 (Chromium) | The same core APIs; store policies and review times differ per vendor |
| Firefox | WebExtensions, MV2 and MV3 | MV3 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 |
| Safari | Safari Web Extensions | Ships 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.
