What you're actually building when you create a Chrome extension

A Chrome extension is a small program that adds a feature to your browser — it lives in your toolbar, runs on web pages you visit, or both. You write it using the same languages you'd use for a website: HTML for structure, CSS for appearance, and JavaScript for behavior. Chrome reads these files, packages them together, and lets you install them like you would any other extension.

The simplest extensions are just a few files in a folder. You don't need a server, you don't need to publish to the Chrome Web Store to test it, and you don't need special tools beyond a text editor. This guide walks you through building a working extension that does something visible — a button in your toolbar that changes the background color of any web page you're on.

Key Takeaways

  • A Chrome extension requires at least three files: a manifest file that tells Chrome what the extension does, an HTML file for the popup window, and a JavaScript file for the behavior.
  • You write these files in a text editor, save them in a folder, and load that folder into Chrome using Developer Mode — no publishing required to test.
  • The manifest file is the contract between you and Chrome; it declares what permissions the extension needs and what it will do.
  • JavaScript in an extension runs in separate contexts depending on where it executes: in the popup, in the background, or on the page itself.
  • Testing happens in Chrome's extension management page, where you can reload, enable, disable, and inspect errors without leaving the browser.

Set up your folder and create the manifest file

Create a new folder on your computer called my-first-extension (or any name without spaces). This folder will hold all your extension files. Inside it, create a new file called manifest.json and open it in a text editor like Notepad, VS Code, or any plain-text editor.

Paste this into manifest.json:

{ "manifest_version": 3, "name": "My Color Changer", "version": "1.0", "description": "Changes the background color of web pages", "permissions": ["scripting", "activeTab"], "action": { "default_popup": "popup.html", "default_title": "Click to change colors" } }

Save the file. This manifest tells Chrome the extension's name, what it does, what permissions it needs, and which file to show when someone clicks the toolbar button. The permissions field is important: "scripting" means the extension can run JavaScript on pages, and "activeTab" means it only runs on the page you're currently viewing.

Create the popup window that appears when you click the button

In the same folder, create a file called popup.html. This is the window that appears when someone clicks your extension's button in the toolbar. Paste this into it:

<!DOCTYPE html> <html> <head> <style> body { width: 200px; padding: 10px; font-family: Arial, sans-serif; } button { width: 100%; padding: 8px; margin: 5px 0; cursor: pointer; } </style> </head> <body> <h2>Pick a color</h2> <button id="redBtn">Red</button> <button id="blueBtn">Blue</button> <button id="greenBtn">Green</button> <script src="popup.js"></script> </body> </html>

Save this file. It's a normal HTML page with three buttons. When you click the extension button, this popup appears. The last line loads a JavaScript file called popup.js, which you'll create next.

Write the JavaScript that makes the buttons work

Create a file called popup.js in the same folder. This file runs when the popup opens and listens for button clicks. Paste this into it:

document.getElementById("redBtn").addEventListener("click", () => { chrome.tabs.query({active: true, currentWindow: true}, (tabs) => { chrome.tabs.executeScript(tabs[0].id, { code: "document.body.style.backgroundColor = 'red';" }); }); }); document.getElementById("blueBtn").addEventListener("click", () => { chrome.tabs.query({active: true, currentWindow: true}, (tabs) => { chrome.tabs.executeScript(tabs[0].id, { code: "document.body.style.backgroundColor = 'blue';" }); }); }); document.getElementById("greenBtn").addEventListener("click", () => { chrome.tabs.query({active: true, currentWindow: true}, (tabs) => { chrome.tabs.executeScript(tabs[0].id, { code: "document.body.style.backgroundColor = 'green';" }); }); });

Save this file. Each block does the same thing: when a button is clicked, it finds the active tab you're on and runs JavaScript code that changes the background color. The chrome.tabs.query function finds the current tab, and chrome.tabs.executeScript runs code on that page.

Load your extension into Chrome and test it

Open Chrome and go to chrome://extensions in the address bar. In the top right corner, turn on Developer mode — you'll see a toggle switch. Once it's on, three buttons appear: "Load unpacked", "Pack extension", and "Update". Click Load unpacked.

A file browser opens. Navigate to the folder you created (my-first-extension) and select it. Chrome reads your manifest.json, loads all the files, and adds your extension to the toolbar. You should see a small icon in the top right of Chrome.

Click the icon. The popup appears with your three buttons. Click any button and the background of the current web page changes color. If nothing happens, check the Chrome extensions page — there may be an error message in red text below your extension's name. Click "Errors" to see what went wrong.

Common problems and how to fix them

If the popup doesn't appear, check that popup.html is spelled correctly in manifest.json and that the file actually exists in your folder. If the buttons don't work, open the Chrome extensions page, find your extension, and click "Errors" — JavaScript mistakes show up there with line numbers.

If you change any of your files, go back to the extensions page and click the reload icon (circular arrow) under your extension's name. Chrome will read the new files. You don't need to unload and reload the extension every time — just reload.

If the extension works on some pages but not others, the page may have security restrictions that prevent scripts from running. This is normal — extensions can't run on pages like chrome://extensions itself or on the Chrome Web Store.

What to learn next

This extension changes the page for as long as you're on it, then reverts when you reload. To make changes permanent during a session, you'd store the color choice and reapply it when the page loads. To do that, you'd use chrome.storage to save the user's choice and a content script to run code automatically on every page.

You can also add a settings page, change the icon, run code in the background without a popup, or interact with other websites' data. The Chrome extension documentation has examples for all of these. For now, you have a working extension that demonstrates the core pattern: manifest declares what you need, HTML builds the interface, and JavaScript makes it work.

Frequently Asked Questions

Do I have to publish my extension to the Chrome Web Store to use it?

No. You can load it unpacked and use it privately forever. Publishing is only necessary if you want other people to install it from the Web Store. Unpacked extensions work the same way — they just show a warning that they're not from the store.

What's the difference between manifest version 2 and 3?

Chrome stopped supporting manifest version 2 in 2023. Version 3 is required for all new extensions. If you find old tutorials using version 2, the syntax is different and won't work in modern Chrome.

Can my extension run on all websites?

By default, no — you need to declare which sites it runs on in the manifest using the "host_permissions" field. You can use wildcards like "https://*/*" to run on all HTTPS sites, but users will see a warning that the extension can read and change data on those sites.

What happens if I close the popup?

The popup closes, but the code you ran on the page stays active. If you changed the background color, it stays changed until you reload the page or run different code. The popup is just the interface — the real work happens on the page itself.

Can I add an icon to my extension button?

Yes. Create a small image file (128x128 pixels works well), save it in your extension folder, and add this to the manifest under "action": "default_icon": "icon.png". Replace icon.png with your actual filename.