Chrome Extension Development
Build modern Chrome extensions using Manifest V3, the current 2025 standard for secure, performant browser extensions.
Quick Start
Create a minimal extension:
- Create
manifest.jsonwith MV3 format - Add service worker for background logic
- Create UI (popup, side panel, or content script)
- Load unpacked in
chrome://extensions
See asset templates for complete project structure.
Core Concepts
Manifest V3 Architecture
Service Workers replace background pages:
- Event-driven, terminate when idle
- No DOM access
- Use chrome.storage and chrome.runtime for data
Content Scripts:
- Run in web page context
- Can read/modify DOM
- Communicate via messaging API
Action API:
- Toolbar icon interactions
- Popup windows
- Badge text/icons
Development Workflow
- Initialize project structure
- Configure manifest.json (see MANIFEST.md)
- Implement components (service worker, content scripts, popups)
- Load and test locally in developer mode
- Debug using Chrome DevTools
- Package for Chrome Web Store
Common Extension Patterns
Popup Extension
Structure:
extension/
├── manifest.json
├── popup.html
├── popup.js
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
manifest.json:
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0",
"action": {
"default_popup": "popup.html"
}
}
Content Script Extension
manifest.json:
{
"manifest_version": 3,
"name": "Page Modifier",
"version": "1.0",
"content_scripts": [{
"matches": ["https://example.com/*"],
"js": ["content.js"],
"run_at": "document_idle"
}]
}
Message passing to service worker:
// content.js
chrome.runtime.sendMessage({action: "getData"}, (response) => {
console.log(response.data);
});
// background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "getData") {
sendResponse({data: "example"});
}
});
Background Service Worker
manifest.json:
{
"manifest_version": 3,
"name": "Background Task",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"permissions": ["storage", "alarms"]
}
background.js:
chrome.alarms.create("refresh", {periodInMinutes: 60});
chrome.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === "refresh") {
// Perform periodic task
}
});
Declarative Net Request
manifest.json:
{
"manifest_version": 3,
"name": "Request Blocker",
"version": "1.0",
"permissions": ["declarativeNetRequest"],
"declarative_net_request": {
"rule_resources": [{
"id": "ruleset",
"enabled": true,
"path": "rules.json"
}]
}
}
rules.json:
[{
"id": 1,
"priority": 1,
"action": {"type": "block"},
"condition": {
"domains": ["example.com"],
"urlFilter": "||tracker.com/*"
}
}]
Permissions Best Practices
Use minimum required permissions:
- Active permissions: Declare in manifest.json
- Optional permissions: Request at runtime with
chrome.permissions.request()
Common permissions:
storage- chrome.storage APIactiveTab- current tab access (user gesture required)scripting- dynamic script injectionalarms- scheduled taskstabs- tab management
Key APIs
Storage API
// Save data
chrome.storage.local.set({key: "value"});
// Retrieve data
chrome.storage.local.get(["key"], (result) => {
console.log(result.key);
});
Tabs API
// Query tabs
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
const currentTab = tabs[0];
});
// Send message to content script
chrome.tabs.sendMessage(tabId, {action: "execute"});
Scripting API
// Inject content script dynamically
chrome.scripting.executeScript({
target: {tabId: tabId},
files: ["content.js"]
});
Security Guidelines
Critical MV3 requirements:
- ✅ All code bundled with extension
- ❌ No remotely hosted JavaScript
- ❌ No eval() or inline scripts
- ✅ Content Security Policy required
CSP example:
{
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
}
Testing & Debugging
Load unpacked extension:
- Navigate to
chrome://extensions - Enable "Developer mode"
- Click "Load unpacked"
- Select extension directory
Debug service worker:
- Go to
chrome://extensions - Find extension, click "service worker" link
- Opens DevTools for background script
Debug content script:
- Open web page where script runs
- Open DevTools (F12)
- Content script appears in Sources panel
Debug popup:
- Right-click extension icon
- Select "Inspect popup"
Migration from V2 to V3
Key changes:
- Background pages → Service workers
chrome.webRequest→declarativeNetRequestchrome.extension.getBackgroundPage()→ Use messaging- Persistent state → chrome.storage
See MV3 Migration Guide for detailed steps.
Chrome Web Store Publication
Requirements:
- Single, clearly defined purpose
- Detailed store listing (screenshots, description)
- Privacy policy if collecting data
- Comply with Developer Program Policies
Package extension:
- Zip all extension files (not the folder itself)
- Upload to Chrome Web Store Developer Dashboard
- Complete store listing
- Submit for review
Resources
Detailed Documentation
- Manifest Configuration - Complete manifest.json reference
- MV3 Migration Guide - V2 to V3 migration patterns
- API Reference - All Chrome extension APIs
Asset Templates
- Basic extension - Minimal popup extension
- Content script - Page modification example
- Service worker - Background processing example
- Declarative rules - Network filtering example
Tools
- Chrome Extensions Developer Hub - Official documentation
- Extension Playground - Tutorials and examples
