To build a Chrome extension, create a project with a root-level manifest.json, add the interface and browser behavior your feature needs, and load the package unpacked in Chrome to test it. In Manifest V3, use a service worker for background events—not as an always-running process—and request only the permissions and site access the extension actually needs.
Plan one clear purpose before you write code
Start with one sentence: what does the extension do, and who benefits? Chrome’s getting-started guidance recommends a single purpose that is narrowly defined and easy to understand. A focused purpose also helps determine whether you need a popup, a content script, a background service worker, or some combination.
Choose the smallest set of browser capabilities that can deliver that purpose. A toolbar popup is useful for extension-owned controls; a content script is for interacting with matching web pages; a service worker handles background events. These are different execution contexts, not interchangeable places to put the same code.
Create the project and its manifest
Every extension needs a file named manifest.json at the root of its package. It describes the extension’s metadata, resources, permissions, and execution configuration. The exact fields depend on the chosen interface and APIs.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
A minimal starting point for an extension with a toolbar popup could look like this:
{
"manifest_version": 3,
"name": "Focused Example",
"version": "1.0.0",
"description": "A concise description of the extension's purpose.",
"action": {
"default_popup": "popup.html"
}
}
Save this as manifest.json in the project’s top directory and create the referenced popup.html. This example establishes a popup only; it does not add page access, background event handling, or other API capabilities. Add those only when the feature requires them, and ensure every referenced file is included in the package.
Put each part of the extension in the right place
Popup or extension page: extension-owned interface
Use a popup or another extension page for controls and information that belong to the extension itself. The toolbar Action API provides icon-click behavior; a side panel is another possible interface. Select a surface based on how the feature should be used instead of adding every available interface.
Content script: interaction with matching web pages
Use a content script when the extension needs to interact with a web page. Declare its URL match patterns in content_scripts.matches and keep those patterns as narrow as the feature permits. A content script’s page context is distinct from the background service worker.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Service worker: background events
Add a service worker only when background event handling is needed. Register its JavaScript file with background.service_worker in the manifest. Chrome’s tutorial also demonstrates type: "module" when using static imports.
A Manifest V3 service worker is event-driven and may stop when idle, then start again for a later event. It is not a persistent server process. Register event listeners at the top level so Chrome can find them when the worker starts, and design handlers so they can run after a restart.
Rank #3
Design around the Manifest V3 service-worker lifecycle
- Persist state deliberately. Do not depend on global variables to retain data between events. Store durable extension state with an extension storage API; the worker may be stopped between tasks.
- Keep DOM work out of the worker. A service worker cannot use the DOM or
windowdirectly. Put that work in an extension page or, where suitable, an offscreen document. Do not usewindow.localStorageas worker storage. - Use supported request and scheduling patterns. Replace
XMLHttpRequestwithfetchfor network requests made by worker code. Do not assume ordinary timers will complete after the worker becomes idle; Chrome’s migration guidance points to alarms for scheduled work. - Choose the supported module-loading method. In the documented worker model, use static
importwithtype: "module", or useimportScripts(). Dynamicimport()is not supported there.
When changing service-worker behavior, update and package the extension version you distribute. Manifest V3 does not permit remotely hosted executable code: extension logic must be included in the package.
Request only the permissions the feature needs
Manifest permissions describe different kinds of access. API permission names go in permissions; website access goes in host_permissions; content script URL patterns go in content_scripts.matches. Chrome also supports optional permissions and optional host permissions that an extension can request at runtime.
Recommended Free Tools
Some permission and host-pattern changes can prompt users. Where a feature can work with optional access, request it when needed and explain why. Avoid broad site patterns unless the feature genuinely needs broad access. A permission prompt is both a technical consequence and a trust decision.
Check API support for the Chrome versions you target
Manifest V3 is generally supported in Chrome 88 or later, according to Chrome’s migration guidance, but that is not a guarantee that every API or API feature works in Chrome 88. Check the Chrome API reference for the particular API’s permission requirements, behavior, and minimum supported Chrome version; set a higher minimum where a feature requires it.
The API reference reports that APIs are available under the browser namespace beginning in Chrome 148 as a cross-browser alternative. Treat that as a version-specific compatibility detail, not a reason to assume that every extension can switch namespaces without checking the relevant API guidance.
Compatibility is therefore an API-by-API decision: identify the oldest Chrome version your audience uses, then verify each capability against that version. Recheck the current API entry and Chrome Web Store guidance before release, since support and publishing rules can change.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Best Value
Choose request handling based on the feature
For many request-blocking or request-modification use cases, Chrome presents Declarative Net Request (DNR) as a safer alternative and a way to reduce permissions compared with some approaches. Whether it fits depends on the exact behavior you need, so check its API limits and requirements rather than assuming it can replace every network-related API.
More broadly, compare implementation choices by where code runs, how access is granted, how network behavior is handled, and which Chrome versions support the required APIs. The best design is the one that meets the feature requirement with the narrowest access and a support range your users can actually run.
Load and test the extension locally
- Prepare the package. Put
manifest.jsonat the project root and confirm that its referenced files exist in the package. - Load it unpacked. In Chrome, enable developer mode on the extensions page and use the option to load the unpacked project directory.
- Exercise the main user flow. Test the popup, page interaction, or other interface your extension actually provides, along with any permission request it makes.
- Inspect background behavior. Use the extension service worker’s logs to check event handling and errors. Test behavior after the worker has stopped and is started again; do not rely on a single uninterrupted session.
- Check access and compatibility. Confirm that the extension asks only for needed permissions and that every required API works in the Chrome versions you intend to support.
Chrome’s service-worker tutorial covers debugging and state handling. A successful local load is not a substitute for checking API compatibility or reviewing the policies and live publishing guidance before distributing through the Chrome Web Store.
Prepare the packaged extension for distribution
Include the extension’s executable logic in its package; Manifest V3 disallows runtime-downloaded JavaScript and other remotely hosted executable code. Keep the extension’s stated purpose clear and review Chrome Web Store developer policies before submitting. Submission requirements and review details can change, so consult the current store guidance rather than relying on a remembered fee, review estimate, or account rule.
For each release, verify the manifest, packaged resources, permissions, and API version requirements together. A feature that works in your development browser may still fail for users on an older supported version if it relies on a later API capability.
Quick Recap
Common implementation mistakes
- Assuming the worker stays alive: it can terminate when idle, so register listeners predictably and persist state outside globals.
- Using page-only APIs in the worker: DOM,
window, andwindow.localStoragedo not belong there. - Loading executable code remotely: package extension logic and distribute changes in an updated extension version.
- Requesting broad access by default: narrow API permissions and host access to the feature; use optional access where it makes sense.
- Treating Chrome 88 as universal API support: confirm minimum versions for each API and feature.
- Putting every feature in one context: use extension pages for extension-owned UI, content scripts for matching page interaction, and a worker for background events.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

