Comment créer une extension Chrome ? Guide complet pour développer votre première extension

30 janvier 2026

Smartphone affichant le logo Google Chrome sur un carnet rouge idéal pour apprendre à créer une extension Chrome et optimiser sa navigation sur mobile et bureau

Vous souhaitez personnaliser votre expérience de navigation ou créer un outil qui améliorera la productivité de milliers d’utilisateurs ? Développer une extension Chrome représente l’une des opportunités les plus accessibles pour transformer une idée en produit concret. Avec plus de trois milliards d’utilisateurs actifs de Chrome, le potentiel de diffusion est considérable. Je vais vous accompagner à travers toutes les étapes pour concevoir, développer et publier votre première extension, en maîtrisant l’architecture Manifest V3, les interfaces réactives et les APIs Chrome.

Introduction : prérequis et fonctionnement d’une extension Chrome

Qu’est-ce qu’une extension Chrome ?

Une extension Chrome est un programme léger qui personnalise et enrichit l’expérience de navigation en s’intégrant directement dans le navigateur. Techniquement, il s’agit d’un ensemble de fichiers HTML, CSS et JavaScript orchestrés par un fichier manifest.json.

Les extensions accèdent aux APIs Chrome qui permettent de :

  • Manipuler les onglets et leur contenu
  • Stocker des données localement de manière sécurisée
  • Gérer les favoris et l’historique de navigation
  • Intercepter les requêtes réseau avant leur envoi
  • Interagir avec le système de notifications du navigateur

Le Chrome Web Store héberge aujourd’hui plus de 130 000 extensions. Depuis janvier 2024, toutes les nouvelles extensions doivent utiliser Manifest V3, qui a remplacé les background pages persistantes par des service workers et interdit le code hébergé à distance pour renforcer la sécurité et les performances.

Connaissances nécessaires pour développer

Le développement d’extensions Chrome s’appuie sur des technologies web standard. Les compétences fondamentales incluent :

  • JavaScript moderne (ES6+) avec promises, async/await et arrow functions
  • Manipulation du DOM pour modifier les pages web
  • HTML et CSS pour créer les interfaces
  • JSON pour configurer le manifest

Les outils essentiels sont un éditeur de code performant comme Visual Studio Code, les DevTools de Chrome pour déboguer, et Git pour le versionnement. Pour les extensions simples, Vanilla JavaScript suffit amplement. Les frameworks comme React, Vue ou Angular peuvent être utiles pour des projets complexes, mais je vous conseille de commencer avec du JavaScript pur pour bien comprendre les mécanismes fondamentaux.

Architecture et configuration du manifest.json

Structure des fichiers et organisation du projet

Une architecture typique comprend :

  • À la racine : le fichier manifest.json
  • Un dossier icons : vos icônes en 16×16, 48×48, 128×128 pixels
  • Un dossier popup : les fichiers HTML, CSS et JavaScript de votre interface
  • Un dossier content : les content scripts qui s’injectent dans les pages
  • Un dossier background : votre service worker en arrière-plan
  • Un dossier options : votre page de configuration (si nécessaire)

Excluez de votre package final les fichiers .vscode, .idea, .git, .gitignore et node_modules. Ces fichiers alourdiraient inutilement votre extension et pourraient causer des problèmes lors de la validation.

Créer et configurer le fichier manifest.json

Le manifest.json constitue le point d’entrée de votre extension. La structure minimale comprend :

  • manifest_version : doit être 3
  • name : le nom de votre extension
  • version : versionnement sémantique (ex: « 1.0.0« )
  • description : présentation concise

Le service worker s’exécute uniquement quand nécessaire, puis s’arrête pour économiser les ressources. La section content_scripts définit quels scripts s’injectent dans quelles pages via des patterns d’URL.

