ryanwhocodes May 9, 2018 · 5 min read

How to make a cross-browser extension using JavaScript and browser APIs

This tutorial will cover how to create a web extension that works across multiple browsers.

I will show you how to structure a project and write JavaScript code to interact with the browser’s tabs, depending on which browser is being used. This means you can code and then distribute one extension package to multiple browsers’ web stores.


This post will focus on the Chrome and Firefox browsers, along with distributing extensions via the Chrome Web Store and Firefox Add-ons websites. Other browsers and distribution options are also available for web extensions.

Browser extensions

Extensions are a fantastic way to extend the functionality of your browser, and they allow you to improve your experience online. If you are building your first one or want to learn more about them, I recommend the following:

Template and example

If you would like a simple template browser extension to help you get started, here is one I made you can clone, edit, and publish.

To see a completed example, here’s a link to an extension I made called Link Formatter, with the cross-browser JavaScript within popup.js. The same package is listed in both the Chrome and Firefox web stores.

Load your extension locally on your computer

When developing your extension, you can load it locally without having to publish and download it from an external website. The way you do this depends on which browser you are using.


  • Visit chrome://extensions/ in your Chrome browser
  • Click Load Unpacked
  • Select the extension’s folder


  • Visit about:debugging
  • Click on Load Temporary Add-on
  • Select the manifest.json within the extension’s folder

Debugging tip: to view the console, (for example to see errors), right click/control click on the web extension icon or popup and select inspect

Writing JavaScript for your browser extension

There are many JavaScript API’s that can be used in your browser extension. This post will focus on the tabs API.

For more on web extension APIs, see JavaScript APIs for WebExtensions — Mozilla | MDN.

A browser extension that includes a popup HTML page when the user clicks on the icon in the browser’s toolbar could have a project structure like this:

├── css
│   └── style.css
├── js
│   └── popup.js
├── manifest.json
└── popup.html

The popup.html page would then run the js/popup.js script at the bottom of the page. You would add your JavaScript here.

Note: other project structures could have a folder for library code, as well as JavaScript files that run in other areas of the extension. For example, in the extension’s background scripts, and in any other documents bundled with the extension, including browser action or page action popups, sidebars, options pages, or new tab pages.

Browser tabs APIs

When writing a web extension, you need to use the tabs API to interact with the tabs in the browser. You also need to request permission from the user to do this.

Requesting permissions to access tabs

Permissions need to be set in manifest.json. When a user tries to install the extension, it will prompt the user to confirm that this action is allowed.

"permissions": [

Query tabs with the browser API

Browsers, such as Firefox, use the browser.tabs API to interact with the browser’s tabs. To request info about the window’s tabs, you use the query method, which returns a promise with an array of tabs.

  queryInfo  // object

Read more about browser.tabs.query at tabs.query() — Mozilla | MDN

To request the active tab for the browser window, you would write the following JavaScript:

browser.tabs.query({active: true, currentWindow: true})

To get the current tab, you retrieve the first tab from the returned array of tabs. Following this structure, you can get the data from the browser tab.

const logCurrentTabData = (tabs) => {
  currentTab = tabs[0]

However, when you try to open the extension in Chrome, it throws a an error browser is not defined.

Query tabs with the chrome API

Chrome has its own API for tabs queries. This follows the syntax chrome.tabs → your query

chrome.tabs.query(object queryInfo, function callback)

Read more about Chrome’s tabs API here: chrome.tabs — Google Chrome.

So to use this method call, you would write the following in your browser extension:

   {active: true, currentWindow: true},
   (arrayOfTabs) => { logCurrentTabData(arrayOfTabs) }

Combine APIs to run on multiple browsers

Detect which API to use

You can then include both types of browser queries in your extension by using a conditional statement to determine which one to use.

if(chrome) {
    {active: true, currentWindow: true},
    (arrayOfTabs) => { logCurrentTabData(arrayOfTabs) }
} else {
  browser.tabs.query({active: true, currentWindow: true})

Add more code for each browser type

Within each side of the condition, you can then add other pieces of code that depend on the different APIs, for example to create new tabs.


Here is the code with the extra methods added in that opens a link in a new tab.

if(chrome) {
    {active: true, currentWindow: true},
    (arrayOfTabs) => { logCurrentTabData(arrayOfTabs) }
  $('a').click( (event) => { chrome.tabs.create({url:event.target.href}) } )
} else {
  browser.tabs.query({active: true, currentWindow: true})
  $('a').click( (event) => { browser.tabs.create({url:event.target.href}) } )**

Publish your extension

With this code in place, you can now interact with the current browser without having to write two or more different web extension projects. You can now package your extension and publish to multiple web stores with the same file!

Find out more

As well as the links to developer docs within this tutorial, here are some articles where you can read more about browser extensions on Medium.