Comment j’ai créé un email scraper Chrome pour Google Maps (et ce que vous pouvez en faire)

par | 20 Avr 2026 | Non classé

J'ai construit une extension Chrome pour scraper des emails depuis Google Maps et le web, sans API payante. Voici l'histoire, l'architecture technique, le code de base et les leçons apprises.

Scraper des emails depuis Google Maps avec une simple extension Chrome. Sans abonnement, sans API payante, sans passer par des outils SaaS à 100€/mois. C’est exactement ce que j’ai construit, version après version, pour mes propres besoins de prospection — notamment pour organiser les événements Moovers à Toulouse. Dans cet article, je vous explique tout : pourquoi j’ai créé cet outil, comment il fonctionne techniquement, les problèmes qu’on a rencontrés, les solutions qu’on a trouvées, et je partage le code de base pour que vous puissiez faire de même.

Pourquoi j’ai créé cet email scraper Chrome

Tout a commencé avec un besoin très concret : je voulais inviter des entrepreneurs toulousains à mes afterworks mensuels Moovers. Le problème, c’est que les outils de prospection existants sont soit très chers (Hunter, Apollo, Kaspr à partir de 50-100€/mois), soit peu adaptés à la prospection locale par type de profession.

Google Maps est une mine d’or inexploitée pour ça. Tapez « plombier Toulouse » ou « coach sportif Lyon » et vous avez des centaines de fiches professionnelles avec des noms, des adresses, des téléphones — et parfois des emails. Le tout, totalement public. Il suffisait de trouver un moyen d’extraire tout ça automatiquement.

La deuxième idée est venue naturellement : et si on ne scrape pas que Google Maps, mais aussi les résultats de recherche web ? Quand quelqu’un cherche « plombier Toulouse » sur Google, les dix premières pages donnent accès à des centaines de sites de professionnels établis — des gens qui ont déjà investi dans leur présence digitale, donc des profils beaucoup plus qualifiés que la moyenne.

C’est comme ça qu’est né le projet : un seul outil, deux modes de scraping complémentaires, exportation automatique vers Google Drive, et intégration directe avec Brevo pour envoyer des campagnes email sans friction.

Comment fonctionne une extension Chrome — les bases techniques

Avant d’entrer dans le détail du code, il faut comprendre ce qu’est réellement une extension Chrome sous le capot. C’est un programme JavaScript qui s’exécute directement dans votre navigateur, avec accès aux pages que vous visitez. Elle se compose de plusieurs fichiers clés.

Le manifest.json — la carte d’identité de l’extension

C’est le fichier de configuration central. Il déclare les permissions dont l’extension a besoin (accès à l’onglet actif, stockage local, identité Google pour OAuth), les pages sur lesquelles les scripts s’injectent, et les informations générales comme le nom et la version. Sans ce fichier correctement configuré, rien ne fonctionne.

Exemple de manifest.json minimal :

{
  "manifest_version": 3,
  "name": "Email Scraper Maps",
  "version": "1.0",
  "permissions": ["activeTab", "scripting", "storage", "identity"],
  "host_permissions": ["https://www.google.com/*", "https://www.googleapis.com/*"],
  "action": { "default_popup": "popup.html" },
  "background": { "service_worker": "background.js" }
}

Le content script — celui qui lit les pages

Le content script est injecté dans les pages que vous visitez. Pour Google Maps, il parcourt le DOM de la page de résultats, extrait les noms d’établissements, clique sur chaque fiche pour en récupérer les détails (email, téléphone, site web), et renvoie ces données au script de fond.

Le background script — le cerveau de l’extension

Le background script (service worker en Manifest V3) coordonne tout. C’est lui qui reçoit les données du content script, les déduplique, gère l’upload vers Google Drive via l’API OAuth, et communique avec le popup pour afficher la progression.

Le popup — l’interface utilisateur