{
  "manifest_version": 3,
  "name": "Ma Première Extension",
  "version": "1.0.0",
  "description": "Extension de démonstration pour apprendre le développement Chrome",
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  "action": {
    "default_popup": "popup/popup.html",
    "default_icon": "icons/icon48.png",
    "default_title": "Cliquez pour ouvrir"
  },
  "background": {
    "service_worker": "background/service-worker.js",
    "type": "module"
  },
  "content_scripts": [
    {
      "matches": ["https://*/*", "http://*/*"],
      "js": ["content/content-script.js"]
    }
  ],
  "permissions": [
    "storage",
    "activeTab"
  ]
}

La propriété type avec « module » permet d’utiliser les modules ES6 dans votre service worker.

Définir les permissions et métadonnées

Demandez uniquement les permissions strictement nécessaires. Le tableau permissions contient les autorisations pour accéder aux APIs Chrome :

  • « storage » : utiliser l’API de stockage local
  • « tabs » : accéder aux informations sur les onglets
  • « notifications » : afficher des notifications système
  • « activeTab » : accéder à l’onglet actif sur action utilisateur
Un utilisateur sur un ordinateur portable consultant Google dans la neige illustrant les premières recherches pour apprendre à créer une extension Chrome utile

Les host_permissions spécifient les domaines sur lesquels votre extension peut interagir. Utilisez des patterns précis comme « https://.example.com/ » plutôt que « https:/// » pour tous les sites.

Bloquer un site sur Chrome : reprenez enfin le contrôle de votre écran

PermissionUsage typiqueNiveau de sensibilité
storageSauvegarder les préférences utilisateurFaible
activeTabAccéder à l’onglet actif sur action utilisateurFaible
tabsLire les URLs et titres de tous les ongletsMoyen
webRequestIntercepter et modifier les requêtes réseauÉlevé
declarativeNetRequestBloquer ou modifier des requêtes (règles déclaratives)Moyen
cookiesLire et modifier les cookiesÉlevé

Certaines permissions nécessitent une justification détaillée lors de la soumission au Chrome Web Store. Préparez-vous à expliquer clairement pourquoi votre extension a besoin de chaque permission sensible.

Développer l’interface et les fonctionnalités de votre extension

Créer la popup (HTML, CSS, JavaScript)

La popup doit être légère et se charger rapidement. Limitez sa taille à quelques centaines de kilooctets, ressources incluses. Les dimensions s’ajustent automatiquement au contenu, dans les limites de 800×600 pixels maximum.

Structure essentielle :

  • Balises HTML sémantiques
  • Styles via CSS externe
  • Scripts JavaScript externes (jamais inline)
  • Pas d’attributs onclick dans le HTML
// popup.js
document.addEventListener('DOMContentLoaded', async () => {
  const button = document.getElementById('actionButton');
  const statusElement = document.getElementById('status');
  
  const data = await chrome.storage.local.get(['savedValue']);
  if (data.savedValue) {
    statusElement.textContent = `Valeur sauvegardée : ${data.savedValue}`;
  }
  
  button.addEventListener('click', async () => {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    
    chrome.tabs.sendMessage(tab.id, {
      action: 'performAction',
      data: { timestamp: Date.now() }
    }, (response) => {
      if (chrome.runtime.lastError) {
        statusElement.textContent = 'Erreur : ' + chrome.runtime.lastError.message;
      } else {
        statusElement.textContent = 'Action effectuée avec succès !';
      }
    });
  });
});

Une popup qui se charge en moins de 100 millisecondes offre une expérience utilisateur optimale. Pour l’accessibilité, ajoutez des labels appropriés, assurez la navigation au clavier, utilisez des contrastes suffisants et testez avec un lecteur d’écran.

Utiliser les content scripts pour interagir avec les pages web

Les content scripts s’exécutent dans le contexte de la page et permettent de lire et modifier le DOM. Le champ matches accepte des patterns d’URL pour cibler des sites spécifiques.

Le timing d’injection se contrôle via run_at :

  • « document_idle » (par défaut) : attend que le DOM soit complètement chargé
  • « document_start » : s’exécute avant tout autre script
  • « document_end » : intervient quand le DOM est prêt
// content-script.js
console.log('Content script chargé sur', window.location.href);

