How to Build a Chrome Extension and Publish It to the Chrome Web Store (2026 Guide)
Why Build a Chrome Extension?
With over 3.8 billion Chrome users worldwide, Chrome extensions offer developers direct access to a massive audience. Whether you want to build a productivity tool, automate workflows, or create a SaaS product — extensions are one of the fastest ways to ship software that people use daily.
The barrier to entry is low: if you know HTML, CSS, and JavaScript, you already have everything you need.
Part 1: Setting Up Your Development Environment
Prerequisites
- Google Chrome (latest stable version)
- Code editor (VS Code recommended)
- Basic knowledge of HTML, CSS, and JavaScript
No special SDKs, compilers, or build tools required for simple extensions.
Project Structure
Create a new folder for your extension. A minimal Chrome extension needs just one file — manifest.json — but most real extensions follow this structure:
my-extension/
├── manifest.json # Required: extension configuration
├── service-worker.js # Background logic (event-driven)
├── content.js # Injected into web pages
├── popup.html # Toolbar popup UI
├── popup.js # Popup logic
├── popup.css # Popup styles
├── options.html # Settings page (optional)
└── icons/
├── icon-16.png
├── icon-48.png
└── icon-128.pngPart 2: Writing Your First Extension
Step 1: Create the Manifest
The manifest.json file is your extension’s blueprint. Every extension must use Manifest V3 (V2 is fully deprecated as of 2024).
{
"manifest_version": 3,
"name": "My First Extension",
"version": "1.0.0",
"description": "A simple extension that greets users",
"permissions": ["activeTab", "storage"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon-16.png",
"48": "icons/icon-48.png",
"128": "icons/icon-128.png"
}
},
"background": {
"service_worker": "service-worker.js"
},
"content_scripts": [
{
"matches": ["https://*/*"],
"js": ["content.js"]
}
]
}Key fields explained:
manifest_version: Must be3— non-negotiablepermissions: Declare only what you need (reviewed by Google)host_permissions: Separate field for website access patternsaction: Controls the toolbar icon and popupbackground.service_worker: Replaces the old background page model
Step 2: Build the Popup UI
Create popup.html — the interface users see when clicking your extension icon:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<div class="container">
<h1>Hello, Extension!</h1>
<p id="status">Click the button to get started.</p>
<button id="action-btn">Do Something</button>
</div>
<script src="popup.js"></script>
</body>
</html>/* popup.css */
body {
width: 320px;
padding: 16px;
font-family: system-ui, sans-serif;
}
.container { text-align: center; }
button {
background: #4285f4;
color: white;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
}
button:hover { background: #3367d6; }// popup.js
document.getElementById('action-btn').addEventListener('click', async () => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
chrome.tabs.sendMessage(tab.id, { action: 'greet' });
document.getElementById('status').textContent = 'Message sent!';
});Step 3: Add a Service Worker
The service worker handles background events. Unlike MV2 background pages, service workers are event-driven and terminate when idle:
// service-worker.js
chrome.runtime.onInstalled.addListener(() => {
console.log('Extension installed successfully');
});
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'getData') {
// Handle background tasks
sendResponse({ data: 'Hello from service worker' });
}
});Important: Register all event listeners at the top level — not inside callbacks or promises.
Step 4: Create a Content Script
Content scripts run in the context of web pages and can manipulate the DOM:
// content.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'greet') {
const banner = document.createElement('div');
banner.textContent = '👋 Hello from My Extension!';
banner.style.cssText = `
position: fixed; top: 0; left: 0; right: 0;
background: #4285f4; color: white;
padding: 12px; text-align: center;
z-index: 99999; font-family: system-ui;
`;
document.body.prepend(banner);
setTimeout(() => banner.remove(), 3000);
}
});Part 3: Loading and Debugging Your Extension
Load Your Extension in Chrome
- Open
chrome://extensions/in your browser - Enable Developer mode (toggle in top-right corner)
- Click “Load unpacked”
- Select your extension folder
- Your extension appears in the toolbar immediately
Debugging Techniques
| Component | How to Debug |
|---|---|
| Service Worker | Click “service worker” link on the extension card |
| Popup | Right-click extension icon → “Inspect popup” |
| Content Script | Open page DevTools → Console tab (select extension context) |
Pro tips:
- Changes to code require clicking the refresh icon on
chrome://extensions/ - Changes to
manifest.jsonrequire removing and re-loading the extension - Use
chrome.storagefor persistent data — service worker variables are lost on termination - Check the Errors button on your extension card for crash reports
Part 4: Key APIs You Should Know
| API | Purpose | Permission |
|---|---|---|
chrome.storage | Persist data locally or sync across devices | storage |
chrome.tabs | Query and manipulate browser tabs | tabs |
chrome.alarms | Schedule recurring background tasks | alarms |
chrome.contextMenus | Add right-click menu items | contextMenus |
chrome.notifications | Show desktop notifications | notifications |
chrome.declarativeNetRequest | Block/modify network requests | declarativeNetRequest |
Communication Between Components
Extensions use message passing to communicate between popup, service worker, and content scripts:
// Send message from popup to service worker
chrome.runtime.sendMessage({ action: 'fetchData' }, (response) => {
console.log(response);
});
// Send message from service worker to content script
chrome.tabs.sendMessage(tabId, { action: 'updateUI' });Part 5: Publishing to the Chrome Web Store
Once your extension is tested and ready, here’s how to get it in front of users.
Step 1: Register as a Developer
- Go to the Chrome Web Store Developer Dashboard
- Sign in with your Google account
- Pay the one-time $5 registration fee
- Enable 2-Step Verification on your Google account (mandatory)
Step 2: Prepare Your Assets
You’ll need these before submitting:
| Asset | Requirements |
|---|---|
| Extension icon | 128×128 PNG (96×96 visible area + 16px padding) |
| Screenshots | 1-5 images, 1280×800 pixels recommended |
| Short description | Up to 132 characters |
| Full description | Up to 16,000 characters — explain features and benefits |
| Privacy policy URL | Required if you handle any user data |
Screenshot tips: Show your extension in real use. Highlight key features. Avoid generic mockups — reviewers want to see actual functionality.
Step 3: Package Your Extension
Create a .zip file of your extension folder (the folder containing manifest.json at the root):
cd my-extension
zip -r ../my-extension.zip . -x ".*" -x "__MACOSX"Step 4: Submit for Review
- In the Developer Dashboard, click “New Item”
- Upload your
.zipfile - Fill in the Store Listing tab:
- Name, description, category, language
- Upload icon and screenshots
- Complete the Privacy tab:
- Declare data usage practices
- Provide privacy policy URL if applicable
- Justify every permission you declared
- Set Distribution options:
- Public (visible to all) or Unlisted (accessible via direct link)
- Geographic targeting (optional)
- Click “Submit for Review”
Step 5: Wait for Review
- Typical timeline: 1-3 days for simple extensions, up to 7 days for complex ones
- Manual review triggered by: Sensitive permissions, network request APIs, or policy flags
- After approval: Your extension goes live immediately
Speed up approval:
- Declare minimal permissions
- Write clear permission justifications
- Ensure your privacy policy matches actual behavior
- Test thoroughly — crashes trigger rejection
- Follow all Chrome Web Store policies
Part 6: After Publishing — What’s Next?
Monitor Performance
- Track installs, uninstalls, and active users in the Developer Dashboard
- Respond to user reviews promptly
- Monitor crash reports and fix issues quickly
Update Your Extension
- Increment the
versioninmanifest.json - Upload a new
.zipto the Developer Dashboard - Updates go through review again (usually faster than initial submission)
- Chrome auto-updates extensions for users within a few hours of approval
Grow Your User Base
- Optimize your store listing with relevant keywords
- Encourage satisfied users to leave reviews
- Create a landing page or documentation site
- Engage with your user community
- Use tools like ExtensionBooster to analyze and improve your store presence
Common Mistakes to Avoid
- Requesting excessive permissions — Only declare what you actually use. Broad permissions trigger longer reviews and scare users.
- Using remote code — Manifest V3 prohibits remotely-hosted JavaScript. All code must be bundled in your extension package.
- Ignoring service worker lifecycle — Don’t store state in variables; use
chrome.storage. Service workers terminate when idle. - Misleading store listing — Your description and screenshots must accurately represent functionality. Mismatches lead to rejection.
- Missing privacy policy — If your extension accesses any user data (even just the current tab URL), you need a privacy policy.
Helpful Resources
- Chrome Extensions Documentation — Official reference
- Chrome Extension Samples — Working code examples
- Manifest V3 Migration Guide — For MV2 developers
- Chrome Web Store Publishing Guide — Submission details
- ExtensionBooster Developer Tools — Free analysis and optimization tools
Conclusion
Building and publishing a Chrome extension is remarkably accessible. With just HTML, CSS, and JavaScript, you can create tools that reach billions of users through the Chrome Web Store. The key steps are straightforward: structure your project with Manifest V3, build your UI and logic, test locally with Developer mode, then submit through the Developer Dashboard with proper assets and documentation.
The $5 registration fee and a few days of review time are all that stand between your idea and a published extension. Start small, iterate based on user feedback, and grow from there.
Ready to build? Create your manifest.json and load it as an unpacked extension today. Your first Chrome extension is just a few files away.
Share this article
Build better extensions with free tools
Icon generator, MV3 converter, review exporter, and more — no signup needed.
Related Articles
I Built the Same Chrome Extension With 5 Different Frameworks. Here's What Actually Happened.
WXT vs Plasmo vs CRXJS vs Extension.js vs Bedframe. Real benchmarks, honest opinions, and the framework with 12K stars that's quietly dying.
5 Best Email Marketing Services to Grow Your Chrome Extension (2026)
Compare the top email marketing platforms for SaaS and Chrome extension developers. MailerLite, Mailchimp, Brevo, ActiveCampaign, and Drip reviewed.
15 Best Practices to Build a Browser Extension That Users Love (2026 Guide)
Master browser extension development in 2026. Manifest V3, security, performance, and UX best practices to build extensions users love.