Le popup, c’est la petite fenêtre qui s’ouvre quand vous cliquez sur l’icône de l’extension. HTML + CSS + JavaScript pur. C’est là que vous saisissez votre mot-clé, choisissez le mode de scraping, et suivez la progression en temps réel.

Architecture de l’extension : les deux modes de scraping

L’une des décisions les plus importantes a été de construire deux modes distincts dans le même outil, parce qu’ils ne ciblent pas les mêmes profils de contacts.

Mode Google Maps — les professionnels locaux

Dans ce mode, l’extension s’appuie sur la page Google Maps déjà ouverte dans votre navigateur. Le content script injecté dans la page Maps parcourt les fiches visibles dans la colonne de gauche, clique automatiquement sur chacune d’elles, attend que les détails se chargent, puis extrait toutes les informations disponibles : nom de l’établissement, adresse, téléphone, URL du site web, et surtout l’email quand il est présent dans la fiche.

Le point délicat techniquement : Google Maps charge les fiches en lazy loading. L’extension doit donc gérer des délais d’attente intelligents, détecter quand une fiche est chargée, et simuler un comportement humain (pauses aléatoires entre chaque action) pour éviter d’être bloquée.

💡 Astuce anti-détection : On a ajouté des pauses aléatoires entre chaque fiche scrappée — entre 1 et 3 secondes, avec une variation supplémentaire toutes les 10 fiches. Ce comportement imite la navigation humaine et évite les blocages côté Google.

Mode Web Search — les professionnels établis

Ce mode fonctionne différemment : l’extension interroge DuckDuckGo (gratuit, sans limite d’API) avec le mot-clé que vous avez saisi, récupère les URLs des 10 premières pages de résultats, puis visite chaque site en arrière-plan pour y chercher des adresses email.

La détection d’emails dans une page web est plus complexe qu’il n’y paraît. Les emails peuvent être en clair dans le texte, cachés dans des liens mailto:, masqués par des techniques anti-spam (exemple : « contact [at] domaine [point] com »), ou même chargés dynamiquement via JavaScript. L’extension gère les cas les plus courants avec des expressions régulières robustes.

Ce mode est particulièrement efficace pour cibler des professionnels qui ont déjà un site web donc une présence digitale établie — un signal de qualification précieux.

Le défi de l’intégration Google Drive

C’est ici que les choses se sont vraiment compliquées. L’objectif était simple : à la fin de chaque scraping, l’extension exporte automatiquement un fichier CSV dans un dossier spécifique de Google Drive, sans que l’utilisateur ait à cliquer sur « Télécharger » et à déplacer le fichier manuellement.

En pratique, ça implique de gérer OAuth 2.0 depuis une extension Chrome — et c’est un sujet qui mérite un article entier à lui seul.

L’authentification OAuth depuis une extension

Une extension Chrome peut demander une authentification Google via l’API chrome.identity. Le flux est le suivant : l’utilisateur clique sur « Connecter Google Drive », Chrome affiche une fenêtre d’autorisation standard, l’utilisateur accepte, et l’extension reçoit un token d’accès valide pendant une heure.

Pour que ça fonctionne, il faut déclarer le client OAuth dans la Google Cloud Console, configurer les scopes nécessaires (drive.file pour n’écrire que dans les fichiers créés par l’extension, sans accès à tout le Drive), et référencer le client ID dans le manifest.json.

Le problème de la conversion automatique de Google

Premier problème rencontré : quand on uploadait le CSV via l’API Drive, Google le convertissait automatiquement en Google Sheets. Pratique dans certains cas, catastrophique ici — parce que les scripts Apps Script qui lisaient ces fichiers côté Moovers attendaient de vrais CSV, pas des Sheets.

La solution : ajouter le paramètre convert=false dans la requête d’upload, et forcer le MIME type à text/csv dans les métadonnées du fichier. Une ligne de code, mais qu’il fallait trouver.

Extrait du code d’upload Drive :

const metadata = {
  name: 'scraping_' + keyword + '_' + date + '.csv',
  parents: ['VOTRE_FOLDER_ID_DRIVE'],
  mimeType: 'text/csv'
};