const titles = document.querySelectorAll('h1');
titles.forEach(title => {
  title.style.color = '#4285f4';
  title.style.fontWeight = 'bold';
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'performAction') {
    const result = document.querySelectorAll('p').length;
    sendResponse({ 
      success: true, 
      paragraphCount: result 
    });
  }
  return true; // Nécessaire pour les réponses asynchrones
});

const observer = new MutationObserver((mutations) => {
  mutations.forEach(mutation => {
    if (mutation.addedNodes.length) {
      mutation.addedNodes.forEach(node => {
        if (node.nodeName === 'H1') {
          node.style.color = '#4285f4';
        }
      });
    }
  });
});

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

Les content scripts partagent le DOM avec la page mais possèdent leur propre contexte JavaScript isolé. Pour interagir avec le JavaScript de la page, utilisez window.postMessage. Les content scripts ne peuvent pas utiliser toutes les APIs Chrome – pour chrome.tabs ou chrome.windows, passez par votre service worker.

Vie privée : ce que Google sait réellement de vous

Exploiter les APIs Chrome (Tabs, Storage, Notifications)

L’API Tabs gère les onglets du navigateur. L’accès aux URLs et titres nécessite la permission « tabs », mais pas pour les opérations basiques comme la création.

const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });

await chrome.tabs.create({
  url: 'https://example.com',
  active: true
});

await chrome.scripting.executeScript({
  target: { tabId: activeTab.id },
  func: () => {
    document.body.style.backgroundColor = 'lightblue';
  }
});

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete') {
    console.log('Onglet chargé:', tab.url);
  }
});

L’API Storage fonctionne de manière asynchrone et synchronise les données entre appareils avec storage.sync. Capacité : 10 Mo pour storage.local et 100 Ko pour storage.sync.

Loupe zoomant sur le texte Search en lettres multicolores évoquant la phase d'analyse de données pour créer une extension Chrome performante et ciblée
await chrome.storage.local.set({
  userPreferences: {
    theme: 'dark',
    notifications: true
  },
  lastVisit: new Date().toISOString()
});

const result = await chrome.storage.local.get(['userPreferences', 'lastVisit']);

chrome.storage.onChanged.addListener((changes, areaName) => {
  for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
    console.log(`${key} changé de ${oldValue} à ${newValue}`);
  }
});

L’API Notifications affiche des notifications système. Nécessite la permission « notifications ».

await chrome.notifications.create('notification-id', {
  type: 'basic',
  iconUrl: 'icons/icon48.png',
  title: 'Alerte importante',
  message: 'Votre tâche est terminée !',
  priority: 2
});

chrome.notifications.onClicked.addListener((notificationId) => {
  chrome.notifications.clear(notificationId);
});

D’autres APIs utiles : Bookmarks (favoris), History (historique), ContextMenus (menu contextuel), DeclarativeNetRequest (bloquer/modifier des requêtes). Toutes ces APIs retournent des Promises en Manifest V3 – utilisez async/await pour une meilleure lisibilité.

Tester et déboguer votre extension

Charger l’extension en mode développeur

Ouvrez Chrome et naviguez vers chrome://extensions/. Activez le « Mode développeur » en haut à droite, puis cliquez sur « Charger l’extension non empaquetée ». Sélectionnez le dossier contenant directement le manifest.json.

Chrome affiche des erreurs détaillées si le manifest contient des problèmes : syntaxe JSON, chemins invalides, permissions incorrectes. Une fois chargée, épinglez l’extension à la barre d’outils via l’icône de puzzle.

À chaque modification du manifest, content scripts ou service worker, rechargez l’extension via l’icône circulaire sur chrome://extensions/. Les modifications dans la popup nécessitent généralement juste un rafraîchissement.

Utiliser les outils de développement Chrome

Pour déboguer la popup, clic droit sur l’icône de l’extension > « Inspecter la popup ». Pour le service worker, cliquez sur « service worker » dans chrome://extensions/. Les content scripts se déboguent dans les DevTools de la page (F12) sous la section « Content scripts ».

Utilisez généreusement :

  • console.log() pour tracer l’exécution
  • console.warn() pour les avertissements
  • console.error() pour les erreurs critiques
  • console.table() pour les données structurées

