Selenium est un outil d'automatisation de navigateur, créé à l'origine pour tester les applications web. Mais parce qu'il pilote un vrai navigateur, on l'utilise depuis longtemps et activement pour le parsing de sites, en particulier ceux qui servent leur contenu via JavaScript et ne s'ouvrent pas à une simple requête HTTP.
Dans cet article, nous verrons comment Selenium est construit, comment travailler avec dans différents langages, quelles sont ses forces et ses faiblesses, et pourquoi il est si facilement détecté par les systèmes de protection anti-bots.
Si vous êtes encore en train de choisir votre approche du parsing, commencez par nos panoramas « Dans quel langage écrire son parseur ? Panorama des principales solutions » et « Les bibliothèques pour le parsing de sites » — nous y comparons les outils à haut niveau. Cet article est une analyse approfondie de l'un d'eux.
Qu'est-ce que Selenium et comment il fonctionne
Selenium pilote le navigateur non pas « de l'intérieur », mais via un driver séparé, selon le protocole WebDriver (standard W3C). Le schéma est toujours le même :
Votre script ──▶ Binding Selenium ──▶ Driver (chromedriver / geckodriver / …) ──▶ Navigateur
- Le binding — la bibliothèque dans votre langage (Python, Java, etc.) qui traduit des appels comme
driver.get(url)en commandes WebDriver. - Le driver — l'exécutable intermédiaire propre à chaque navigateur :
chromedriverpour Chrome,geckodriverpour Firefox,msedgedriverpour Edge. - Le navigateur — un vrai Chrome/Firefox/Edge, qui rend la page exactement comme chez un utilisateur ordinaire.
Autrefois, il fallait télécharger les drivers et les placer dans le PATH à la main, en veillant à la compatibilité des versions du driver et du navigateur. Depuis la version 4.6, Selenium intègre Selenium Manager — il trouve lui-même le navigateur, choisit et télécharge le driver qu'il faut. Au moment de la rédaction, la version courante est Selenium 4.45 (juin 2026). En pratique, cela signifie qu'un script minimal fonctionnel tient aujourd'hui en trois lignes, sans manipulation manuelle des drivers.
La différence essentielle avec les clients HTTP
Les bibliothèques ordinaires (requests + BeautifulSoup, Scrapy, etc.) se contentent de télécharger le HTML que le serveur a renvoyé à la requête. Si le contenu est chargé par JavaScript dans le navigateur, il ne sera pas dans ce HTML.
Selenium, lui, lance un navigateur complet : le JS s'exécute, les requêtes XHR/fetch aboutissent, le DOM final se construit. Le parseur voit exactement ce que voit l'humain. C'est la raison principale de choisir Selenium — mais cela se paie en ressources et en vitesse (voir plus bas).
Selenium dans différents langages
L'un des grands atouts de Selenium, ce sont ses bindings officiels pour plusieurs langages d'emblée. L'API est presque identique partout, seule la syntaxe change. C'est commode : l'équipe peut écrire le parseur dans le langage même du reste du projet.
Sont officiellement pris en charge : Python, Java, JavaScript (Node.js), C# (.NET) et Ruby. Pour PHP, Go, Rust et d'autres langages, il existe des bindings ou des wrappers communautaires, mais maintenus par la communauté, non par l'équipe principale de Selenium.
Python
Le langage le plus populaire pour le parsing et pour Selenium en particulier : barrière d'entrée basse, écosystème immense (pandas, lxml, BeautifulSoup pour le post-traitement) et foule d'exemples prêts.
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://example.com")
title = driver.find_element(By.TAG_NAME, "h1").text
print(title)
driver.quit()
Avantages : la plus grande communauté, des surcouches anti-détection prêtes (undetected-chromedriver, selenium-stealth, SeleniumBase), un développement rapide.
Inconvénients : le GIL limite le vrai parallélisme — pour monter en charge, on lance généralement plusieurs processus ou on utilise Selenium Grid.
Java
Java est le langage « natif » de Selenium (le projet s'est historiquement développé autour) et le standard des grandes équipes QA en entreprise.
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Scraper {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.get("https://example.com");
String title = driver.findElement(By.tagName("h1")).getText();
System.out.println(title);
driver.quit();
}
}
Avantages : vrai multithreading, hautes performances, outils de build mûrs (Maven/Gradle), commode pour les grands systèmes à longue durée de vie. Inconvénients : syntaxe verbeuse, plus long à écrire et à prototyper qu'en Python.
JavaScript (Node.js)
Choix logique si le backend tourne déjà sous Node. Le modèle asynchrone (async/await) épouse bien l'attente du chargement des éléments.
const { Builder, By } = require("selenium-webdriver");
(async () => {
const driver = await new Builder().forBrowser("chrome").build();
await driver.get("https://example.com");
const title = await driver.findElement(By.css("h1")).getText();
console.log(title);
await driver.quit();
})();
Avantages : un seul langage pour le front et le back, asynchronisme natif. Inconvénients : dans la niche de l'automatisation de navigateur sous Node, Selenium a des concurrents plus forts — Puppeteer et Playwright, que beaucoup préfèrent justement dans l'écosystème JS.
C# (.NET)
Populaire en environnement d'entreprise sur la stack Microsoft.
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://example.com");
var title = driver.FindElement(By.TagName("h1")).Text;
Console.WriteLine(title);
driver.Quit();
Avantages : typage strict, bonnes performances, excellente intégration à l'écosystème .NET. Inconvénients : moins d'exemples orientés parsing et moins de bibliothèques anti-détection tierces qu'en Python.
Ruby
require "selenium-webdriver"
driver = Selenium::WebDriver.for :chrome
driver.get "https://example.com"
title = driver.find_element(tag_name: "h1").text
puts title
driver.quit
Avantages : syntaxe concise et expressive. Inconvénients : communauté relativement réduite pour les tâches de parsing, moins de solutions prêtes.
PHP, Go, Rust et autres
Pour PHP il y a php-webdriver/php-webdriver, pour Go et Rust — des wrappers communautaires. Ils fonctionnent, mais : maintenus par la communauté, en retard sur les fonctionnalités récentes des bindings officiels et moins bien documentés dans le contexte précis du parsing. Si le langage de votre projet est l'un d'eux, mieux vaut souvent envisager une alternative (par exemple un navigateur headless via CDP, ou un parseur HTTP) plutôt que de traîner Selenium.
Les avantages de Selenium
- Fonctionne avec les sites dynamiques. Il exécute le JavaScript et voit le DOM final — ce que les clients HTTP ne peuvent en principe pas obtenir sans émuler un navigateur.
- Imitation d'un utilisateur réel. Clics, saisie de texte, défilement, survol, changement d'onglets, gestion des cookies — tout comme un humain.
- Multi-langage. La même approche en Python, Java, JS, C#, Ruby — on peut rester dans la stack du projet.
- Multi-navigateur. Chrome, Firefox, Edge, Safari via une API unique.
- Maturité et documentation. Le projet a plus de 15 ans, une communauté gigantesque ; la réponse à presque n'importe quelle question est déjà sur Stack Overflow.
- Contrôle total du navigateur. Captures d'écran, exécution de JS arbitraire, accès au Chrome DevTools Protocol, interception réseau.
Les inconvénients de Selenium
- Lent et lourd. Lancer un navigateur complet à chaque session dévore beaucoup de CPU et de RAM. À grande échelle, cela coûte des dizaines, voire des centaines de fois plus en ressources qu'une requête HTTP.
- Difficile à mettre à l'échelle « tel quel ». Pour parser des milliers de pages en parallèle, il faut Selenium Grid, un pool de conteneurs ou du cloud — une infrastructure à part.
- Fragilité. Le parseur dépend de la structure de la page et des délais de chargement. Le balisage change ou les temps de réponse dérivent — il faut des attentes explicites (
WebDriverWait), sinon tout casse. - Plus complexe à exploiter. Les versions du navigateur et du driver doivent concorder (Selenium Manager en soulage une partie, pas toute), et le navigateur en Docker demande un réglage soigneux.
- Et surtout — il se détecte facilement. C'est l'objet de la section suivante.
Pourquoi Selenium se repère facilement
C'est sans doute le problème pratique le plus important. Les systèmes anti-bots modernes (Cloudflare, DataDome, Imperva/Incapsula, PerimeterX, etc.) savent reconnaître un navigateur automatisé à une multitude de signes. Et « tel quel », Selenium laisse des dizaines de traces de ce genre.
Les principales traces qui trahissent Selenium
1. Le flag navigator.webdriver. Le marqueur le plus connu. Lancé via WebDriver, le navigateur met navigator.webdriver = true. Chez un utilisateur ordinaire, cette propriété vaut false ou undefined. Une seule ligne de JavaScript côté site suffit à marquer la visite comme robotisée.
2. Les variables $cdc_ et $wdc_. ChromeDriver injecte dans le document des variables de service (par exemple commençant par $cdc_). Le détecteur cherche simplement leur présence dans l'objet document/window — et les trouve.
3. Les traces du Chrome DevTools Protocol (CDP). Selenium dialogue avec Chrome via CDP. L'activation du domaine Runtime (Runtime.Enable) se détecte à part — c'est la « détection de deuxième génération », et la plupart des bibliothèques anti-détection simples ne la couvrent pas.
4. Les incohérences dans navigator. Si l'on remplace le User-Agent par un iPhone mais que navigator.platform reste Win32, que le nombre de cœurs (hardwareConcurrency) est atypique pour l'appareil déclaré, et que la liste de plugins/langues paraît « stérile » — l'antifraude repère l'incohérence logique instantanément.
5. Les signatures des commandes WebDriver elles-mêmes. Les appels execute_script/execute_async_script laissent des traces reconnaissables dans la pile d'appels JS, à partir desquelles on peut aussi reconnaître l'automatisation.
6. Les signes comportementaux et réseau. Une vitesse parfaitement régulière, l'absence de mouvements de souris, un historique et des cookies vides, ainsi que l'empreinte TLS (JA3/JA4) et l'ordre des en-têtes différant d'un vrai navigateur. C'est la « troisième génération » de détection.
Les « générations » de détection — pour bien voir contre quoi vous luttez
Il est utile de garder en tête cette gradation :
- Génération 1 — vérifications au niveau de l'API.
navigator.webdriver, variables$cdc_et similaires. Se couvre avec les bibliothèques anti-détection. - Génération 2 — détection au niveau du protocole CDP. Par exemple, le suivi de
Runtime.Enable. La plupart des patchs populaires ne soignent plus cela. - Génération 3 — empreinte TLS, analyse comportementale, modèles de ML propres à un client donné. Ne se couvre en principe pas par des patchs côté client — il faut ici des proxys, de la rotation, une imitation du comportement et des empreintes de qualité.
Les outils pour « cacher » Selenium
On ne peut pas supprimer entièrement la détection, mais on peut réduire la probabilité de blocage. Les plus utilisés :
undetected-chromedriver(Python) — patche le binaire du driver (retire la chaînecdc_), masquenavigator.webdriver, ajuste les options. Longtemps considéré comme la « référence », il couvre surtout les problèmes de première génération.selenium-stealth(Python) — un jeu de patchs JS : remplacenavigator.webdriver,plugins,languages, le vendeur WebGL, etc. Moins bien maintenu qu'UC.SeleniumBaseUC Mode — ajoute la technique du disconnect/reconnect : sur les actions sensibles, il déconnecte temporairement ChromeDriver du navigateur, contournant une partie de la détection CDP.nodriver— le successeur d'undetected-chromedriver, du même auteur. Il fonctionne directement via CDP, sans chromedriver ni couche WebDriver, ce qui élimine une série de marqueurs. Ce n'est plus tout à fait « Selenium », mais une approche à part.- Techniques manuelles — le flag
--disable-blink-features=AutomationControlled, la désactivation d'enable-automation, le remplacement denavigator.webdriverviaPage.addScriptToEvaluateOnNewDocument, l'accord du User-Agent avec les propriétés réelles de navigator.
Pour vérifier à quel point votre navigateur est bien « caché », utilisez des bancs de test publics comme bot.sannysoft.com ou des services d'empreinte.
Réserve importante
Toutes ces bibliothèques ne sont pas une baguette magique. Les entreprises anti-bots étudient les contournements open source : quels patchs précis applique undetected-chromedriver, cela se voit directement dans son dépôt. Ce qui contourne la protection aujourd'hui peut cesser de marcher après la prochaine mise à jour — sans préavis. C'est pourquoi, pour du parsing sérieux, on ajoute presque toujours à Selenium des proxys de qualité avec rotation, des délais raisonnables, des profils « chauffés » avec cookies et une imitation du comportement humain. Et malgré tout, face à la protection de troisième génération, Selenium nu se révèle souvent insuffisant.
Quand prendre Selenium, et quand non
Selenium se justifie quand :
- le site est entièrement bâti sur JavaScript et le contenu est inaccessible sans navigateur ;
- il faut imiter un scénario utilisateur complexe (connexion, formulaires multi-étapes, défilement infini) ;
- les volumes sont modérés, pas des millions de pages par heure ;
- vous avez déjà une stack Java/C#/Python et souhaitez y rester.
Mieux vaut chercher une alternative quand :
- les données sont accessibles par HTTP/API ordinaire — alors
requests/Scrapy/httpxseront bien plus rapides et moins coûteux ; - il faut le maximum d'échelle et de vitesse ;
- l'objectif est de contourner une protection anti-bots sérieuse : ici, Playwright ou Puppeteer l'emportent souvent (plus modernes, avec un meilleur contrôle du navigateur et des plugins stealth commodes), et parfois
nodriverou des API spécialisées.
En résumé
Selenium est un outil puissant et universel : il fonctionne avec les sites dynamiques, prend en charge de nombreux langages et navigateurs, possède une communauté immense et une excellente documentation. Cela en fait un bon choix pour parser des pages JS complexes et des scénarios imitant un utilisateur réel.
Mais il a deux contreparties sérieuses : sa gourmandise en ressources (donc des problèmes de vitesse et de mise à l'échelle) et sa détectabilité facile. « Tel quel », Selenium laisse des dizaines de traces d'automatisation, et même si on peut les masquer en partie, cela reste souvent insuffisant face à la protection anti-bots moderne.
La conclusion pratique est simple : si les données peuvent être obtenues par une requête HTTP — prenez un parseur HTTP. Si le navigateur est incontournable — Selenium conviendra très bien, mais prévoyez dans le projet des proxys, de la rotation, un comportement humain et de l'anti-détection ; et pour les cibles les plus protégées, comparez-le honnêtement à Playwright, Puppeteer et aux solutions plus récentes.