You can build a working Chrome extension with AI in about an hour. An extension is a folder: a manifest.json file that describes it, plus a little HTML, JavaScript and a few icons. You load the folder into Chrome in Developer mode, test it, then zip it and submit it to the Chrome Web Store for review.
The AI will happily write all of it. Your two jobs are keeping it small and keeping its permissions narrow, because permissions decide both the warning people see at install and how closely Google reviews it. Below is a tested example you can copy.
- An extension is a folder with a
manifest.json, some HTML and JavaScript, and icons. Ask the AI for Manifest V3, the only version Chrome still runs. - Ask for
activeTabandscriptinginstead of access to every site. Neither shows a warning at install. - Load the folder with Developer mode and Load unpacked, then test the unhappy paths, such as
chrome://pages. - Never put an API key in an extension. Anyone who installs it can read its files.
- Publishing takes a one-time fee, 2-Step Verification, a store listing, privacy answers and a review that usually takes a few days.
What a Chrome extension is made of
Chrome turned off Manifest V2 for every user with Chrome 138, in July 2025. On August 31, 2026, the last V2 extensions were removed from the Chrome Web Store. So if an AI hands you browser_action, a background page or chrome.tabs.executeScript, it is copying old examples. Ask it to redo the work in V3.
Most small extensions use only a few parts.
| Part | What it does | In our example |
|---|---|---|
manifest.json | Names the extension and declares its files and permissions | Yes |
| Action and popup | The toolbar icon, and the small page that opens when you click it | Yes |
chrome.scripting | Runs a function inside a web page when you ask it to | Yes |
| Content script | Runs automatically on every page that matches a pattern | No |
| Service worker | Handles events in the background, such as alarms or messages | No |
Brief the AI before it writes anything
A one-paragraph brief saves most of the hour. Name the job, the files, the permissions and what must not happen. Our prompts for coding agents explain why each of those lines matters.
Build a Manifest V3 Chrome extension called Reading Time. When I click its toolbar icon, a popup shows how many words the current page has and roughly how long it takes to read at 230 words a minute. Count the text in the page's article or main element, or the whole body if there is neither. Use only the activeTab and scripting permissions. No content scripts, no background service worker, no remote code, no libraries, no inline scripts. If Chrome blocks the page, such as a chrome:// page, show a plain message instead of failing silently. Give me every file, then explain each permission in one sentence.
The example: a reading-time extension
Here is the finished extension. Save the three files in a folder called reading-time, and add an icons folder with 16, 48 and 128 pixel PNG images.
{
"manifest_version": 3,
"name": "Reading Time",
"version": "1.0.0",
"description": "Shows how long the page you are on takes to read.",
"action": {
"default_title": "Reading time",
"default_popup": "popup.html"
},
"icons": {
"16": "icons/16.png",
"48": "icons/48.png",
"128": "icons/128.png"
},
"permissions": ["activeTab", "scripting"]
}<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body { font: 14px system-ui, sans-serif; margin: 0; padding: 12px 16px; min-width: 220px; }
</style>
</head>
<body>
<p id="result">Counting words...</p>
<script src="popup.js"></script>
</body>
</html>const WORDS_PER_MINUTE = 230;
// This function runs inside the web page, not in the popup.
function countWords() {
const root = document.querySelector("article, main") || document.body;
return root.innerText.split(/\s+/).filter(Boolean).length;
}
async function showReadingTime() {
const result = document.getElementById("result");
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
try {
const [{ result: words }] = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: countWords,
});
const minutes = Math.max(1, Math.round(words / WORDS_PER_MINUTE));
result.textContent = `${words.toLocaleString()} words, about ${minutes} min to read`;
} catch (error) {
result.textContent = "Chrome does not let extensions read this page.";
}
}
showReadingTime();countWords is the clever part. Chrome copies that function into the page and runs it there, so it can read the page’s text, and the popup only receives the number. Nothing stays behind on the page after the click.
Load it and test it like a user
Open the extensions page
Go to
chrome://extensionsand switch on Developer mode.Load your folder
Click Load unpacked and choose the
reading-timefolder. If the manifest has a mistake, Chrome refuses to load it and says why. Problems at run time show up behind an Errors button on the extension’s card.Pin it and click it
Pin the extension from the puzzle-piece menu, open a long article, and click the icon. The popup should show a word count and the minutes.
Try the unhappy paths
Click it on
chrome://extensionsor any otherchrome://page. You should see the plain message, not a blank popup. Right-click the popup and choose Inspect to open its console.Reload after edits
Popup changes show up the next time you open it. After you change the manifest, click the reload icon on the extension’s card.
We loaded this exact folder into Chrome 153 and clicked its toolbar button with a script (Puppeteer’s triggerExtensionAction), first on a test article of 1,151 words, then on a chrome:// page. We also ran a copy with activeTab removed, to show what a missing permission looks like. Real output:
Chrome: Chrome/153.0.8010.53
[article page] popup says: "1,151 words, about 5 min to read" | chrome error: none
[chrome:// page] popup says: "Chrome does not let extensions read this page." | chrome error: Cannot access a chrome:// URL
[control, no activeTab] popup says: "Chrome does not let extensions read this page." | chrome error: Cannot access contents of the page. Extension manifest must request permission to access the respective host.The article’s menu and footer were left out of the count, because the function reads the article element first. The last line is the error you will meet when a permission is missing. Paste it straight back to the AI.
Ask for the fewest permissions
Permissions are what users and reviewers look at first. Chrome turns them into warnings at install, and Google’s review looks harder at broad ones.
| activeTab and scripting | Access to all sites | |
|---|---|---|
| Install warning | None | “Read and change all your data on all websites” |
| When it can read a page | Only after the user clicks, until they leave that page | Every page, all the time |
| Review | Standard | Google names broad host permissions as a cause of slower review |
| Right for | Tools the user starts with a click or a shortcut | Extensions that must change pages automatically |
Three habits keep an extension easy to trust and to approve:
Ask the AI to justify every permission. If it cannot point to the line of code that needs one, remove it.
Prefer
activeTabovertabs, which warns users that the extension can read their browsing history.Keep every script inside the package. Manifest V3 extension pages load only their own scripts, and they block inline JavaScript.
How to publish a Chrome extension
Register as a developer
Sign in to the Chrome Web Store developer dashboard, accept the developer agreement and pay the one-time registration fee. Turn on 2-Step Verification for your Google account first, because the store requires it before you publish or update anything.
Zip the folder
The manifest must sit at the top level of the ZIP, not inside another folder.
Terminal cd reading-time zip -r ../reading-time.zip . -x ".*"Upload it and write the listing
Click Add new item and upload the ZIP. Then fill in the store listing: a clear description, your 128 pixel icon and screenshots of the popup in use.
Answer the privacy questions
State your extension’s single purpose, justify each permission and declare what user data it handles. If it handles any user data, you also need a privacy policy. Reading Time sends nothing anywhere, which keeps this step short.
Choose visibility and submit
Pick public, unlisted or private, then click Submit for review. You can choose to publish by hand after approval. You then have 30 days before the submission goes back to being a draft.
Google says most reviews finish within a few days, though some take a few weeks. New developers, new extensions, sensitive permissions and large or obfuscated code all get a closer look. If yours has waited more than three weeks, contact developer support.
What AI gets wrong in extensions
Old Manifest V2 code:
browser_action, background pages andchrome.tabs.executeScript.Permission creep:
<all_urls>,tabsorstorageadded “just in case”.Inline scripts in the popup HTML. Chrome blocks them, so the popup quietly does nothing.
Libraries loaded from a CDN, which Manifest V3 does not allow. Bundle the file into the extension, or do without it.
No handling for protected pages, which leaves a blank popup on
chrome://pages.Secrets in the code, from API keys to private endpoints.
When something breaks, copy the exact message from the Errors button or the popup’s console and give it to the AI like a bug report. Before you publish, read the change the way you would review any AI-written code.
FAQ
How much does it cost to publish a Chrome extension?
One registration fee per developer account, paid once. Google’s docs call it a one-time fee without printing the amount. It was US$5 in 2020, when Google made it due at sign-up, so check the figure when you register.
How long does Chrome Web Store review take?
Most reviews finish within a few days, but some take a few weeks. Broad permissions, new accounts and large or obfuscated code take longer. Google suggests contacting support if a review passes three weeks.
Can I build a Chrome extension without knowing how to code?
Yes, for small tools like this one. You need to follow the load and test steps, read the manifest and paste errors back to the AI. Our guide to building an app without coding covers where that approach hits walls.
Can my extension use an AI model?
Yes, but call the model from your own server, never with a key inside the extension. Tell users what page text you send and why, in the store’s privacy questions and in your privacy policy.
Next, see how to secure AI-generated code before real users install it, or plan a bigger build with an MVP in a weekend.
- Manifest file format, Chrome for Developers
- The activeTab permission, Chrome for Developers
- Permissions list and warnings, Chrome for Developers
- Manifest content security policy, Chrome for Developers
- Manifest V2 support timeline, Chrome for Developers, September 2026
- Hello World extension tutorial, Chrome for Developers
- Register your developer account, Chrome Web Store docs
- Publish in the Chrome Web Store, Chrome Web Store docs
- Chrome Web Store review process, Chrome Web Store docs
- Chrome Web Store program policies, Chrome Web Store docs
- Chrome Web Store requiring up-front registration fee for all extension developers, 9to5Google, March 2020