L’onglet Network montre toutes les requêtes réseau. L’onglet Performance identifie les fonctions lentes et les problèmes de performance. Les erreurs de Content Security Policy apparaissent dans la console et indiquent généralement du code inline ou eval() à refactoriser.

Approches alternatives de développement

Créer une extension avec React et frameworks modernes

React apporte une architecture composant robuste pour les interfaces complexes. Le défi principal est la configuration du build pour respecter Manifest V3 : éviter le JavaScript inline et produire des chemins relatifs.

Configuration Vite pour React :

// vite.config.ts
import react from '@vitejs/plugin-react'
import { resolve } from 'path'
import { defineConfig } from 'vite'

export default defineConfig({
  base: './',
  build: {
    assetsInlineLimit: 0,
    outDir: 'dist',
    rollupOptions: {
      output: {
        entryFileNames: '[name].js',
        chunkFileNames: '[name].js',
        assetFileNames: '[name].[ext]'
      },
      input: {
        popup: resolve(__dirname, 'popup.html'),
        options: resolve(__dirname, 'options.html')
      }
    }
  },
  plugins: [react()]
})

Le service worker ne peut pas utiliser React directement. Réservez React pour vos interfaces : popup, page d’options. Utilisez des hooks personnalisés pour encapsuler les interactions avec les APIs Chrome :

// useStorage.ts
import { useState, useEffect } from 'react';

export function useStorage<T>(key: string, defaultValue: T) {
  const [value, setValue] = useState<T>(defaultValue);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    chrome.storage.local.get([key], (result) => {
      if (result[key] !== undefined) {
        setValue(result[key]);
      }
      setLoading(false);
    });

    const listener = (changes: any, areaName: string) => {
      if (areaName === 'local' && changes[key]) {
        setValue(changes[key].newValue);
      }
    };

    chrome.storage.onChanged.addListener(listener);
    return () => chrome.storage.onChanged.removeListener(listener);
  }, [key]);

  const updateValue = (newValue: T) => {
    chrome.storage.local.set({ [key]: newValue });
    setValue(newValue);
  };

  return { value, updateValue, loading };
}

TypeScript avec @types/chrome apporte l’autocomplétion et la détection d’erreurs. Vue et Svelte fonctionnent selon les mêmes principes. Pour une simple popup, JavaScript pur reste plus performant – évaluez le rapport bénéfice/complexité.

Utiliser les outils no-code (limites et possibilités)

Les plateformes no-code pour extensions Chrome restent limitées. Elles permettent de créer des popups basiques avec des boutons et du contenu statique, mais les fonctionnalités complexes impliquant plusieurs APIs ou des logiques métier élaborées sont impossibles sans code.

Les templates GitHub offrent une meilleure alternative : recherchez « chrome-extension-boilerplate » ou « chrome-extension-template » pour trouver des bases préconfigurées avec React, Vue, TypeScript ou Vanilla JavaScript. Pour tout usage nécessitant de la logique conditionnelle ou des appels API, vous devrez écrire du code personnalisé.

Publier votre extension sur le Chrome Web Store

Empaqueter l’extension et créer un compte développeur

Créez un fichier ZIP avec le manifest.json à la racine (pas dans un sous-dossier). Excluez .git, .gitignore, .vscode, .idea, node_modules et tous les fichiers de développement.

Sous Linux/macOS : zip -r extension.zip . -x "*.git*" ".DS_Store"

Créez un compte développeur sur chrome.google.com/webstore/devconsole. Google demande des frais d’inscription uniques de 5 dollars pour publier autant d’extensions que vous le souhaitez.

Configurer la fiche de publication (description, captures, confidentialité)

Dans le tableau de bord, cliquez sur « Ajouter un nouvel élément » et téléversez votre ZIP. Complétez :

  • Description détaillée : expliquez ce que fait votre extension, quels problèmes elle résout, pourquoi l’installer, comment l’utiliser
  • Captures d’écran : minimum une, recommandé 4-5, dimensions 1280×800 ou 640×400 pixels. Montrez l’extension en action avec des annotations
  • Icône : 128×128 pixels, design reconnaissable
  • Politique de confidentialité : obligatoire si vous collectez des données. Doit expliquer quelles données, leur usage, le partage avec des tiers, et comment les consulter/supprimer

