Creating a browser extension for Android is a task that seems difficult only at first glance. In fact, even without programming experience, you can develop a useful plugin for Chrome, Firefox or Kiwi Browserif you follow a clear algorithm. Unlike desktop versions, mobile browsers impose a number of restrictions, but also open up unique opportunities: from ad blocking to integration with Android API.

In this article we will analyze the entire process - from preparing the working environment to publishing the finished extension in Chrome Web Store or Firefox Add-ons. You'll learn what tools you'll need, how to get around the limitations of mobile browsers, and why some functions (for example, working with chrome.tabs) require a special approach on Android. We will also look at alternative ways to distribute extensions if official stores refuse to accept them.

It is important to understand that mobile extensions have less functionality compared to desktop ones. For example, Chrome for Android there is still no support background scripts in the classic form. However, with Kiwi Browser (based on Chromium) or Firefox Nightly almost any scenario can be implemented. If your goal is maximum compatibility, you will have to adapt the code for each browser separately.

1. Selecting a browser and preparing tools

Before starting development, decide on the target browser. Not all mobile browsers support extensions, and those that do do so in different ways. Here are the key options: Android support extensions, and those that do support them do it differently. Here are the key options:

  • ๐ŸŒ Kiwi Browser โ€”the best choice for extensions based on Chromium. Supports most desktop APIs, including Chrome, including chrome.storage and chrome.notifications.
  • ๐ŸฆŠ Firefox for Android - supports extensions via WebExtensions, but with limitations. For example, there is no access to the mobile version. Firefox for Android does not officially support extensions (except for enterprise mode). However, you can use workarounds, which we will discuss below. browserAction in the mobile version.
  • ๐Ÿšซ Google Chrome for Android โ€” does not officially support extensions (except for enterprise mode). However, you can use workarounds, which we will discuss below.
  • ๐Ÿ›ก๏ธ Brave Browser - supports extensions, but requires manual installation via adb.

For development you will need:

  • ๐Ÿ’ป Computer with Windows, macOS or Linux (mobile development "on the knee" is possible, but inconvenient).
  • ๐Ÿ“ฑ Android-device with software debugging enabled USB (Settings โ†’ About phone โ†’ Number builds - tap 7 times).
  • ๐Ÿ”ง Android Studio (for debugging through adb) or Visual Studio Code with extension Live Server.
  • ๐Ÿ“ฆ Node.js (for building projects with webpack or Parcel).
โš ๏ธ Attention: If you plan to test the extension on Chrome for Android via enterprise policies, please note that this method requires an enterprise license Google Workspace. Without it, extensions will not work.