const response = await fetch(
  'https://www.googleapis.com/upload/drive/v3/files'
  + '?uploadType=multipart&convert=false',
  {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + token,
      'Content-Type': 'multipart/related; boundary=boundary'
    },
    body: buildMultipartBody(metadata, csvContent)
  }
);

L’intégration Brevo — de l’email scraping à la campagne en un clic

Une fois les emails collectés, encore faut-il pouvoir les utiliser. J’ai intégré Brevo (ex-Sendinblue) directement dans l’extension pour permettre l’import immédiat des contacts dans une liste, sans passer par l’interface web de Brevo.

Le flux est le suivant :

1. Scraping terminé → l’extension affiche le nombre d’emails trouvés et le taux de succès (typiquement 50-70% sur Maps, 30-50% en mode Web).
2. Clic sur « Exporter vers Brevo » → une modal s’ouvre pour nommer la liste (ex: « Plombiers Toulouse – Avril 2026 »).
3. Appel API Brevo → l’extension crée automatiquement la liste via POST /v3/contacts/lists, puis importe tous les contacts via POST /v3/contacts/import.
4. Confirmation → une notification verte confirme le nombre de contacts importés. La liste est prête dans Brevo pour une campagne.

Pour aller encore plus loin, j’ai ajouté un export automatique vers le dossier Google Drive csv_import_moovers à chaque scraping. Un Google Apps Script côté Drive surveille ce dossier et peut déclencher des actions supplémentaires automatiquement.

Le mode Batch — scraper 8 000 contacts en automatique

La fonctionnalité la plus puissante, construite dans les dernières versions, c’est le mode Batch. L’idée : au lieu de lancer des recherches une par une, vous renseignez une liste de villes et une liste de professions, et l’extension enchaîne toutes les combinaisons automatiquement, en tâche de fond.

Exemple concret : vous voulez toucher des artisans (plombiers, électriciens, maçons) dans 5 villes (Toulouse, Bordeaux, Lyon, Marseille, Nantes). Avec le mode Batch, vous entrez ces informations une fois, cliquez sur « Lancer », et l’extension génère et exécute les 15 recherches automatiquement — avec des pauses aléatoires entre chaque pour simuler une navigation humaine.

C’est exactement ce qu’on a utilisé pour scraper plus de 8 000 contacts à destination des campagnes Moovers sur Brevo. Chaque scraping prend environ 5 minutes par combinaison ville/profession — une bonne centaine de contacts en moyenne. Lancé un soir avant de dormir, vous vous réveillez avec une liste qualifiée prête à l’emploi.

🚀 Performance observée en conditions réelles : sur une recherche « plombier Toulouse » en mode Maps, on obtient en moyenne 60 à 70% de taux de récupération d’emails sur les fiches qui en ont un. Sur les 123 fiches visitées lors d’un test, 74 emails ont été extraits — soit un taux de 60%.

Les problèmes rencontrés et leurs solutions

Je ne vais pas vous faire croire que tout s’est construit sans accrocs. Voici les principaux problèmes rencontrés et comment ils ont été résolus — parce que c’est souvent plus utile que les success stories.

Problème 1 : les onglets qui ne s’ouvrent pas

Dans les premières versions, l’extension essayait d’ouvrir un nouvel onglet Google Maps au moment du clic sur « GO ». Chrome bloque ce comportement depuis les popups d’extension pour des raisons de sécurité. La solution : l’extension doit d’abord s’assurer que Google Maps est déjà ouvert dans un onglet actif, puis injecter le content script dans cet onglet existant.

Problème 2 : les fichiers Drive convertis en Google Sheets

Évoqué plus haut — résolu avec convert=false et le bon MIME type. Ce bug a pris plusieurs itérations à identifier car il ne se manifestait que dans certains cas selon les paramètres de compte Google.

Problème 3 : les tokens OAuth qui expirent