Choisissez la catégorie pertinente et ajoutez des tags descriptifs. Configurez la visibilité : Public (visible à tous), Non répertorié (lien direct uniquement), ou Privé (domaine Google Workspace).

Le délai de validation varie entre un et trois jours pour les extensions simples, jusqu’à une semaine pour les fonctionnalités complexes. Vous recevez un email en cas d’approbation ou de rejet avec les raisons détaillées.

Bonnes pratiques et optimisation

Sécurité et content security policies

La Content Security Policy de Manifest V3 interdit le code inline, eval() et le chargement de ressources externes non approuvées. Toutes vos ressources JavaScript et CSS doivent être externes. Utilisez addEventListener() plutôt que des attributs onclick.

Validez rigoureusement toutes les entrées utilisateur pour éviter les injections XSS. Demandez uniquement les permissions strictement nécessaires (principe du moindre privilège). Incluez les bibliothèques tierces localement plutôt que de les charger depuis des CDN.

Validez toujours les messages reçus entre composants – vérifiez l’origine et la structure. Pour les données sensibles, chiffrez-les avant stockage car l’API Storage stocke en clair.

Performances et gestion des mises à jour

Le service worker doit rester léger et s’exécuter uniquement quand nécessaire. Utilisez les alarmes Chrome pour les tâches périodiques au lieu de timers JavaScript. Injectez les content scripts uniquement sur les pages nécessaires via des patterns d’URL précis.

Pour la manipulation du DOM : utilisez querySelector, DocumentFragments, IntersectionObserver et RequestAnimationFrame. Regroupez les opérations de storage et respectez les limites (10 Mo local, 100 Ko sync). Implémentez un cache pour les requêtes réseau et utilisez debouncing/throttling pour les actions fréquentes.

Compressez les images, minimisez JavaScript et CSS en production. Utilisez le versionnement sémantique :

  • Version 2.0.0 : changements majeurs incompatibles
  • Version 1.1.0 : nouvelles fonctionnalités rétrocompatibles
  • Version 1.0.1 : corrections de bugs

Testez exhaustivement chaque mise à jour. Utilisez le déploiement progressif du Chrome Web Store pour publier d’abord auprès d’un petit pourcentage d’utilisateurs. Rédigez des notes de version claires mentionnant les nouvelles fonctionnalités, bugs corrigés et changements importants.

Surveillez les métriques du tableau de bord (utilisateurs actifs, taux de désinstallation, distribution des versions) et répondez aux avis utilisateurs, particulièrement aux négatifs.

<a href="https://www.thewalkingweb.fr/author/adebayova/" target="_self">Léo V.</a>

Léo V.

Passionné par l'univers de la data et des technologies numériques, je suis fier de contribuer au succès de Thewalkingweb. Mon rôle au sein de l'agence me permet d'explorer des solutions innovantes pour transformer les données en opportunités stratégiques. Toujours curieux et en quête de nouveaux défis, j'aime partager mes connaissances et échanger sur les sujets liés à l'analyse de données et au digital.
Créer un serveur VPN : le guide complet pour sécuriser votre connexion

Créer un serveur VPN : le guide complet pour sécuriser votre connexion

À l'heure où la confidentialité numérique devient une denrée rare, de plus en plus d'utilisateurs cherchent à reprendre le contrôle sur leurs données. Si les services de VPN commerciaux inondent le marché, monter sa propre infrastructure reste la méthode la plus...

Stratégie de pricing dynamique : guide complet pour optimiser vos tarifs

Stratégie de pricing dynamique : guide complet pour optimiser vos tarifs

La maîtrise de votre stratégie tarifaire peut faire toute la différence entre une rentabilité médiocre et des marges exceptionnelles. Le pricing dynamique révolutionne la façon dont les tarifs s'ajustent en temps réel, vous permettant de capter chaque opportunité de...

0 commentaires

Soumettre un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *