system onlinepath: /guias/testing/como-instalar-y-usar-selenium/mode: knowledge_baselocal:
Testing y QA · Nivel inicial

Selenium: qué es, cómo se instala y cómo se usa

La herramienta de automatización de navegadores más veterana y la única que implementa un estándar del W3C. Acá está todo lo que necesitás para instalarla, escribir tu primer script y no caer en los errores de esperas que rompen la mayoría de las suites.

13 min de lectura▣ Actualizada el ◇ Por Underc0de
Respuesta rápida

Selenium WebDriver es una biblioteca que controla navegadores reales desde código, implementando la especificación WebDriver del W3C. Se instala con el gestor de paquetes de tu lenguaje —pip install selenium en Python, una dependencia Maven en Java, dotnet add package Selenium.WebDriver en C#— y desde la versión 4.6 ya no hace falta descargar drivers a mano: lo resuelve Selenium Manager. Un script se compone siempre de ocho bloques, de abrir la sesión a cerrarla. Selenium automatiza el navegador y nada más: el ejecutor de pruebas y las aserciones los aporta el framework de tu lenguaje.

Ver índice de contenidos
  1. 01Qué es Selenium, en concreto
  2. 02Qué necesitás antes de instalar
  3. 03Cómo se instala en cada lenguaje
  4. 04Tu primer script, bloque por bloque
  5. 05Cómo encontrar elementos sin que se rompa
  6. 06Esperas: el error que rompe más suites
  7. 07Sin ventana y en integración continua
  8. 08Cómo organizarlo cuando crece
  9. 09Errores frecuentes al empezar
  10. 10Preguntas frecuentes
  11. 11Fuentes

Qué es Selenium, en concreto

Cuando alguien dice «Selenium» puede estar hablando de tres cosas distintas, y conviene separarlas antes de instalar nada:

  • Selenium WebDriver: la biblioteca que controla el navegador desde tu código. Es lo que se usa en el 99 % de los casos y de lo que trata esta guía.
  • Selenium IDE: una extensión de navegador que graba y reproduce interacciones, sin escribir código. Sirve para explorar, no para sostener una suite.
  • Selenium Grid: la pieza que distribuye la ejecución en varias máquinas para correr en paralelo.

La definición oficial de WebDriver es «una API y un protocolo que definen una interfaz neutral respecto del lenguaje para controlar el comportamiento de los navegadores». La parte importante de esa frase es protocolo: WebDriver es una especificación del W3C, el mismo organismo que estandariza HTML y CSS. Los navegadores traen soporte porque el estándar existe, no porque Selenium se los pida, y eso es lo que permite que el mismo conjunto de órdenes funcione desde cinco lenguajes distintos.

i
Qué no incluye

Selenium automatiza el navegador y se detiene ahí. No trae ejecutor de pruebas, aserciones, informes ni ejecución en paralelo: eso lo aporta el framework de tu lenguaje. Si esperabas que todo viniera en la misma caja, la comparación entre las tres herramientas está en Selenium, Cypress o Playwright.

Qué necesitás antes de instalar

Menos de lo que suele creerse. La lista completa son tres cosas:

  1. Un navegador instaladoChrome, Firefox o Edge alcanzan. Safari solo se puede automatizar en macOS, con safaridriver.
  2. Un lenguaje y su gestor de paquetesPython con pip, Java con Maven o Gradle, C# con NuGet, Ruby con gem, o Node.js con npm.
  3. Nada másEn particular, ningún driver descargado a mano: de eso se encarga Selenium Manager desde la versión 4.6.

Sobre versiones mínimas del lenguaje, los propios repositorios de paquetes son la fuente a mirar porque cambian con cada release. Al 27 de julio de 2026, el paquete selenium de PyPI declara Python 3.10 o superior y selenium-webdriver en npm declara Node.js 20 o superior.

Cómo se instala en cada lenguaje

Estos son los comandos que figuran en la documentación oficial. La versión estable al momento de escribir esta guía es la 4.46.0.

Instalación por lenguaje
# Python
pip install selenium

# JavaScript / Node.js
npm install selenium-webdriver

# C# / .NET
dotnet add package Selenium.WebDriver

# Ruby
gem install selenium-webdriver

En Java se declara como dependencia del proyecto. Con Maven, dentro de pom.xml:

XML · Maven
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.46.0</version>
</dependency>

Y con Gradle, en build.gradle: testImplementation "org.seleniumhq.selenium:selenium-java:4.46.0". Si trabajás en Kotlin, se usan las bindings de Java sin nada extra.

!
Fijá la versión en el proyecto

