How to Load an Unpacked Chrome Extension
The 60-second path from a folder on your desktop to a working extension in the Chrome toolbar.

You do not need the Chrome Web Store to run an extension. Loading unpacked installs a local folder directly, which is how every extension is tested during development.
Steps
- Unzip your extension so manifest.json sits at the top level of the folder (not inside a nested folder).
- Open chrome://extensions in the address bar.
- Turn on Developer mode with the toggle in the top-right corner.
- Click 'Load unpacked' and select the folder — not the .zip file.
- Pin the extension from the puzzle-piece toolbar menu so the icon is always visible.
Fixing load errors
- 'Manifest file is missing or unreadable' — you selected the wrong folder level, or manifest.json has a trailing comma, a comment, or a BOM. Chrome parses strict JSON only.
- 'Manifest version 2 is deprecated' — set "manifest_version": 3; MV2 unpacked loads are blocked in current Chrome.
- 'Could not load icon 'icons/icon16.png' specified in 'icons'' — the path is relative to the folder root and is case-sensitive; icon48.png and Icon48.png are different files.
- 'Service worker registration failed. Status code: 15' — a syntax error or a top-level throw in background.js. Click the Errors button on the extension card for the file and line.
- 'Service worker registration failed. Status code: 3' — the file named in background.service_worker does not exist at that path.
- 'Cannot load extension with file or directory name _metadata' — remove folders starting with an underscore, usually left over from an unzipped Web Store download.
- 'Permission 'x' is unknown or URL pattern is malformed' — MV3 splits host access into host_permissions; site patterns no longer belong in permissions.
- 'Refused to execute inline script' after loading — MV3's content security policy blocks inline handlers; move the code into an external .js file.
Debugging in order
- Read the red Errors button on chrome://extensions — it names the file and line before you start guessing.
- Validate manifest.json in any JSON linter to rule out a parse error.
- Open the 'service worker' link on the extension card to see background logs live.
- Reload the extension, then refresh the target page so content scripts re-inject.
Reloading after edits
Click the circular reload arrow on the extension card after changing background or manifest files. Content-script edits also need a page refresh; popup edits apply the next time you open the popup.
Where the developer mode toggle actually lives
On chrome://extensions the Developer mode switch sits in the top-right corner of the page, not inside any menu. Turning it on reveals three new buttons — Load unpacked, Pack extension, and Update — and also enables the red Errors button on every extension card.
Folder structure requirements
- manifest.json must be directly inside the folder you select — a common mistake is selecting the parent folder after unzipping, leaving manifest.json one level too deep.
- All paths referenced in the manifest (icons, scripts, html) are resolved relative to that same top-level folder.
- Hidden files like .DS_Store don't break loading, but a nested .git folder can slow Chrome's file watching during development.
Using the Pack extension button
Pack extension turns an unpacked folder into a .crx file plus a .pem private key, which is the format used for enterprise-policy or sideloaded distribution outside the Web Store. Keep the .pem file — you need the same key to push updates to the same .crx identity later.
Testing across multiple Chrome profiles
Load the same unpacked folder into more than one Chrome profile (or a fresh profile with --user-data-dir) to test how your extension behaves for a brand-new user versus one who has existing chrome.storage.sync data carried over from a signed-in account.
From unpacked folder to a Web Store upload
- Zip the folder's contents directly — not the folder itself — so manifest.json again sits at the zip's root.
- Upload the .zip on the Chrome Web Store Developer Dashboard under a new or existing item.
- Fill in the store listing fields (description, screenshots, privacy practices) which are separate from anything in manifest.json.
- ManifestGo outputs a ready-to-upload .zip directly, skipping the manual folder/zip step entirely.
Next step
Now that loading works, the quickest way to get a folder worth loading is to generate one. Pick a starting point and get complete Manifest V3 code with working icons.
Browse extension generatorsFrequently asked questions
Do unpacked extensions survive a browser restart?
Yes, as long as the folder stays in the same location. Deleting or moving the folder disables the extension.
Can I share an unpacked extension?
You can share the folder or .zip and the recipient repeats these steps, but for wider distribution publish to the Chrome Web Store.
Why does my extension say 'Service worker (inactive)'?
That is normal. MV3 service workers idle after about 30 seconds and wake on the next event. It only signals a problem when the card also shows a red Errors button.
Does loading unpacked count against the Chrome Web Store's item limits?
No. Unpacked loading is entirely local and never touches the Web Store, so it does not use any developer account quota or require a listing.
Why does Chrome show 'This extension may have been corrupted' after loading unpacked?
This warning typically appears for .crx installs outside the Web Store, not for Load unpacked folders used during development — if you see it, you likely packed and sideloaded a .crx instead.
Can I load an unpacked extension in Chrome for Android?
No, Developer mode's Load unpacked option is only available on desktop Chrome; Chrome for Android does not support loading local unpacked extension folders.

