· 6 min read
Manifest V3 Chrome Extensions: What Actually Changed
Background pages are gone, remote code is banned, and blocking webRequest is out. Here is what Manifest V3 changes and how to migrate without breaking your extension.
If you are porting an extension from Manifest V2, most of the pain lands in four places.
Background pages became service workers
There is no long-lived background page anymore. Your service worker starts on an event and gets torn down when idle, so any state kept in a module-level variable will disappear. Persist state in `chrome.storage.session` or `chrome.storage.local` and read it back at the top of each handler.
No remote code
You cannot load scripts from a CDN or evaluate strings. Everything must be bundled inside the extension package. If you relied on a hosted config, fetch it as data (JSON), never as code.
webRequest is mostly read-only
Blocking `webRequest` is replaced by `declarativeNetRequest`, where you register static or dynamic rules and the browser applies them. It is faster and more private, but you cannot inspect a request and decide in JavaScript.
Permissions are split
Host permissions moved out of `permissions` into `host_permissions`, and users can grant them per site. Design for the case where you have none yet and request them at the point of use with `chrome.permissions.request`.
A practical migration order
Start with the manifest itself, then move background logic into an event-driven service worker, replace blocking network code with declarative rules, and finally re-test the flows that depend on host access. Ship to an unlisted test build before touching your public listing.