En equipos, conviene declarar la versión exacta (selenium==4.46.0 en requirements.txt, por ejemplo) en lugar de instalar siempre la última. Así una actualización silenciosa no rompe la suite de otra persona un lunes a la mañana.

Tu primer script, bloque por bloque

La documentación oficial describe cualquier script de Selenium como una combinación de ocho operaciones. Aprenderlas de entrada ahorra mucho tiempo, porque después toda prueba que leas —por larga que sea— se descompone en estas mismas piezas.

Ocho tarjetas numeradas en dos columnas: iniciar la sesión con webdriver.Chrome(), actuar sobre el navegador con driver.get(url), pedir información al navegador con driver.title, definir la estrategia de espera con WebDriverWait, encontrar un elemento con find_element y la clase By, actuar sobre el elemento con send_keys o click, pedir información del elemento con la propiedad text, y cerrar la sesión con driver.quit().
Los ocho bloques que define la documentación oficial de Selenium. Los nombres son idénticos en los cinco lenguajes.

Veámoslos funcionando sobre una página real: el índice de guías de este portal, que filtra resultados en el cliente mientras escribís. El script abre la página, busca wardriving y comprueba que quede una sola guía.

Python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 1. Iniciar la sesión — Selenium Manager resuelve el driver solo
driver = webdriver.Chrome()

try:
    # 2. Actuar sobre el navegador
    driver.get("https://underc0de.org/guias/")

    # 3. Pedir información al navegador
    print("Título:", driver.title)

    # 5. Encontrar un elemento
    buscador = driver.find_element(By.CSS_SELECTOR, "[data-guide-search]")

    # 6. Actuar sobre el elemento
    buscador.send_keys("wardriving")

    # 4. Estrategia de espera + 7. información del elemento
    contador = WebDriverWait(driver, 10).until(
        EC.text_to_be_present_in_element(
            (By.CSS_SELECTOR, "[data-result-count]"), "1 guía encontrada"
        )
    )
    assert contador, "El buscador no filtró a una sola guía"

finally:
    # 8. Cerrar la sesión, pase lo que pase
    driver.quit()

Dos detalles que no son decorativos. El try/finally garantiza que driver.quit() se ejecute incluso si la aserción falla: sin eso, cada corrida fallida deja un proceso de navegador vivo en segundo plano, y después de una tarde de trabajo tenés la memoria llena. Y quit() no es lo mismo que close(): close() cierra la ventana actual, quit() termina el proceso del driver y con él todas las ventanas.

Cómo encontrar elementos sin que se rompa

Selenium busca elementos con la clase By, que ofrece ocho estrategias. Estas son las que valen la pena en la práctica:

Estrategias de localización de Selenium y cuándo conviene cada una
EstrategiaEjemploCuándo usarla
By.IDBy.ID, "login"Primera opción si el elemento tiene un id estable y único.
By.CSS_SELECTORBy.CSS_SELECTOR, "[data-test=enviar]"La más versátil. Ideal con atributos puestos a propósito para pruebas.
By.NAMEBy.NAME, "email"Campos de formulario, que casi siempre tienen name.
By.LINK_TEXTBy.LINK_TEXT, "Ver guía"Enlaces, cuando el texto visible es estable.
By.XPATHBy.XPATH, "//button[text()='Enviar']"Último recurso: cuando hay que subir en el árbol o filtrar por texto.

La regla que ahorra más mantenimiento: pedile al equipo de desarrollo un atributo dedicado a las pruebas, del tipo data-test="boton-enviar". Un selector apoyado en clases de CSS se rompe la primera vez que alguien retoca el diseño, y un XPath copiado del navegador —esos que se ven como /html/body/div[3]/div/div[2]/button— se rompe cuando cambia cualquier cosa en el camino. El atributo dedicado, en cambio, existe solo para esto y nadie lo toca por accidente.

Ojo con la diferencia entre find_element y find_elements: el primero devuelve el primer elemento coincidente y lanza una excepción si no hay ninguno; el segundo devuelve una lista, posiblemente vacía. Para comprobar que algo no está, usá el segundo y verificá que la lista esté vacía.

Esperas: el error que rompe más suites

Este es el punto donde se cae casi todo el mundo, así que vale la pena leerlo despacio. Selenium no espera solo. Cuando pedís un elemento que la página todavía no terminó de renderizar, no hay reintento: falla. Y como el momento exacto depende de la red y de la máquina, la prueba anda en tu computadora y falla en el servidor de integración continua.

Hay tres formas de manejarlo, y solo dos son buenas.

Espera implícita

Se configura una vez y aplica a todas las búsquedas de elementos: el driver reintenta durante ese tiempo antes de dar error. Su valor por defecto es 0, es decir, sin espera.

