Everything you need to build, publish, and manage powerful browser extensions
Build your first browser extension in minutes
Create a new directory for your extension with the following structure:
my-extension/
├── manifest.json
├── popup.html
├── popup.js
├── popup.css
├── background.js
├── content.js
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
The manifest.json file is the blueprint of your extension. Here's a basic example:
{
"manifest_version": 3,
"name": "My First Extension",
"version": "1.0.0",
"description": "A simple browser extension",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"action": {
"default_popup": "popup.html",
"default_icon": "icons/icon48.png"
},
"permissions": ["storage", "activeTab"],
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": [""],
"js": ["content.js"]
}]
}
Create popup.html for the extension's user interface:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<div class="container">
<h1>My Extension</h1>
<button id="actionBtn">Click Me</button>
<p id="result"></p>
</div>
<script src="popup.js"></script>
</body>
</html>
Chrome/Edge:
Firefox:
Understanding the extension configuration
Specifies the manifest file format. Use version 3 for modern extensions.
"manifest_version": 3
The name of your extension (maximum 45 characters).
"name": "My Awesome Extension"
Version string with up to four numbers separated by dots.
"version": "1.0.0"
A short description (maximum 132 characters).
"description": "Boost productivity with this tool"
Request permissions your extension needs:
| Permission | Description |
|---|---|
| activeTab | Access the current active tab |
| storage | Use chrome.storage API |
| tabs | Access tabs API for tab management |
| notifications | Display notifications to users |
| webRequest | Intercept and modify web requests |
| cookies | Access and modify cookies |
Important
Only request permissions your extension actually needs. Excessive permissions may deter users from installing.
Common APIs and their usage
Store and retrieve data across browser sessions with Free Chrome Extension API:
// Save data
chrome.storage.sync.set({ key: 'value' }, function() {
console.log('Data saved');
});
// Retrieve data
chrome.storage.sync.get(['key'], function(result) {
console.log('Value is: ' + result.key);
});
// Remove data
chrome.storage.sync.remove('key', function() {
console.log('Data removed');
});
Interact with browser tabs:
// Get current tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
let currentTab = tabs[0];
console.log(currentTab.url);
});
// Create new tab
chrome.tabs.create({ url: 'https://example.com' });
// Update tab
chrome.tabs.update(tabId, { url: 'https://newurl.com' });
// Close tab
chrome.tabs.remove(tabId);
Handle extension lifecycle events:
// Listen for installation
chrome.runtime.onInstalled.addListener(function(details) {
if(details.reason == "install"){
console.log("Extension installed!");
}
});
// Send message between scripts
chrome.runtime.sendMessage({type: "getData"}, function(response) {
console.log(response);
});
// Listen for messages
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.type === "getData") {
sendResponse({data: "Hello from background"});
}
});
Display desktop notifications:
chrome.notifications.create({
type: 'basic',
iconUrl: 'icon48.png',
title: 'Notification Title',
message: 'This is the notification message',
priority: 2
});
Create beautiful and intuitive interfaces
| Size | Purpose | Format |
|---|---|---|
| 16x16 | Favicon and extension menu | PNG |
| 48x48 | Extension management page | PNG |
| 128x128 | Chrome Web Store listing | PNG |
#3B82F6
Primary Blue
#8B5CF6
Primary Purple
#10B981
Success Green
#EF4444
Error Red
Ensure quality before publishing
// Add console logs for debugging
console.log('Extension loaded');
// Use debugger statement
debugger;
// Check background script errors
chrome://extensions/ > Details > Inspect views: background page
// Debug content scripts
Right-click page > Inspect > Console tab
// View storage data
chrome://extensions/ > Details > Storage
Submit to extension stores
Register on Chrome Web Store, Firefox Add-ons, or Edge Add-ons. One-time fee may apply.
Zip your extension directory (excluding hidden files and development files).
Upload your zip file and fill in store listing details, screenshots, and metadata.
Wait for store review (typically 1-3 days). Address any feedback if rejected.
Once approved, your extension goes live. Promote it to reach your target audience.
Pro Tip
Submit to multiple stores simultaneously to maximize reach. Each store has different audiences and requirements.
Build better, more secure extensions
Ready-to-use snippets and templates
popup.html
<!DOCTYPE html>
<html>
<head>
<style>
body { width: 300px; padding: 20px; font-family: Arial; }
button { width: 100%; padding: 10px; background: #8B5CF6;
color: white; border: none; border-radius: 5px;
cursor: pointer; font-size: 16px; }
button:hover { background: #7C3AED; }
</style>
</head>
<body>
<h2>My Extension</h2>
<button id="clickBtn">Click Me</button>
<p id="output"></p>
<script src="popup.js"></script>
</body>
</html>
popup.js
document.getElementById('clickBtn').addEventListener('click', function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
let currentTab = tabs[0];
document.getElementById('output').textContent =
'Current URL: ' + currentTab.url;
});
});
// content.js - Runs on web pages
console.log('Content script loaded');
// Modify page content
document.body.style.backgroundColor = '#f0f0f0';
// Listen for messages from background/popup
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.action === 'changeColor') {
document.body.style.backgroundColor = request.color;
sendResponse({status: 'Color changed'});
}
});
// background.js - Runs in the background
chrome.runtime.onInstalled.addListener(() => {
console.log('Extension installed');
// Create context menu
chrome.contextMenus.create({
id: 'myContextMenu',
title: 'My Extension Action',
contexts: ['selection']
});
});
// Handle context menu clicks
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === 'myContextMenu') {
console.log('Selected text: ' + info.selectionText);
}
});
// Listen for tab updates
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete') {
console.log('Page loaded: ' + tab.url);
}
});
options.html
<!DOCTYPE html>
<html>
<body>
<h1>Extension Options</h1>
<label>
<input type="checkbox" id="enableFeature">
Enable Feature
</label>
<button id="saveBtn">Save</button>
<script src="options.js"></script>
</body>
</html>
options.js
// Load saved settings
chrome.storage.sync.get(['enableFeature'], function(result) {
document.getElementById('enableFeature').checked = result.enableFeature || false;
});
// Save settings
document.getElementById('saveBtn').addEventListener('click', function() {
const enabled = document.getElementById('enableFeature').checked;
chrome.storage.sync.set({enableFeature: enabled}, function() {
alert('Settings saved!');
});
});
Join our developer community and access additional resources
Start buying or selling extensions today