Quick answer
Manifest V2 extensions no longer run in Chrome: Chrome 138 was the last version that could load them, and the Chrome Web Store removed the remaining ones on August 31, 2026. Paste your MV2 manifest.json into Playxoft's free MV2 to MV3 Converter to get a Manifest V3 manifest with action, a background service worker, host_permissions and object-form resources and policy, plus a side-by-side diff and a checklist of the code changes you still need.
- Instant MV2 to MV3 conversion
- Side-by-side diff
- Host permissions split out
- Policy made MV3-safe
- Service worker loader
- Code change checklist
How to use the MV2 to MV3 Converter
- 1Paste your Manifest V2 manifest.json, drop the file on the editor, or click Load example.
- 2Copy or download the converted Manifest V3 manifest from the right-hand panel.
- 3Read What changed and the side-by-side diff to see every edit and why.
- 4If the converter created a service-worker.js loader, download it into your extension folder.
- 5Work through the code checklist: items marked for your extension are the ones its manifest says you need.
- 6Load the extension unpacked and test it, then check the result in the Manifest V3 validator.
When did Manifest V2 stop working?
Google phased Manifest V2 out over four years. Today no version of Chrome runs it:
| Date | What happened |
|---|---|
| January 2022 | Chrome Web Store stops accepting new public or unlisted MV2 extensions |
| June 2022 | No new private MV2 extensions |
| June 3, 2024 | Phase-out starts: warning banners, Featured badges removed |
| October 9, 2024 | MV2 extensions start being disabled in stable Chrome |
| March 31, 2025 | MV2 disabled by default on all channels, users can re-enable |
| July 24, 2025 | Chrome 138 disables MV2 everywhere; Chrome 139 drops the enterprise policy |
| August 31, 2026 | All remaining MV2 extensions removed from the Chrome Web Store |
Existing installs on Chrome 138 or earlier keep running, but they can't be updated or reinstalled. Source: Chrome's Manifest V2 support timeline.
What does the converter change in manifest.json?
It applies every manifest change in Chrome's migration guide:
| Manifest V2 | Manifest V3 |
|---|---|
"manifest_version": 2 | "manifest_version": 3 |
browser_action or page_action | action |
background.scripts or page, persistent | background.service_worker (one file) |
Host patterns in permissions | host_permissions |
Host patterns in optional_permissions | optional_host_permissions |
web_accessible_resources as file paths | Objects with resources and matches |
content_security_policy as a string | { "extension_pages": … }, unsafe sources removed |
_execute_browser_action shortcut | _execute_action |
webRequestBlocking | Removed; use declarativeNetRequest |
When your background page ran several scripts, the converter writes a service-worker.js that loads them in order with importScripts(). Paste the result into the Manifest V3 validator, or compare versions in the JSON diff.
What code changes does Manifest V3 need?
The manifest is the easy part. A service worker isn't a background page: it has no DOM, starts when an event arrives and stops when idle. The checklist covers each change, with links to Chrome's guide:
- Move DOM and
windowwork to an offscreen document. - Replace
localStoragewithchrome.storage, and global variables with stored state. - Register every listener at the top level, not inside callbacks.
- Replace
setTimeoutandsetIntervalwithchrome.alarms, andXMLHttpRequestwithfetch(). - Rename APIs:
chrome.extension.getURLbecomeschrome.runtime.getURL, andtabs.executeScriptbecomesscripting.executeScript.
// Manifest V2
chrome.tabs.executeScript(tabId, { file: "content.js" });
// Manifest V3: add the "scripting" permission
chrome.scripting.executeScript({ target: { tabId }, files: ["content.js"] });What replaces webRequestBlocking in Manifest V3?
The declarativeNetRequest API. Instead of a listener that decides about each request, you describe rules and Chrome applies them, without your code seeing the traffic. Blocking needs only the declarativeNetRequest permission, which shows "Block content on any page".
[
{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": { "urlFilter": "||example.com", "resourceTypes": ["main_frame"] }
}
]Only extensions installed by enterprise policy can still use webRequestBlocking in Manifest V3. See replacing blocking web requests.
Can Manifest V3 extensions load remote code?
No. All logic must ship in the package: no scripts from your server or a CDN, no eval() or new Function() on fetched strings. The extension_pages policy may only allow 'self', 'none', 'wasm-unsafe-eval' and, while unpacked, localhost. The converter removes everything else and lists what it took out.
You can still fetch data and configuration, and sandboxed pages may evaluate code. The Chrome Web Store allows remote logic only through the Debugger and User Scripts APIs. Bundle libraries you used to load from a CDN. Once your extension is ready, it needs a privacy policy if it handles user data: the privacy policy generator for Chrome extensions covers the Chrome Web Store's requirements.
Frequently asked questions
Last updated by the Playxoft engineering team.