Python
# Aplica a todo find_element de esta sesión
driver.implicitly_wait(10)

Es cómoda pero tosca: espera a que el elemento exista en el DOM, no a que sea visible o clicable, y no sirve para esperar que un texto cambie.

Espera explícita

Espera una condición concreta en un punto concreto del código. Es la que conviene usar casi siempre.

Python
# Esperar hasta 10 s a que el botón sea clicable
boton = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "[data-test=enviar]"))
)
boton.click()

Las condiciones más usadas de expected_conditions son visibility_of_element_located, element_to_be_clickable, text_to_be_present_in_element y invisibility_of_element_located —esta última, perfecta para esperar que desaparezca un indicador de carga.

!
No mezcles las dos

La documentación oficial es explícita: «no mezcles esperas implícitas y explícitas, hacerlo puede causar tiempos de espera impredecibles». El ejemplo que da es elocuente: una implícita de 10 segundos junto a una explícita de 15 puede terminar esperando 20. Elegí una estrategia —idealmente, explícitas— y dejá la implícita en 0.

Y la que no hay que usar

time.sleep(5). Una pausa fija siempre está mal calibrada: es demasiado larga cuando la app responde rápido, y demasiado corta el día que la red va lenta. Multiplicada por doscientas pruebas, convierte una suite de tres minutos en una de media hora que igual falla.

Sin ventana y en integración continua

En un servidor de CI no hay pantalla, así que el navegador tiene que correr en modo headless —sin interfaz gráfica—. Se configura con las opciones del navegador:

Python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

opciones = Options()
opciones.add_argument("--headless=new")
opciones.add_argument("--window-size=1440,900")

driver = webdriver.Chrome(options=opciones)

Fijar el tamaño de ventana no es un detalle: sin pantalla, el navegador adopta un tamaño por defecto que puede dejar elementos fuera de la vista y hacer fallar clics que localmente funcionan. Es una de las causas más frecuentes de «anda en mi máquina pero no en CI».

Para que las pruebas se ejecuten como una suite de verdad —con informes, ejecución en paralelo y capturas al fallar— hay que combinarlas con el framework de tu lenguaje. En Python, con pytest, el patrón habitual es una fixture que abre y cierra el navegador por cada prueba:

Python · pytest
import pytest
from selenium import webdriver

@pytest.fixture
def driver():
    navegador = webdriver.Chrome()
    yield navegador          # acá corre la prueba
    navegador.quit()          # y esto se ejecuta siempre al terminar

def test_titulo_del_indice(driver):
    driver.get("https://underc0de.org/guias/")
    assert "Underc0de" in driver.title

Con esto ya podés correr pytest y tener el andamiaje que Selenium no incluye: descubrimiento de pruebas, aserciones legibles, informes y ejecución selectiva.

Cómo organizarlo cuando crece

Con diez pruebas cualquier estructura funciona. A partir de cincuenta, el problema deja de ser escribirlas y pasa a ser mantenerlas: si el botón de login cambió de selector y ese selector está copiado en treinta archivos, tenés treinta ediciones por delante.

La respuesta clásica se llama Page Object Model (modelo de objetos de página): cada pantalla de la aplicación se representa como una clase que concentra sus selectores y expone acciones con nombres del dominio. Las pruebas dejan de hablar de CSS y empiezan a hablar de negocio.

Python · Page Object
class IndiceDeGuias:
    URL = "https://underc0de.org/guias/"
    BUSCADOR = (By.CSS_SELECTOR, "[data-guide-search]")
    CONTADOR = (By.CSS_SELECTOR, "[data-result-count]")

    def __init__(self, driver):
        self.driver = driver

    def abrir(self):
        self.driver.get(self.URL)
        return self

    def buscar(self, texto):
        self.driver.find_element(*self.BUSCADOR).send_keys(texto)
        return self

# La prueba queda legible y sin un solo selector a la vista
def test_busqueda_filtra(driver):
    IndiceDeGuias(driver).abrir().buscar("wardriving")

El selector vive en un solo lugar. Cuando cambia, se edita una línea. Es el patrón más difundido en suites de Selenium y vale la pena adoptarlo antes de que la suite crezca, no después.