Le token Google Drive est valide une heure. Si le batch de scraping dure plus longtemps, les uploads échouent silencieusement. La solution : vérifier la validité du token avant chaque upload et le rafraîchir automatiquement via chrome.identity.getAuthToken({ interactive: false }) si nécessaire.

Problème 4 : la déduplication des emails

Quand on enchaîne plusieurs scrapings sur des zones géographiques proches, certains contacts apparaissent dans plusieurs listes. J’ai développé un Google Apps Script séparé qui lit tous les CSV du dossier Drive, croise les emails, et génère une liste déduplication propre — sans doublon, triée par qualité de la fiche source.

Problème 5 : la mise à jour de l’extension sans la réinstaller

Chaque fois qu’on sortait une nouvelle version, le process naïf était : supprimer l’ancienne extension, dézipper la nouvelle, recharger. Trop lent et trop risqué (perte des paramètres stockés). Le bon process : garder toujours le même dossier sur le bureau, remplacer les fichiers modifiés, puis cliquer sur le bouton « Recharger » dans chrome://extensions. Les paramètres sont conservés dans le storage local de l’extension.

Le code de base pour démarrer

Voici une version simplifiée mais fonctionnelle du cœur de l’extension — suffisamment complète pour comprendre la mécanique et l’adapter à vos besoins.

manifest.json

{
  "manifest_version": 3,
  "name": "Email Scraper Maps",
  "version": "1.0",
  "description": "Scrape les emails depuis Google Maps et le web",
  "permissions": ["activeTab", "scripting", "storage", "identity", "tabs"],
  "host_permissions": [
    "https://www.google.com/*",
    "https://maps.google.com/*",
    "https://www.googleapis.com/*",
    "<all_urls>"
  ],
  "oauth2": {
    "client_id": "VOTRE_CLIENT_ID.apps.googleusercontent.com",
    "scopes": ["https://www.googleapis.com/auth/drive.file"]
  },
  "action": { "default_popup": "popup.html" },
  "background": { "service_worker": "background.js" }
}

content.js — extraction des emails depuis Google Maps

// Pause aléatoire anti-détection
function sleep(min, max) {
  const ms = Math.floor(Math.random() * (max - min + 1)) + min;
  return new Promise(r => setTimeout(r, ms));
}

// Extraction email depuis le texte d'une fiche
function extractEmail(text) {
  const match = text.match(
    /[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}/
  );
  return match ? match[0].toLowerCase() : null;
}

// Scraping d'une fiche Maps ouverte
async function scrapeFiche() {
  await sleep(800, 1800); // Pause humaine
  const details = document.querySelector('[data-attrid="kc:/local:place"]');
  const emailEl = document.querySelector('a[href^="mailto:"]');
  const nameEl = document.querySelector('h1.DUwDvf');

  return {
    name: nameEl ? nameEl.textContent.trim() : '',
    email: emailEl ? emailEl.href.replace('mailto:', '') : null,
    source: 'Google Maps',
    url: window.location.href
  };
}

background.js — upload vers Google Drive

const DRIVE_FOLDER_ID = 'VOTRE_FOLDER_ID_ICI';

async function uploadCsvToDrive(csvContent, filename) {
  // 1. Récupérer le token OAuth
  const token = await new Promise((resolve, reject) => {
    chrome.identity.getAuthToken({ interactive: true }, t => {
      if (chrome.runtime.lastError) reject(chrome.runtime.lastError);
      else resolve(t);
    });
  });

  // 2. Construire le body multipart
  const boundary = 'email_scraper_boundary';
  const metadata = JSON.stringify({
    name: filename,
    parents: [DRIVE_FOLDER_ID],
    mimeType: 'text/csv'
  });

  const body = [
    '--' + boundary,
    'Content-Type: application/json',
    '',
    metadata,
    '--' + boundary,
    'Content-Type: text/csv',
    '',
    csvContent,
    '--' + boundary + '--'
  ].join('
');

  // 3. Upload avec convert=false
  const response = await fetch(
    'https://www.googleapis.com/upload/drive/v3/files'
    + '?uploadType=multipart&convert=false',
    {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer ' + token,
        'Content-Type': 'multipart/related; boundary=' + boundary
      },
      body: body
    }
  );

  if (!response.ok) {
    const err = await response.json();
    throw new Error(err.error?.message || 'Upload Drive échoué');
  }

  return await response.json();
}