For convenience, we recommend starting with Kiwi Browser โ€”it is closest to the desktop Chrome and allows you to test extensions without additional manipulations. Install it from Google Play and enable developer mode in the browser settings (kiwi://extensions).

๐Ÿ“Š Which browser are you using on Android?
Chrome
Firefox
Kiwi Browser
Brave
Other

2. Extension structure: which files are required

Any browser extension consists of a set of files with a clear structure. The minimum set includes:

  • ๐Ÿ“„ manifest.json โ€” the โ€œheartโ€ of the extension, which describes rights, versions and resources.
  • ๐Ÿ“ icons/ โ€” a folder with icons for different resolutions (16x16, 48x48, 128x128).
  • ๐Ÿ“„ popup.html (optional) - HTML page that opens when you click on the extension icon.
  • ๐Ÿ“„ background.js or service-worker.js - script for background tasks (works with limitations in mobile browsers).
  • ๐Ÿ“„ content.js - script that runs on website pages.

Example minimum manifest.json for Kiwi Browser:

{

"manifest_version": 3,

"name": "My extension",

"version": "1.0",

"description": "Test extension for Android",

"icons": {

"16": "icons/icon16.png",

"48": "icons/icon48.png",

"128": "icons/icon128.png"

},

"action": {

"default_popup": "popup.html",

"default_icon": "icons/icon48.png"

},

"permissions": ["storage", "activeTab"]

}

In mobile browsers manifest_version there should be 3 (and not 2, as in old desktop extensions). Also note that some permissions (for example "tabs") may not work or require additional right.

File/folder Required? Purpose
manifest.json Yes Extension configuration, access rights, metadata.
icons/ Yes Icons for display in the browser panel and store.
popup.html No Pop-up window interface when you click on the icon.
background.js No Background tasks (works to a limited extent in mobile browsers).
content.js No Scripts executed on web pages.
โš ๏ธ Attention: In Firefox for Android are not supported browserAction and pageAction from manifest.json. Instead, use sidebar_action or adapt the UI to a mobile interface.

Create a project folder|Add manifest.json|Prepare icons of different sizes|Write popup.html (if needed UI)|Check permissions in manifest.json-->

3. Development of functionality: from simple to complex

Start with a simple extension that performs one task. For example, let's replace all the images on the site with random pictures of cats. To do this, you only need content.js and manifest.json.

Add to manifest.json permission to work with the active tab:

  "permissions": ["activeTab"],

"content_scripts": [

{

"matches": ["<all_urls>"],

"js": ["content.js"]

}

]

Now create content.js:

document.querySelectorAll('img').forEach(img => {

img.src = 'https://placekitten.com/' + img.width + '/' + img.height;

});

This script replaces all images (<img>) on the website for random pictures of cats from the service placekitten.com. To test it:

  1. Go to Kiwi Browser and open kiwi://extensions.
  2. Enable Developer mode (toggle in the upper right corner).
  3. Click Load unpacked extension and select the folder with your project.

If everything is done correctly, when you open any site, all images will be replaced with cats. This example demonstrates the basic principle of operation content_scriptsbut in real projects you will need more complex mechanisms.

๐Ÿ’ก

For debugging content.js use Chrome DevTools on a computer. Connect to Androiddevice via adb and open chrome://inspect in desktop Chrome.

4. Working with storage and settings

Most extensions require data to be saved between sessions - for example, user settings or cache. In browsers on Android this is done using chrome.storage (in Chromium) or browser.storage (in Firefox).

An example of saving and reading data in Kiwi Browser:

// Saving data

chrome.storage.sync.set({ color: 'red' }, () => {

console.log('Color saved');

});

// Reading data

chrome.storage.sync.get(['color'], (result) => {

console.log('Current color: ' + result.color);

});

In Firefox for Android syntax similar, but instead chrome. is used browser.:

browser.storage.local.set({ key: 'value' });

Pay attention to two types of storage:

  • ๐Ÿ”„ storage.sync - synchronized with the account Google (v Chrome) or Firefox. Suitable for small data (~5 MB limit).
  • ๐Ÿ’พ storage.local - stored only on the device. Limit ~5 MB in Chrome and ~10 MB in Firefox.
โš ๏ธ Attention: In mobile browsers. data-i="171">may be unstable due to background activity restrictions. Test saving data on a real device, not in the emulator. storage.sync May be unstable due to background activity restrictions. Test saving data on a real device, not in an emulator.

For complex data (for example, lists of blocked sites), it is better to use IndexedDB via window.indexedDB v content_scripts. However, note that IndexedDB is tied to the site domain, not the extension.

How to bypass the storage.sync limitation in Firefox for Android?

v Firefox for Android storage.sync is not supported at all. Instead, use storage.local or implement your own synchronization via Firebase or another cloud service. This will require a backend, but this is the only way to synchronize data between devices.

5. Testing and debugging on an Android device

Testing extensions on Android is different from desktop development. Here are the key steps:

  1. Connect via ADB:

    Make sure that software debugging is enabled on your device USB (Settings โ†’ System โ†’ For Developers). Connect the device to the computer and do:

    adb devices

    If the device is not displayed, install drivers ADB for your model Android.

  2. Installing an extension:

    Download the extension via Kiwi Browser download the extension via kiwi://extensions. In Firefox use WebExt Tool:

    web-ext run --target=firefox-android --android-device=DEVICE_ID
  3. Debugging:

    For Chromiumbrowsers open chrome://inspecton your computer, select your device and click Inspect next to the extension tab. To Firefox use about:debugging.

Frequent problems during testing:

  • ๐Ÿ”Œ Extension does not load - check manifest.json for errors (for example, incorrect version manifest_version).
  • ๐Ÿ“ต ADB does not see the device โ€” restart the device and computer, check the cable USB (itโ€™s better to use the original one).
  • ๐Ÿšซ No access to API โ€”some permissions (for example, "tabs") may be blocked in the mobile version.
๐Ÿ’ก

Test the extension on a real device, not just in the emulator. Many errors (for example, related to permissions) appear only on physical devices.

6. Publish the extension: Chrome Web Store vs. Firefox Add-ons

When the extension ready, it can be published in official stores. The process is different for Chrome Web Store and Firefox Add-ons.

Publishing in the Chrome Web Store

Algorithm for Kiwi Browser (and other Chromiumbrowsers):

  1. Create a ZIP archive with extension files (without a folder).
  2. Register as a developer in Chrome Web Store (one-time payment $5).
  3. Upload the archive to DevConsole, fill in the metadata (description, screenshots, category).
  4. Pay for publication (if this is your first extension).
  5. Wait for moderation (usually 1-7 days).

Publishing in Firefox Add-ons

For Firefox the process is simpler:

  1. Create a ZIP archive (similar to Chrome).
  2. Register on AMO (free).
  3. Download the extension via Developer Hub. Firefox does not charge for publication.
  4. Go through automatic and manual moderation (usually 1-3 days).

Restrictions for mobile extensions:

  • ๐Ÿ“ฑ Q Chrome Web Store extensions for Android are not allocated to a separate category Please indicate in. description that it is intended for mobile devices.
  • ๐Ÿ” Firefox requires separate verification for the mobile version. If your extension uses an unsupported API, it may be rejected.
โš ๏ธ Attention: If your extension modifies pages (for example, blocks ads), it may be rejected by Chrome Web Store according to policy Google. In this case, consider alternative distribution methods (see the next section).
How to publish an extension without moderation?

The only legal way is to distribute the extension as a .crxfile through your website. manually via kiwi://extensions (in Kiwi Browser) or about:debugging (in Firefox). However, this method requires users to enable developer mode, which is inconvenient.

7. Alternative distribution methods

If your extension has not been moderated in official stores (for example, due to ad blocking), there are workarounds:

  • ๐ŸŒ Self hosting:

    Post the extension files on your website or GitHub. Users will be able to download the ZIP archive and download it manually via kiwi://extensions (for Kiwi Browser) or about:config (for Firefox).

  • ๐Ÿ“ฆ APK with a pre-installed extension:

    Build a modified version Kiwi Browser or Firefox with a built-in extension. This will require assembly skills APK from sources.

  • ๐Ÿ”— Link to install via ADB:

    Provide users with a command to install via adb:

    adb install-extension --package-name=com.kiwibrowser.browser PATH_TO_EXTENSION

Advantages and risks of alternative methods:

Method Pros Cons
Self hosting No moderation, full control Users must manually enable developer mode
APK with extension Convenient for users (installation as a regular application) Requires updating the entire APK when changing the extension
Installation via ADB Works without developer mode in the browser Requires a connection to a PC and knowledge of commands adb

If you choose self-distribution, make sure that your site is protected by HTTPSand the extension files do not contain malicious code Users must trust the source, so add instructions for. checking the integrity of files (for example, through hash sums SHA-256).

8. Optimization for mobile devices

Extensions on Android should take into account the features of the mobile interface:

  • ๐Ÿ“ฑ Responsive design:

    If your extension has popup.htmlmake sure that it displays correctly on small devices screens. Use media queries @media to adapt:

    @media (max-width: 400px) {
    

    body { font-size: 14px; }

    button { padding: 8px; }

    }

  • ๐Ÿ”‹ Save battery:

    Avoid constant activity in the background. In mobile browsers, background scripts (background.js) are often suspended by the system to save energy.

  • ๐Ÿš€ Performance:

    Optimize the code so that it does not slow down the browser. For example, instead of setInterval use requestIdleCallback for background tasks.

Example of optimized content.js for mobile devices:

// Bad: constant DOM polling

setInterval(() => {

document.querySelectorAll('img').forEach(img => { ... });

}, 1000);

// Good: using MutationObserver

const observer = new MutationObserver((mutations) => {

mutations.forEach(() => {

document.querySelectorAll('img:not(.processed)').forEach(img => {

img.src = 'https://placekitten.com/200/200';

img.classList.add('processed');

});

});

});

observer.observe(document.body, { childList: true, subtree: true });

In mobile browsers MutationObserver consumes less resources than setInterval, since it only fires when there are changes in the DOM.

๐Ÿ’ก

Test the extension on devices with different screen resolutions and versions Android. What works on a flagship may slow down on a budget smartphone.

FAQ: Frequently asked questions about developing extensions for Android

Is it possible to make an extension for Chrome on Android without Kiwi Browser?

Officially - no. Google Chrome for Android does not support extensions for ordinary users. However, there are workarounds: Google Chrome for Android data-i="316">with superuser rights (root required).

  1. Use Chrome in enterprise mode (Volume license required).
  2. Install the extension via adb with superuser rights (root required).
  3. Use alternative browsers (Kiwi, Firefox, Brave).
How to update the extension for users if it is installed manually?

When you distribute it yourself, updates do not occur automatically. You need to:

  1. Change the version in manifest.json (for example, from "1.0" to "1.1").
  2. Collect a new ZIP archive and place it on the site.
  3. Inform users about the need to reinstall the extension.

Automatic updates require publishing to Chrome Web Store or Firefox Add-ons.

Why does my extension work on PC, but not on Android?

Main reasons:

  • manifest_version there should be 3 (version 2 is also found in desktop extensions).
  • Some APIs (for example, chrome.tts) are not supported on mobile browsers.
  • Restrictions on background scripts - in Android they can be suspended.
  • Lack of rights to some permissions (for example, "management").

Check the logs through Chrome DevTools or Firefox Debugger on a real device.

Is it possible to make money on mobile extensions?

Yes, but it is more difficult than on desktop ones. The main methods of monetization:

  • ๐Ÿ’ฐ Paid publication - selling extensions in stores (for example, via Gumroad).
  • ๐Ÿ“ข Advertising โ€” integration of banners into popup.html (but this may cause rejection during moderation).
  • ๐Ÿ”“ Freemium model โ€” basic version free, premium features for fee.
  • ๐Ÿค Affiliate apps โ€” if the extension is associated with a specific service (for example, VPN).

Please note that mobile users are less likely to pay for extensions than desktop ones.

How to protect extension code from copying?

It is impossible to completely protect JavaScript code, but you can complicate the task:

  • Use obfuscators (for example, JavaScript Obfuscator).
  • Move critical logic to the backend (for example, via Cloud Functions).
  • Add a license check when loading the extension.
  • Distribute the extension in closed communities (for example, via Patreon).

Remember that obfuscation can slow down the extension on weaker users) devices.