Errores frecuentes al empezar

  • Seguir un tutorial anterior a 2022. Si te dice que descargues chromedriver, que uses webdriver-manager o que llames a find_element_by_id(), está desactualizado: esos métodos se eliminaron en Selenium 4.3 y el driver lo resuelve Selenium Manager desde la 4.6.
  • Olvidar quit(). Cada corrida deja un proceso vivo. Usá try/finally o una fixture del framework de pruebas.
  • Resolver la intermitencia con sleep. Esconde el problema y multiplica el tiempo de ejecución.
  • Copiar XPath desde las herramientas del navegador. Son rutas absolutas que se rompen con cualquier cambio de estructura.
  • Guardar elementos en variables y reutilizarlos después de que la página cambie. Si el elemento se vuelve a renderizar, la referencia queda huérfana y aparece el clásico StaleElementReferenceException. Volvé a buscarlo.
  • Automatizar por la interfaz lo que se verifica mejor en la API. Una regla de negocio se comprueba con una petición HTTP en milisegundos; moverla a un navegador la vuelve lenta y frágil.

Preguntas frecuentes

¿Necesito descargar chromedriver a mano?

No. Desde Selenium 4.6 el paquete incluye Selenium Manager, que detecta el navegador instalado, descarga el driver compatible y lo guarda en caché sin que configures nada. Actúa como respaldo: si en tu código ya indicás la ruta de un driver, esa tiene prioridad. Si venís de tutoriales viejos, podés borrar de tu proyecto webdriver-manager y las líneas que definían webdriver.chrome.driver.

¿Qué lenguaje conviene usar con Selenium?

El que ya escriba tu equipo. Selenium tiene bindings oficiales para Java, Python, C#, Ruby y JavaScript, y los ocho bloques de un script son idénticos en los cinco: cambia la sintaxis, no los conceptos. Java es el más extendido en suites corporativas grandes, Python el más cómodo para arrancar, y C# el habitual en equipos .NET. Kotlin usa las bindings de Java.

¿Por qué mi prueba falla de manera intermitente?

Casi siempre es un problema de esperas. Selenium no espera solo: si buscás un elemento que todavía no existe porque la página lo carga con JavaScript, falla. La solución no es agregar pausas fijas con sleep, que hacen la suite lenta y siguen fallando cuando la red va más despacio, sino usar esperas explícitas con WebDriverWait sobre la condición concreta que necesitás. Y no mezclar esperas implícitas con explícitas: la documentación oficial advierte que hacerlo produce tiempos de espera impredecibles.

¿Selenium sirve para hacer scraping o bots?

Técnicamente sí, y de hecho mucha gente lo conoce por ahí. Pero antes de automatizar un sitio que no es tuyo hay que revisar sus términos de servicio y su archivo robots.txt, y no generar carga que afecte el servicio. Automatizar tu propia aplicación o un entorno de pruebas autorizado no tiene ese problema. Para extraer datos, además, una API o una petición HTTP directa suele ser más rápida y estable que mover un navegador completo.

¿Qué es Selenium Grid y cuándo lo necesito?

Es el componente que distribuye la ejecución en varias máquinas o contenedores, para correr pruebas en paralelo y en distintas combinaciones de navegador y sistema operativo. No lo necesitás para empezar: tiene sentido cuando la suite creció tanto que ejecutarla en serie en una sola máquina tarda demasiado, o cuando tenés que certificar navegadores que no están en tu equipo.

¿Selenium incluye aserciones e informes?

No. Selenium WebDriver automatiza el navegador y nada más; a diferencia de Cypress y Playwright, no trae ejecutor de pruebas, aserciones ni informes. Eso se lo agregás vos con el framework de tu lenguaje: pytest o unittest en Python, JUnit o TestNG en Java, NUnit o xUnit en C#, RSpec en Ruby, Mocha o Jest en JavaScript.

Fuentes

Documentación oficial y registros de paquetes consultados para esta guía. Fecha de consulta: 27 de julio de 2026.

  1. Selenium. Install a Selenium library. Comandos de instalación para los cinco lenguajes y coordenadas de Maven y Gradle.
  2. Selenium. Write your first Selenium script. Los ocho bloques de un script y el comportamiento de driver.quit().
  3. Selenium. Waiting strategies. Esperas implícitas, explícitas y fluidas, valor por defecto y advertencia sobre mezclarlas.
  4. Selenium. Selenium Manager (Beta). Gestión automática de drivers desde la versión 4.6.
  5. Selenium. Locator strategies. Las estrategias disponibles en la clase By.
  6. SeleniumHQ, en GitHub. [py]: remove deprecated find_element_by_ methods. Eliminación de los métodos de localización antiguos en Python.
  7. PyPI. selenium. Versión 4.46.0 y Python ≥ 3.10. El requisito de Node.js ≥ 20 figura en el campo engines del paquete selenium-webdriver del registro de npm.
  8. Underc0de, foro. «Selenium: aprende a crear tus propios bots con Python», por Mortal_Poison, 5 de octubre de 2017. Aporte de la comunidad que introdujo el tema en el foro; su código usa la API anterior a Selenium 4.