Ce que vous pouvez faire avec cet outil

Au-delà de mon cas d’usage Moovers, les applications sont nombreuses dès lors qu’on a besoin de constituer une base de contacts qualifiés localement.

📧 Prospection commerciale locale

Cibler des artisans, commerçants, professions libérales dans une ville précise pour proposer vos services (communication, SEO, comptabilité, assurance…).

🎪 Organisation d’événements

Inviter des professionnels d’une catégorie spécifique à des conférences, afterworks, salons ou ateliers. C’est l’usage principal pour Moovers.

🔍 Études de marché terrain

Constituer un panel de professionnels à contacter pour un sondage, une étude qualitative ou une validation de concept.

🤝 Partenariats et networking

Identifier des partenaires potentiels dans votre secteur pour des collaborations, prescriptions ou co-marketing.

Limites légales et bonnes pratiques RGPD

Je ne peux pas conclure cet article sans aborder la question légale. Collecter des emails de professionnels est une zone grise en France et en Europe. Voici ce qu’il faut savoir.

En B2B, la prospection par email est autorisée sans consentement préalable à condition que l’email soit en rapport direct avec la profession du destinataire, que chaque email comporte une mention de désinscription claire, et que vous respectiez les demandes de suppression dans les plus brefs délais.

Les emails professionnels visibles publiquement sur Google Maps (contact@plombier-toulouse.fr) entrent généralement dans ce cadre. En revanche, les emails personnels (jean.dupont@gmail.com récupérés sur un profil Maps) sont à éviter absolument — ils relèvent de la vie privée et leur utilisation à des fins commerciales sans consentement est illégale.

Mon conseil pratique : dans vos campagnes email, soyez ultra-clair sur qui vous êtes, pourquoi vous contactez cette personne, et facilitez-lui au maximum la désinscription. Une prospection transparente et respectueuse convertit mieux qu’une approche agressive — et elle vous évite des plaintes CNIL.

Pour aller plus loin

L’extension que je vous ai décrite ici est celle que j’utilise en conditions réelles pour Moovers. Elle est arrivée à sa version 2.26 après des dizaines d’itérations, de bugs corrigés, de fonctionnalités ajoutées. Elle n’est pas parfaite — aucun outil ne l’est — mais elle fait ce pour quoi elle a été construite avec une fiabilité suffisante pour des usages professionnels.

Si vous souhaitez construire votre propre version ou adapter ce code à votre cas d’usage, le code de base présenté dans cet article est un bon point de départ. Les principaux défis techniques à anticiper : la gestion du lazy loading de Maps, l’authentification OAuth Drive, la robustesse de la détection d’emails dans des pages HTML hétérogènes, et le comportement anti-détection.

Si vous voulez qu’on travaille ensemble sur un outil similaire ou une stratégie de prospection digitale pour votre activité, je suis disponible pour en discuter.

Un projet de scraping ou de prospection digitale ?

Discutons de votre cas d’usage — je peux vous accompagner sur la stratégie ou le développement.

Planifier un échange

+50 clients accompagnés

Prêt à structurer votre projet digital ?

Je vous propose un échange stratégique gratuit de 30 minutes pour faire le point sur votre projet : vision, objectifs, contraintes techniques, budget disponible.

Vous repartirez avec une vision claire de ce qu’il faut faire en priorité — que vous travailliez avec moi ou non.

Allez, on se retrouve de l’autre côté pour un Café Visio  ☕️

Envie de lire d’autres articles ?

Je vous partage sur mon blog mes tests, leçons et apprentissages, ainsi que des conseils pertinents pour votre activité.