27 Nov 2023 · Software Engineering

    How to Build a Google Chrome Extension in 6 Steps Using ChatGPT

    19 min read

    Chrome extensions have become an integral part of the browsing experience, allowing users to enhance and customize their web interactions. In this tutorial, I will guide you step-by-step in building your own Chrome extension using ChatGPT. We will explore how to leverage the language model’s capabilities to automate the code generation process. As I take you through each step, I will be building a simple Chrome extension using ChatGPT, for demonstration purposes, so that you can follow along. The Chrome extension I will be building will be referred to as “URL Saver” and it allows users to:

    • Save the URL of the website they’re currently on.
    • Add a title for every URL they want to save.
    • View a list of all saved URL’s once clicking on the extension.
    • Save a maximum of 20 URL’s.
    • Delete any URL from the list by clicking on a cross that appears next to each item.

    Pre-requisites: This tutorial is targeted at those who have a beginner to intermediate knowledge of coding and development. You will need to familiarize yourself with Google’s documentation on how to migrate Chrome extensions from Manifest Version 2 to Manifest Version 3. Everything else will be clearly explained in this tutorial.

    The Architecture Behind a Chrome Extension

    Before I launch into the tutorial, I am going to provide a brief overview of all the files that could make up a Chrome extension. This is important because you will need to know which files to ask ChatGPT to write code for, depending on what you want your extension to do. Furthermore, from time-to-time ChatGPT does produce code with bugs. Therefore, knowing the function of each file can help you identify which file the issue is in if your extension does not perform as expected. Let’s start off with the manifest.json file.


    The manifest file is a JSON file that defines the basic properties of your extension, such as its name, description, version, permissions, and background page. It is also used to declare the extension’s content scripts and service workers.


    The service worker file is a JavaScript file that defines the extension’s service worker. A service worker is a background process that can handle network requests and other tasks even when the extension is not active. This can improve the performance of your extension and allow it to work offline.


    The content script file is a JavaScript file that can be injected into web pages. Content scripts can be used to:

    • Modify the content of web pages.
    • Add new functionality.
    • Track user activity.

    The popup.css file is a CSS file that defines the style of the extension’s popup window. It determines the visual appearance of the window when it appears after a user clicks on the extension’s icon in the Chrome toolbar.

    The popup.js file is a JavaScript file that is executed when the extension’s popup window is opened. It allows developers to add functionality and interactivity to the popup window. This file serves various purposes, including:

    • Listen for events.
    • Update the content of the popup window.

    In addition to the CSS and JavaScript files, the popup.html file:

    • Determines what information is displayed to the user.
    • Provides user controls and interactive elements.
    • Allows for the execution of JavaScript code within the popup window.

    It serves as the foundation for constructing the visual layout and structure of the window, enabling developers to present relevant information, interactive features, and a user-friendly interface to enhance the extension’s functionality and usability.

    options Files

    The options.css file is a CSS file that defines the style of the extension’s options page. It determines how the options page appears visually to the user. When the user clicks on the extension’s icon in the Chrome toolbar and selects “Options,” a small window, known as the options page, appears. This page allows users to configure the settings of the extension according to their preferences.

    The options.js file, on the other hand, is a JavaScript file that executes when the extension’s options page is opened. It provides the functionality for the options page and allows developers to implement various actions and behaviours. Some of the tasks that can be performed using options.js include:

    • Event listening.
    • Updating the content of the options page dynamically.

    The options.html file is an HTML file that defines the content of the extension’s options page. It serves as the structure and layout of the page, providing the foundation for the visual elements and user interface components. By modifying the options.html file, developers can design and organize the content of the options page, enabling users to conveniently customize the settings of the extension to their liking.

    Icon Files

    The icons files define the icons for your extension. The icons files must be located in the extension’s root directory.

    It is important to note that not all the files I’ve described will be used for every extension. Rather, based on the requirements and design you have in mind for your extension, you will only be using a few selected files.

    Step 1: Set Up the Development Environment

    In order to setup our development environment, we first must identify what files our extension will need in order to work the way we want it to. For example, based on my description of the URL Saver extension and the functions of the files I have described, we can see that we will need the following files:

    • manifest.json
    • content-script.js
    • popup.css
    • popup.js
    • popup.html
    • Icon files

    Now that we know what files we need, we can begin setting up our development environment by following the steps below:

    1. Open a text editor of your choosing.
    2. Create a folder named after the extension you want to create.
    3. In the folder, create and name appropriately the files you will need to build your extension.

    Step 2: Add in the Code

    Now that our development environments are properly setup, we need to prompt ChatGPT to write the code for us. We will need to send a prompt to ChatGPT that includes an appropriate mix of the following:

    • Detailed description of our extension.
    • Name of the file we want written.
    • Specific instructions of what we want written in the file.
    • Request to begin writing the code for each file.

    Once the code has been printed, you need to copy and paste it into the appropriate files.

    I will also be providing all the prompts I used to get ChatGPT to print the code for each file in the “URL Saver” extension. It’s important to note that even if you use the exact same prompts I will provide below, there is a chance ChatGPT will produce code with slight deviations from the one it provided me. If the deviations affect the functionality of the end product in any way, all you have to do is ask ChatGPT to make the appropriate changes you want and reprint the code. Alternatively you can also try regenerating the response until ChatGPT gives you the exact code you want.

    • Here is the prompt I used to get the manifest.json file:

    “Create a manifest file for a Chrome extension called “URL Saver” with the following specifications:

    1. Set the manifest version to 2.
    2. Name the extension “URL Saver.”
    3. Assign it the version “1.0.”
    4. Provide a description: “Save and manage website URLs.”
    5. Define icons for various sizes (16×16, 32×32, 48×48, and 128×128) with corresponding image files: “icon16.png,” “icon32.png,” “icon48.png,” and “icon128.png.”
    6. Specify the necessary permissions: “tabs” and “storage.”
    7. Configure a browser action with a default popup HTML file named “popup.html” and an icon file named “icon.png.”
    8. Include a content script that matches all URLs (“<all_urls>”) and use the script file “content-script.js.”
    9. Make “popup.css” a web-accessible resource available for all URLs (“<all_urls>”).

    Please generate the manifest.json file based on these requirements.”

    • The manifest.json file that printed:
      "manifest_version": 2,
      "name": "URL Saver",
      "version": "1.0",
      "description": "Save and manage website URLs",
      "icons": {
        "16": "icon16.png",
        "32": "icon32.png",
        "48": "icon48.png",
        "128": "icon128.png"
      "permissions": [
      "browser_action": {
        "default_popup": "popup.html",
        "default_icon": "icon16.png"
      "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content-script.js"]
      "web_accessible_resources": [
            "resources": ["popup.css"],
            "matches": ["<all_urls>"]

    For the URL Saver extension, the above code specifies the:

    • Version.
    • Name.
    • Description.
    • Icons.

    It also declares the required permissions, including access to tabs and storage APIs. The browser action section determines the default popup HTML file and icon for the extension’s toolbar button. The manifest includes a content script that will be injected into all web pages.

    • Here is the following prompt I used to get the content-script.js file:

    “Create a content script for the “URL Saver” Chrome extension. The content script should have the following functionality:

    1. Listen for changes in the URL of the currently active tab.
    2. When the URL changes, send a message to the extension background script with the updated URL.
    3. The content script should be triggered by the chrome.tabs.onUpdated event.
    4. The content script should only send a message when the changeInfo object contains a valid URL (i.e., when changeInfo.url is present).
    5. Use the chrome.runtime.sendMessage method to send the message to the extension background script.
    6. Ensure that the code is encapsulated within a JavaScript function or block as necessary.

    Please provide the JavaScript code that accomplishes the above tasks.”

    • The content-script.js file that printed:
    // Listen for changes in the URL and send a message to the extension
    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
      if (changeInfo.url) {
        chrome.runtime.sendMessage({ url: changeInfo.url });

    The above code listens for changes in the URL of the active tab. When a URL update occurs, the chrome.tabs.onUpdated event listener is triggered. It checks if the changeInfo.url property exists, indicating that the URL has changed. If so, it sends a message to the extension using chrome.runtime.sendMessage(), passing the updated URL as the payload. This allows the extension to receive and handle the URL updates from the content script.

    Please also note that I have intentionally left a bug in the content-script.js code above as an exercise for you to try debugging files using ChatGPT in Step 5 of this tutorial. You will find the following error in the above code: TypeError: Cannot read properties of undefined (reading ‘onUpdated’)

    • Here is the following prompt I used to get the popup.css file:

    “Please create a CSS code snippet for a Chrome extension popup with the following styles:

    1. Set the width of the body element to 300px.
    2. Center-align the text in the h1 element.
    3. Style the ul element to have no bullet points and zero padding.
    4. For each li element within the ul, do the following:
    • Add a margin of 10px to the bottom.
    • Make them display as flex containers.
    • Align the items within each li element to the center.
    1. Style elements with the class .delete-button to have the following properties:
    • Text color: red.
    • Cursor: pointer.
    • Margin to the left: 5px.

    Please ensure that the generated CSS adheres to these specifications for a Chrome extension popup.”

    • The popup.css file that printed:
    body {
      width: 300px;
    h1 {
      text-align: center;
    ul {
      list-style-type: none;
      padding: 0;
    li {
      margin-bottom: 10px;
      display: flex;
      align-items: center;
    .delete-button {
      color: red;
      cursor: pointer;
      margin-left: 5px;

    The provided CSS code defines the styling for the extension’s popup window. It ensures a visually pleasing and well-organized appearance for the popup window of the extension.

    • Here is the following prompt I used to get the popup.js file:

    “I want to create a Chrome extension named “URL Saver” with the following features:

    1. Users can save the URL of the website they are currently on.
    2. Users can add a title for every URL they want to save.
    3. Users can view a list of all the saved URLs by clicking on the extension icon in the popup.
    4. The extension should allow users to save a maximum of 20 URLs. When the limit is reached, the oldest URL should be removed to make space for the new one.
    5. Users should be able to delete any URL from the list by clicking on a cross (X) icon that appears next to each item.

    Please provide the JavaScript code for the popup.js file that implements these features. The code should include the following functions:

    1. A function named deleteURL(index) that deletes a URL from storage and updates the list in the popup when given an index. It should use the Chrome storage API.
    2. A function named displayURLs(urls) that displays the saved URLs in the popup. It should take an array of URL objects as input and render them in an HTML list. Each list item should include the URL’s title, a clickable link to the URL, and a delete button.
    3. Retrieve the saved URLs from storage when the popup is opened and display them using the displayURLs function.
    4. Listen for a click event on a “Save” button in the popup. When clicked, it should save the current URL and a user-provided title using the Chrome storage API. If the limit of 20 URLs is reached, the oldest URL should be removed. After saving, the list of URLs should be updated.

    Please ensure that the code is structured and commented for clarity. Thank you!”

    • The popup.js file that printed:
    // Function to delete a URL from storage and update the list in the popup
    function deleteURL(index) {
      chrome.storage.local.get('urls', function(result) {
        let urls = result.urls || [];
        urls.splice(index, 1);
        chrome.storage.local.set({ urls: urls }, function() {
          // Update the displayed list
    // Function to display the URLs in the popup
    function displayURLs(urls) {
      const urlList = document.getElementById('urlList');
      urlList.innerHTML = '';
      urls.forEach(function(urlObj, index) {
        const listItem = document.createElement('li');
        const title = document.createElement('strong');
        const link = document.createElement('a');
        const deleteButton = document.createElement('span');
        title.textContent = urlObj.title;
        link.href = urlObj.url;
        link.target = '_blank';
        link.textContent = urlObj.url;
        deleteButton.className = 'delete-button';
        deleteButton.textContent = 'X';
        deleteButton.addEventListener('click', function() {
    // Retrieve the saved URLs from storage and display them in the popup
    chrome.storage.local.get('urls', function(result) {
      const urls = result.urls || [];
    // Listen for a click event on the save button and save the current URL
    document.getElementById('saveButton').addEventListener('click', function() {
      chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
        const currentTab = tabs[0];
        const url = currentTab.url;
        const title = prompt('Enter a title for the URL:', currentTab.title);
        if (url && title) {
          chrome.storage.local.get('urls', function(result) {
            let urls = result.urls || [];
            if (urls.length >= 20) {
              urls.shift(); // Remove the oldest URL if the limit is reached
            urls.push({ title: title, url: url });
            chrome.storage.local.set({ urls: urls }, function() {
              // Update the displayed list

    The above code handles the functionality of saving, deleting, and displaying URLs in the extension’s popup. It includes functions for deleting a URL from storage and updating the displayed list, as well as displaying the URLs in the popup with clickable links and delete buttons. The saved URLs are retrieved from storage and displayed when the popup is opened. Additionally, a click event listener is added to the save button, allowing the user to save the current URL with a custom title. The code ensures that the maximum limit of 20 URLs is maintained by removing the oldest URL if necessary.

    • Here is the following prompt I used to get the popup.html file:

    “Please generate an HTML file named “popup.html” for a Chrome extension called “URL Saver.” The extension should have the following features:

    1. Allow users to save the URL of the website they’re currently on.
    2. Provide an input field for users to add a title for the URL they want to save.
    3. Display a list of all saved URLs.
    4. Limit the maximum number of saved URLs to 20.
    5. Allow users to delete any URL from the list by clicking on a cross that appears next to each item.”
    • The popup.html file that printed:
    <!DOCTYPE html>
      <title>URL Saver</title>
      <h1>URL Saver</h1>
      <div id="urlContainer">
        <ul id="urlList"></ul>
        <div id="buttonContainer">
          <button id="saveButton">Save URL</button>
      <script src="popup.js"></script>

    The provided HTML code represents the structure of the extension’s popup window. The HTML file also includes a reference to the popup.js JavaScript file for handling the interactivity and functionality of the popup window.

    Step 3: Switch from Manifest Version 2 to Manifest Version 3

    Looking at the code that was generated for the URL Saver extension, you may have noticed that ChatGPT wrote the manifest.json file in Manifest Version 2. This is because the ChatGPT’s training data is cut off at 2021 and it does not know that Google will stop supporting extensions using Manifest Version 2 from 1 June 2023. When I have asked ChatGPT to code extensions in Manifest Version 3, it consistently produced code with bugs. Therefore, it is easier to have ChatGPT write the code in Version 2 and migrate it ourselves.

    The reason why one of the pre-requisites for this article was to familiarize yourself with Google’s documentation on how to migrate from Version 2 to 3, is because every extension is unique, so the modifications that will need to be done to the code during the migration will differ. Once you read through the documentation, you will be equipped with the knowledge to migrate any extension you create with ChatGPT to Version 3.

    To migrate the URL Saver extension over to Version 3, I only had to update the manifest.json file. I changed "manifest_version": 2 to "manifest_version": 3 and I replaced the browser_action key with the action key. These changes align with the updated Manifest Version 3 syntax, explained by Google in their documentation. Below you can see an updated version of the manifest.json file for the URL Saver extension.

      "manifest_version": 3,
      "name": "URL Saver",
      "version": "1.0",
      "description": "Save and manage website URLs",
      "icons": {
        "16": "icon16.png",
        "32": "icon32.png",
        "48": "icon48.png",
        "128": "icon128.png"
      "permissions": [
      "action": {
        "default_popup": "popup.html",
        "default_icon": "icon16.png"
      "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content-script.js"]
      "web_accessible_resources": [
            "resources": ["popup.css"],
            "matches": ["<all_urls>"]

    Step 4: Add in the Icon Files

    Finally, you will need to add four PNG icons to your projects root directory:

    • icon16.png: This icon is used in the Chrome toolbar.
    • icon32.png: This icon is used in the Chrome extensions management page.
    • icon48.png: This icon is used in the Chrome extensions options page.
    • icon128.png: This icon is used in the Chrome Web Store.

    Here are links to 4 icons you can consider using in this project:

    1. Image 1
    2. Image 2
    3. Image 3
    4. Image 4

    Remember to name the icons you add to the root directory appropriately, as described above.

    Step 5: Test and Debug the Chrome Extension with ChatGPT

    Now that your extension is complete, you will need to test it. In order to do that you will need to:

    1. Ensure “Developer Mode” is enabled at upper right.
    2. Open Chrome and go to chrome://extensions.
    3. Click on the Load unpacked extension button.
    4. Select the folder containing your extension’s files.
    5. Test the extensions functionality on different websites.
    6. Check for errors. As you test the extension, pay attention to any errors that may occur. These errors could be caused by a problem with your code or with the website you are testing on.

    If you find any bugs in your code or your extension is not working as intended, you should:

    1. Identify the file or files where the problem lies.
    2. Paste the code of the file into ChatGPT.
    3. Describe the problem you are facing in detail.
    4. Prompt ChatGPT to modify the code to fix the problem.

    Step 6: Publish the Chrome Extension

    Now that you have a working Chrome extension, you can follow the steps below if you wish to publish it to the Chrome Web Store:

    1. Create a developer account. You need to create a Google Developer account in order to publish a Chrome extension. The cost of a developer account is $5 per year.
    2. Package your extension. Once you have created your manifest file, you need to package your extension into a ZIP file. You can do this using a ZIP compression tool, such as 7-Zip or WinRAR.
    3. Upload your extension to the Chrome Web Store. Once you have packaged your extension, you can upload it to the Chrome Web Store. To do this, go to the Chrome Web Store Developer Dashboard and click the “Add New Item” button. Then, select “Extension” from the list of item types and click the “Create” button. Follow the instructions on the screen to upload your extension.
    4. Submit your extension for review. Once you have uploaded your extension, it will be reviewed by Google. This process can take a few days. Once your extension has been approved, it will be published in the Chrome Web Store.


    In conclusion, building a Chrome extension with the help of ChatGPT can greatly simplify the development process. By understanding the architecture, setting up the environment, adding the code, transitioning to manifest version 3, incorporating icon files, conducting thorough testing, and publishing the extension, you can successfully create and share your own Chrome extension with the world.

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Writen by:
    Bradley is the Co-founder of Mylah Digital. He has a passion for Web Development, paired with a curious interest for Machine Learning and A.I. He loves working on new projects and often finds himself creating technical content to share his knowledge.
    Reviewed by:
    I picked up most of my soft/hardware troubleshooting skills in the US Army. A decade of Java development drove me to operations, scaling infrastructure to cope with the thundering herd. Engineering coach and CTO of Teleclinic.