Selenium es una herramienta de automatización de navegadores creada en origen para probar aplicaciones web. Pero, gracias a que controla un navegador real, se usa desde hace tiempo y de forma intensiva para el scraping de sitios, sobre todo aquellos que sirven el contenido a través de JavaScript y no se abren con una simple petición HTTP.
En este artículo veremos cómo funciona Selenium por dentro, cómo trabajar con él en distintos lenguajes, cuáles son sus puntos fuertes y débiles y por qué los sistemas de protección anti-bot lo detectan con facilidad.
Si todavía está eligiendo un enfoque de scraping, empiece por nuestros panoramas «¿En qué lenguaje escribir un scraper? Panorama de soluciones» y «Bibliotecas para web scraping» — allí comparamos las herramientas a alto nivel. Este artículo es un análisis en profundidad de una de ellas.
Qué es Selenium y cómo funciona
Selenium no controla el navegador «desde dentro», sino a través de un driver aparte mediante el protocolo WebDriver (un estándar del W3C). El esquema es siempre el mismo:
Su script ──▶ Binding de Selenium ──▶ Driver (chromedriver / geckodriver / …) ──▶ Navegador- El binding es la biblioteca en su lenguaje (Python, Java, etc.) que traduce llamadas como
driver.get(url)a comandos de WebDriver. - El driver es un ejecutable intermediario para un navegador concreto:
chromedriverpara Chrome,geckodriverpara Firefox,msedgedriverpara Edge. - El navegador es un Chrome/Firefox/Edge real que renderiza la página igual que para un usuario normal.
Antes había que descargar los drivers y colocarlos en el PATH a mano, vigilando la compatibilidad entre las versiones del driver y del navegador. Desde la versión 4.6, Selenium incorpora Selenium Manager — que localiza el navegador y elige y descarga el driver adecuado por sí mismo. En el momento de escribir esto, la versión actual es Selenium 4.45 (junio de 2026). En la práctica, esto significa que hoy el script mínimo funcional cabe literalmente en tres líneas, sin el trajín manual con los drivers.
La diferencia principal con los scrapers HTTP
Las bibliotecas habituales (requests + BeautifulSoup, Scrapy, etc.) se limitan a descargar el HTML que el servidor devolvió ante la petición. Si el contenido se carga con JavaScript ya en el navegador, no estará en ese HTML.
Selenium, en cambio, arranca un navegador completo: se ejecuta el JS, se resuelven las peticiones XHR/fetch y se construye el DOM final. El scraper ve exactamente lo mismo que una persona. Esa es la razón principal para elegir Selenium — pero se paga en recursos y velocidad (más sobre esto abajo).
Selenium en distintos lenguajes
Una de las grandes ventajas de Selenium son sus bindings oficiales para varios lenguajes a la vez. La API es casi idéntica en todos; solo cambia la sintaxis. Esto resulta cómodo: el equipo puede escribir el scraper en el mismo lenguaje que el resto del proyecto.
Oficialmente se admiten Python, Java, JavaScript (Node.js), C# (.NET) y Ruby. Para PHP, Go, Rust y otros lenguajes hay bindings o envoltorios comunitarios, pero los mantiene la comunidad y no el equipo principal de Selenium.
Python
El lenguaje más popular para el scraping y para Selenium en particular: barrera de entrada baja, un ecosistema enorme (pandas, lxml, BeautifulSoup para el posprocesado) y multitud de ejemplos ya hechos.
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()Ventajas: la comunidad más grande, complementos anti-detección ya hechos (undetected-chromedriver, selenium-stealth, SeleniumBase) y desarrollo rápido. Inconvenientes: el GIL limita el paralelismo real — para escalar se suelen lanzar varios procesos o se usa Selenium Grid.
Java
Java es el lenguaje «nativo» de Selenium (el proyecto creció históricamente en torno a él) y un estándar en los grandes equipos corporativos de QA.
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();
}
}Ventajas: multithreading de verdad, alto rendimiento, herramientas de compilación maduras (Maven/Gradle) y comodidad para sistemas grandes y de larga vida. Inconvenientes: sintaxis verbosa; se tarda más en escribir y prototipar que en Python.
JavaScript (Node.js)
Una elección lógica si el backend ya está en Node. El modelo asíncrono (async/await) encaja bien con la espera de la carga de los elementos.
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();
})();Ventajas: un mismo lenguaje para el front y el back, y asincronía nativa. Inconvenientes: en el nicho de la automatización de navegadores sobre Node, Selenium tiene rivales más fuertes — Puppeteer y Playwright, que muchos prefieren precisamente en el ecosistema JS.
C# (.NET)
Popular en entornos empresariales con stack de 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();Ventajas: tipado estricto, buen rendimiento y una integración excelente con el ecosistema .NET. Inconvenientes: menos ejemplos orientados al scraping y menos bibliotecas anti-detección de terceros que 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.quitVentajas: sintaxis concisa y expresiva. Inconvenientes: una comunidad relativamente pequeña en tareas de scraping y menos soluciones ya hechas.
PHP, Go, Rust y otros
Para PHP existe php-webdriver/php-webdriver; para Go y Rust, envoltorios comunitarios. Funcionan, pero: los mantiene la comunidad, van por detrás de los bindings oficiales en novedades y están peor documentados en el contexto concreto del scraping. Si el lenguaje de su proyecto es uno de estos, a menudo compensa considerar una alternativa (por ejemplo, un navegador headless mediante CDP o un scraper HTTP) antes que arrastrar Selenium.
Ventajas de Selenium
- Funciona con sitios dinámicos. Ejecuta JavaScript y ve el DOM final — algo que los scrapers HTTP no pueden obtener sin emular un navegador.
- Imitación de un usuario real. Clics, escritura de texto, scroll, hover, cambio de pestañas, manejo de cookies — todo como una persona de carne y hueso.
- Multilenguaje. El mismo enfoque en Python, Java, JS, C# y Ruby — permite quedarse en el stack del proyecto.
- Multinavegador. Chrome, Firefox, Edge y Safari a través de una única API.
- Madurez y documentación. El proyecto tiene más de 15 años, una comunidad gigantesca y la respuesta a casi cualquier duda ya está en Stack Overflow.
- Control total del navegador. Capturas de pantalla, ejecución de JS arbitrario, acceso al Chrome DevTools Protocol e interceptación de red.
Inconvenientes de Selenium
- Lento y pesado. Arrancar un navegador completo en cada sesión consume mucha CPU y RAM. A gran escala, sale decenas — y a veces cientos — de veces más caro en recursos que una petición HTTP.
- Escala mal «por las bravas». Para procesar miles de páginas en paralelo hace falta Selenium Grid, un pool de contenedores o la nube — toda una infraestructura aparte.
- Fragilidad. El scraper depende de la estructura de la página y de los tiempos de carga. Si cambia el maquetado o se desajustan los retardos, hacen falta esperas explícitas (
WebDriverWait); de lo contrario, todo se rompe. - Más difícil de operar. Las versiones del navegador y del driver deben coincidir (Selenium Manager alivia parte del problema, pero no todo) y ejecutar el navegador en Docker exige una configuración cuidadosa.
- Y, sobre todo, se detecta con facilidad. A ello dedicamos la siguiente sección.
Por qué se detecta con facilidad
Es, quizá, el problema práctico más importante. Los sistemas anti-bot modernos (Cloudflare, DataDome, Imperva/Incapsula, PerimeterX y otros) saben reconocer un navegador automatizado por multitud de indicios. Y «de fábrica», Selenium deja decenas de esas huellas.
Las principales huellas que delatan a Selenium
1. El flag navigator.webdriver. El marcador más conocido. Al arrancar mediante WebDriver, el navegador fija navigator.webdriver = true. En un usuario normal esa propiedad es false o undefined. Basta una línea de JavaScript en el lado del sitio para marcar la visita como de bot.
2. Las variables $cdc_ y $wdc_. ChromeDriver inyecta en el documento variables internas (por ejemplo, las que empiezan por $cdc_). El detector simplemente busca su presencia en el objeto document/window — y las encuentra.
3. Rastros del Chrome DevTools Protocol (CDP). Selenium se comunica con Chrome mediante CDP. La activación del dominio Runtime (Runtime.Enable) se detecta por separado — es la llamada «detección de segunda generación», y la mayoría de las bibliotecas anti-detección sencillas no la tapan.
4. Incoherencias en navigator. Si se falsea el User-Agent para simular un iPhone pero navigator.platform sigue siendo Win32, el número de núcleos (hardwareConcurrency) es atípico para el dispositivo declarado y la lista de plugins e idiomas parece «estéril», el antifraude detecta la incoherencia lógica al instante.
5. Firmas de los propios comandos de WebDriver. Las llamadas execute_script/execute_async_script dejan rastros reconocibles en la pila de llamadas de JS, por los que también se puede identificar la automatización.
6. Indicios de comportamiento y de red. Una velocidad perfectamente uniforme, la ausencia de movimientos del ratón, un historial y unas cookies a cero, además de una huella TLS (JA3/JA4) y un orden de cabeceras distintos a los de un navegador real. Es la «tercera generación» de detección.
Las «generaciones» de detección: para saber a qué se enfrenta
Conviene tener presente esta gradación:
- Generación 1 — comprobaciones a nivel de API.
navigator.webdriver, las variables$cdc_y similares. Se tapan con bibliotecas anti-detección. - Generación 2 — detección a nivel del protocolo CDP. Por ejemplo, la vigilancia de
Runtime.Enable. La mayoría de los parches populares ya no lo solucionan. - Generación 3 — fingerprinting TLS, análisis de comportamiento y modelos de ML a medida de cada cliente. No se resuelve con parches del lado del cliente — aquí hacen falta proxies, rotación, imitación del comportamiento y huellas de calidad.
Herramientas para «esconder» Selenium
Eliminar la detección por completo es imposible, pero sí se puede reducir la probabilidad de bloqueo. Lo más habitual es usar:
undetected-chromedriver(Python) — parchea el binario del driver (elimina la cadenacdc_), ocultanavigator.webdrivery ajusta las opciones. Durante mucho tiempo se consideró el «estándar de oro», pero cubre sobre todo los problemas de primera generación.selenium-stealth(Python) — un conjunto de parches JS: falseanavigator.webdriver,plugins,languages, el proveedor de WebGL, etc. Tiene un mantenimiento más flojo que UC.SeleniumBaseUC Mode — añade la técnica de disconnect/reconnect: en las acciones sensibles desconecta temporalmente ChromeDriver del navegador y sortea parte de la detección por CDP.nodriver— el sucesor deundetected-chromedriver, del mismo autor. Funciona directamente mediante CDP, sin chromedriver ni la capa de WebDriver, lo que elimina una serie de marcadores. Ya no es del todo «Selenium», sino un enfoque aparte.- Técnicas manuales — el flag
--disable-blink-features=AutomationControlled, desactivarenable-automation, falsearnavigator.webdrivermediantePage.addScriptToEvaluateOnNewDocumenty hacer que el User-Agent concuerde con las propiedades reales de navigator.
Puede comprobar hasta qué punto se ha «escondido» bien su navegador en bancos de pruebas públicos como bot.sannysoft.com o en servicios de fingerprinting.
Una advertencia importante
Todas estas bibliotecas no son una bala de plata. Las empresas anti-bot estudian las evasiones de código abierto: qué parches aplica exactamente undetected-chromedriver se ve directamente en su repositorio. Lo que hoy sortea una protección puede dejar de funcionar tras la próxima actualización — sin previo aviso. Por eso, para el scraping serio casi siempre se añaden a Selenium proxies de calidad con rotación, retardos razonables, perfiles «calentados» con cookies e imitación del comportamiento humano. Y, aun así, frente a la protección de tercera generación, Selenium a secas suele quedarse corto.
Cuándo conviene usar Selenium y cuándo no
Selenium se justifica cuando:
- el sitio se construye por completo con JavaScript y sin navegador no hay forma de obtener el contenido;
- se necesita imitar un flujo de usuario complejo (inicio de sesión, formularios de varios pasos, scroll infinito);
- los volúmenes son moderados y no de millones de páginas por hora;
- ya cuenta con un stack en Java/C#/Python y prefiere quedarse en él.
Conviene buscar una alternativa cuando:
- los datos están disponibles mediante HTTP/API normal — en ese caso,
requests/Scrapy/httpxserán varias veces más rápidos y baratos; - se necesita el máximo de escala y velocidad;
- el objetivo es sortear una protección anti-bot seria: aquí suelen ganar Playwright o Puppeteer (más modernos, con mejor control del navegador y cómodos plugins stealth) y, a veces,
nodrivero APIs especializadas.
Conclusión
Selenium es una herramienta potente y versátil: funciona con sitios dinámicos, admite multitud de lenguajes y navegadores y cuenta con una comunidad enorme y una documentación excelente. Todo ello lo convierte en una buena opción para el scraping de páginas JS complejas y de flujos que imitan a un usuario real.
Pero tiene dos peajes serios: el consumo de recursos (y, con él, los problemas de velocidad y escalado) y la facilidad con que se detecta. «De fábrica», Selenium deja decenas de huellas de automatización y, aunque se pueden camuflar en parte, frente a la protección anti-bot moderna eso a menudo no basta.
La conclusión práctica es sencilla: si los datos se pueden obtener con una petición HTTP, use un scraper HTTP. Si no hay manera sin navegador, Selenium encajará de maravilla, pero contemple en el proyecto proxies, rotación, comportamiento humano y anti-detección; y, para los objetivos más protegidos, compárelo con honestidad con Playwright, Puppeteer y las soluciones más nuevas.