Volver al blog
Casos de uso
Mihai MaximLast updated on May 1, 202615 min read

XPath vs Selectores CSS: Elegir el correcto

XPath vs Selectores CSS: Elegir el correcto
En resumen: tanto los selectores XPath como los CSS localizan elementos del DOM, pero resuelven problemas distintos. Los selectores CSS son más rápidos y fáciles de leer para selecciones sencillas. XPath es la mejor opción cuando hay que recorrer el DOM en cualquier dirección, buscar contenido de texto o manejar lógica condicional compleja. La mayoría de los proyectos en producción se benefician del uso estratégico de ambos.

Todos los scripts de web scraping, los flujos de trabajo de automatización de navegadores y las pruebas de extremo a extremo comparten un requisito fundamental: encontrar elementos en el DOM. La cuestión de si usar selectores XPath o CSS surge al principio de cada proyecto, y elegir el enfoque equivocado puede significar una ejecución más lenta, localizadores frágiles y un mantenimiento complicado.

XPath (XML Path Language) es un lenguaje de consulta diseñado para navegar y seleccionar nodos en documentos XML y HTML. Los selectores CSS son cadenas de patrones creadas originalmente para aplicar estilos a HTML, pero ampliamente adoptadas para la selección de elementos en marcos de pruebas y scraping. Ambos te llevan a los mismos elementos, pero la ruta que siguen (y las ventajas e inconvenientes a lo largo del camino) difieren significativamente.

Esta guía desglosa la sintaxis, las características de rendimiento, la compatibilidad con los marcos de trabajo y el comportamiento en casos extremos de cada enfoque para que puedas tomar una decisión segura y fundamentada para tu proyecto.

XPath frente a selectores CSS de un vistazo

Tanto XPath como los selectores CSS identifican elementos dentro de un documento HTML o XML, pero provienen de mundos diferentes. XPath se creó para la navegación por documentos XML y admite recorrido bidireccional, lo que significa que puedes pasar de un elemento hijo a uno padre con la misma facilidad que de uno padre a uno hijo. Los selectores CSS tienen su origen en las hojas de estilo y se mueven en una sola dirección: de padre a hijo (o hermano).

He aquí el veredicto rápido: si tus necesidades de selección son sencillas (ID, clases, atributos, combinadores), los selectores CSS son la opción más rápida y legible. Cuando necesites recorrer hacia arriba, hacer coincidir contenido de texto o aplicar filtros condicionales complejos, XPath es la única opción que te permitirá lograrlo.

Dimensión

Selectores CSS

XPath

Dirección

Solo de padre a hijo

Bidireccional (cualquier eje)

Velocidad

Generalmente más rápido (motor nativo)

Más lento en los navegadores

Coincidencia de texto

No compatible

text(), contains()

Legibilidad

Conciso, familiar

Detallado, curva más pronunciada

Tipos de documento

Solo HTML

HTML y XML

Cómo funciona XPath

XPath, abreviatura de XML Path Language, es un lenguaje de expresiones para navegar y consultar documentos XML, incluido el HTML. Trata el documento como un árbol de nodos y permite escribir expresiones de ruta que seleccionan uno o varios de esos nodos.

Rutas absolutas frente a relativas. Una ruta XPath absoluta parte de la raíz del documento y detalla cada paso: /html/body/div[1]/ul/li[3]. Es frágil porque cualquier cambio estructural lo rompe. Una ruta XPath relativa comienza con // y coincide con los nodos independientemente de su posición en el árbol: //li[@class='active']. En la práctica, las rutas relativas son casi siempre lo que se necesita.

Los métodos de ejes son donde XPath realmente destaca. Métodos como parent::, ancestor::, following-sibling::y preceding-sibling:: te permiten moverte en cualquier dirección desde un nodo de contexto. Por ejemplo, //span[@id='price']/parent::div selecciona el padre div de un elemento específico span, algo que los selectores CSS simplemente no pueden hacer.

Funciones clave como contains(), starts-with(), y text() añaden filtrado condicional. Puedes localizar un elemento cuyo texto visible incluya una subcadena (//a[contains(text(), 'Next Page')]) sin depender en absoluto de los atributos.

Una advertencia importante: la mayoría de los entornos de navegador solo admiten XPath 1.0, publicado en 1999 por el W3C. XPath 2.0 y 3.0 introdujeron potentes características como expresiones regulares y sistemas de tipos más completos, pero rara vez las encontrarás en la automatización basada en navegadores. Bibliotecas como lxml (Python) sí ofrecen compatibilidad con XPath 2.0, por lo que la versión que obtengas dependerá de tu cadena de herramientas.

Cómo funcionan los selectores CSS

Un selector CSS es una cadena de patrón que se dirige a elementos HTML en función de su nombre de etiqueta, ID, clase, atributos, posición o estado. Diseñados originalmente para aplicar estilos en hojas de estilo, los selectores CSS se han convertido en el método predeterminado de selección de elementos en la mayoría de los marcos modernos de automatización y scraping.

Los conceptos básicos son familiares para cualquier desarrollador front-end. #main se dirige a un elemento por su ID. .card coincide con elementos que tienen una clase específica. div > p selecciona directamente p hijos directos de un div. Los selectores de atributos como input[type="email"] y las pseudoclases posicionales como :nth-child(2) te permiten acotar aún más la selección.

Las pseudoclases modernas están acortando distancias con XPath. El :has() selector, ahora ampliamente compatible, te permite seleccionar un padre en función de sus hijos: div:has(> img.hero) selecciona cualquier div que contenga directamente un img con la clase hero. El :is() y :where() pseudoclases simplifican la agrupación, y :not() permiten la exclusión. Estas incorporaciones significan que los selectores CSS pueden gestionar algunos casos que antes requerían XPath.

Dicho esto, los selectores CSS no pueden seleccionar nodos de texto directamente y siguen limitados al recorrido hacia adelante (de padre a hijo). Además, solo funcionan con documentos HTML; si necesitas consultar XML sin procesar o fuentes que no sean HTML, XPath es tu única opción.

Comparación de sintaxis lado a lado

Ver los selectores XPath y CSS uno al lado del otro es la forma más rápida de interiorizar sus diferencias. La tabla siguiente muestra los objetivos de selección comunes en ambas sintaxis, centrándose en los mismos elementos hipotéticos de la página.

Objetivo de selección

Selector CSS

XPath

Por ID

#username

//*[@id='username']

Por clase

.card

//*[contains(@class,'card')]

Por atributo

a[href^="https"]

//a[starts-with(@href,'https')]

Hijo directo

ul > li

//ul/li

Enésimo hijo

li:nth-child(3)

//li[3]

Por contenido de texto

No es posible

//a[text()='Login']

Elemento padre

div:has(> span.icon) (CSS4)

//span[@class='icon']/parent::div

Hermano siguiente

h2 ~ p

//h2/following-sibling::p

Ancestro

No es posible

//span/ancestor::form

Hay algunas cosas que llaman la atención. Para las selecciones de ID, clase y atributos, CSS es notablemente más corto y fácil de leer. Pero en cuanto necesitas coincidencia de texto o recorrido de antepasados, XPath es la única opción disponible. La :has() pseudo-clase reduce esta diferencia en la selección de padres, pero no puede sustituir al sistema de ejes completo de XPath.

Desde el punto de vista de la legibilidad, los selectores CSS resultan naturales para cualquiera que haya escrito una hoja de estilos. La sintaxis basada en rutas de XPath es más prolija, pero esa prolijidad te aporta precisión para consultas complejas. Si tu equipo incluye desarrolladores front-end que se sienten cómodos con CSS, se familiarizarán con los selectores CSS mucho más rápido que con las expresiones XPath.

Rendimiento y velocidad

La opinión generalizada es que los selectores CSS son más rápidos que XPath en entornos de navegador, y en la práctica eso suele ser cierto. Los navegadores incluyen motores de selectores CSS nativos altamente optimizados porque la coincidencia de CSS es una parte fundamental del proceso de renderizado. La evaluación de XPath, por el contrario, se sitúa fuera de esa ruta rápida y suele conllevar más sobrecarga.

Dicho esto, no existen benchmarks públicos estandarizados y ampliamente citados que cuantifiquen la diferencia exacta en el rendimiento entre XPath y los selectores CSS. La diferencia es real, pero a menudo insignificante, a menos que se estén ejecutando decenas de miles de evaluaciones de selectores por página. Para la mayoría de los flujos de trabajo de scraping y pruebas, la velocidad de los selectores rara vez es el cuello de botella; la latencia de la red y la renderización de la página dominan el tiempo de ejecución.

Fuera del navegador, el panorama cambia. Bibliotecas como lxml compilan expresiones XPath en código C optimizado, lo que hace que la evaluación de XPath sea extremadamente rápida para el scraping del lado del servidor en Python. Los usuarios de Scrapy, por ejemplo, pueden no encontrar prácticamente ninguna diferencia de velocidad entre los selectores XPath y CSS, ya que ambos se evalúan a través de lxml en segundo plano.

Filtrado avanzado, recorrido y legibilidad

El recorrido bidireccional de XPath es su mayor ventaja técnica. El uso de ejes como parent::, ancestor::, following-sibling::, y preceding-sibling::, puedes navegar por el árbol DOM en cualquier dirección desde cualquier nodo de partida. Esto es indispensable cuando el elemento que necesitas seleccionar carece de un atributo único, pero tiene una relación predecible con un hermano o un antecesor que sí lo tiene.

Los selectores CSS solo van hacia adelante. Se puede ir de padre a hijo (>) o de un hermano anterior a uno posterior (~, +), pero no se puede ir hacia arriba. La :has() pseudoclase es una solución parcial: permite seleccionar condicionalmente a un padre en función de sus descendientes. Aun así, :has() no ofrece un recorrido completo de los antepasados, y su compatibilidad con los navegadores, aunque va en aumento, aún no es universal en entornos más antiguos.

La selección de nodos de texto es otra clara ventaja de XPath. Expresiones como //td[contains(text(), 'Total')] permiten localizar elementos por su contenido visible, lo cual es muy valioso para extraer datos de páginas en las que los elementos no tienen una clase o un ID significativos. CSS no tiene equivalente.

La curva de aprendizaje merece una mención a la hora de evaluar los selectores XPath frente a los CSS para tu equipo. Los selectores CSS se benefician de una amplia familiaridad; la mayoría de los desarrolladores los han escrito en hojas de estilo mucho antes de encontrarse con la automatización. Las expresiones XPath, especialmente aquellas que utilizan múltiples ejes o predicados anidados, conllevan una mayor carga cognitiva. Esa complejidad merece la pena cuando la necesitas, pero para selecciones más sencillas supone una sobrecarga innecesaria.

Compatibilidad con marcos y bibliotecas

No todos los marcos tratan los selectores XPath y CSS por igual. Antes de decidirte por una estrategia de selectores, comprueba qué es lo que realmente admite tu cadena de herramientas.

Marco / Biblioteca

Selectores CSS

XPath

Selenium (todos los lenguajes)

Playwright

Titiritero

Sí (a través de $x())

Scrapy (Python)

Sí (a través de parsel)

Sí (a través de parsel/lxml)

lxml (Python)

Sí (a través de cssselect)

Sí (nativo)

BeautifulSoup (Python)

No (utiliza el backend de lxml)

Cheerio (Node.js)

No

Hay algunos matices que vale la pena señalar. Puppeteer expone XPath a través de un $x() en lugar de la $() API de selección, por lo que la integración es ligeramente menos fluida. BeautifulSoup no incluye un motor XPath integrado; si necesitas XPath con BeautifulSoup, tendrás que combinarlo con un backend de análisis sintáctico lxml. Cheerio está diseñado exclusivamente para CSS.

Para los usuarios de Selenium que estén comparando los selectores XPath con los CSS, ambos tipos son de primera clase a través de By.CSS_SELECTOR y By.XPATH. Playwright también admite ambos, lo que lo convierte en una buena opción si quieres flexibilidad para mezclar estrategias de selección dentro de un único conjunto de pruebas o canal de análisis de datos.

Casos extremos: Shadow DOM, iframes y contenido dinámico

Las páginas del mundo real rara vez son tan limpias como los ejemplos de los tutoriales, y la decisión entre XPath y los selectores CSS se vuelve más matizada cuando entran en escena el Shadow DOM, los iframes y el contenido inyectado dinámicamente.

Shadow DOM. Los selectores CSS no pueden atravesar una raíz Shadow cerrada por defecto. Playwright ofrece el prefijo css=pierce/ prefijo como solución alternativa, pero los motores CSS estándar de los navegadores se detienen en el límite del Shadow DOM. XPath tampoco ayuda en este caso; no tiene ningún concepto nativo de Shadow DOM. En ambos casos, normalmente se necesitan API específicas del marco (como locator() con «piercing») para acceder a los elementos Shadow.

Iframes. Ni XPath ni los selectores CSS cruzan los límites de los iframes por sí mismos. Primero debes cambiar el controlador o el contexto al documento del iframe (driver.switchTo().frame() en Selenium, frame.contentFrame() en Playwright) y, a continuación, ejecutar el selector dentro de ese ámbito.

Contenido dinámico. Las aplicaciones de página única que reescriben el DOM durante la navegación plantean un reto diferente. Los selectores CSS que apuntan a atributos estables como data-testid o aria-label suelen ser más resistentes en este caso que los selectores basados en clases, que pueden cambiar entre compilaciones. Las expresiones XPath vinculadas al contenido de texto también pueden ser fiables, siempre que el texto visible se mantenga constante.

Escribir selectores resistentes

Independientemente de si te decantas por los selectores XPath o CSS, escribir selectores que sobrevivan a los cambios en el DOM es más importante que el lenguaje que elijas. Los localizadores frágiles son la principal causa de pruebas inestables y rastreadores defectuosos.

Buenas prácticas para ambos tipos:

  • Da preferencia a los atributos estables. Utiliza data-testid, aria-label, u otros atributos semánticos en lugar de nombres de clase generados automáticamente o índices posicionales.
  • Mantén los selectores cortos. Un selector CSS como [data-testid="submit-btn"] es más resistente que div.form-wrapper > div:nth-child(3) > button.btn-primary. Lo mismo se aplica a XPath: //button[@data-testid='submit-btn'] es mejor que una ruta absoluta de cinco niveles.
  • Evita el XPath absoluto. Los selectores que comienzan por /html/body/... dejan de funcionar en cuanto cambia cualquier elemento padre. Utiliza siempre XPath relativo que comience por //.

Antipatrones comunes que hay que evitar:

  • Encadenar más de tres niveles de combinadores descendientes en CSS
  • Usar XPath position() o la selección basada en índices (div[4]) cuando existe un atributo semántico
  • Depender de nombres de clase generados dinámicamente (algo habitual en los marcos CSS-in-JS) para cualquiera de los dos tipos de selector

Invertir en una estrategia de selectores desde el principio, elegir anclajes estables y documentar tus convenciones, ahorra un tiempo significativo de depuración a medida que tu proyecto crece.

Cuándo usar XPath, selectores CSS o ambos

No hay un ganador universal en el debate entre XPath y los selectores CSS. La elección correcta depende de lo que estés creando.

Opta por los selectores CSS cuando tus selecciones impliquen ID, clases, atributos o pseudoclases posicionales. Son más rápidos en los navegadores, más fáciles de leer y compatibles en todas partes. Para tareas sencillas de web scraping y la mayor parte de la automatización de pruebas front-end, los selectores CSS cubren el 80 % o más de tus necesidades de localización con menos código.

Recurre a XPath cuando necesites recorrer hacia arriba (selección de padres o antepasados), hacer coincidir contenido de texto o aplicar filtros condicionales complejos que encadenan múltiples predicados. XPath también es la mejor opción cuando se trabaja con documentos XML que no son HTML o cuando los elementos de destino carecen de atributos útiles.

Utiliza ambos cuando tu proyecto lo justifique. En Selenium o Playwright, mezclar ambos no supone ningún coste By.CSS_SELECTOR y By.XPATH en el mismo archivo de prueba. Un enfoque híbrido te permite utilizar CSS para las selecciones sencillas y rápidas y XPath para los pocos casos extremos que lo requieran.

Lista de verificación de referencia rápida

Utiliza esta lista de verificación para adaptar las restricciones de tu proyecto al tipo de selector adecuado:

  • La velocidad es la máxima prioridad y estás ejecutando en un navegador: utiliza selectores CSS.
  • Necesitas recorrer elementos padres o ancestros: utiliza XPath.
  • Necesitas realizar una coincidencia por contenido de texto visible: utiliza XPath.
  • Tu marco de trabajo solo admite un tipo (por ejemplo, Cheerio solo admite CSS): utiliza lo que esté disponible.
  • Estás extrayendo feeds XML o datos que no son HTML: utiliza XPath.
  • Tu equipo está compuesto principalmente por desarrolladores front-end: opta por los selectores CSS para una incorporación más rápida.
  • El DOM cambia con frecuencia y quieres localizadores resistentes: utiliza el tipo que se adapte data-testid o aria-label (ambos lo gestionan bien).

Conclusiones clave

  • Los selectores CSS suelen ser más rápidos en entornos de navegador y más legibles para selecciones estándar (ID, clase, atributo, posicional).
  • XPath es la única opción cuando necesitas recorrer el DOM en ambos sentidos, buscar coincidencias de contenido de texto o seleccionar antepasados.
  • Las pseudoclases CSS modernas como :has() están reduciendo la brecha de capacidades, pero no sustituyen por completo al sistema de ejes de XPath.
  • La compatibilidad con los marcos varía: Cheerio y BeautifulSoup (sin lxml) solo admiten CSS, mientras que Selenium y Playwright admiten ambos tipos de selectores por igual.
  • Al comparar los selectores XPath con los CSS, la decisión más importante es escribir selectores resilientes que apunten a atributos estables en lugar de localizadores posicionales frágiles o de clases generadas.

Preguntas frecuentes

¿Puedo utilizar selectores XPath y CSS en la misma prueba de Selenium?

Sí. Selenium admite ambos tipos de selectores a través de By.CSS_SELECTOR y By.XPATH, y puedes mezclarlos libremente dentro de un mismo archivo de prueba o incluso de un mismo método de prueba. No hay pérdida de rendimiento al cambiar entre ambos, así que utiliza el tipo que mejor se adapte a la búsqueda de cada elemento concreto.

¿Los selectores CSS modernos como :has() sustituyen a XPath para la selección de elementos padres?

En parte. La :has() pseudoclase permite seleccionar un elemento padre en función de sus hijos, lo que cubre el escenario más común de selección de padres. Sin embargo, no admite el recorrido completo de antepasados a través de múltiples niveles, la lógica de hermanos anteriores ni las cadenas condicionales que permiten los ejes de XPath. Piensa en :has() que cubre aproximadamente el 60 % de los casos que antes requerían XPath para la navegación ascendente.

¿Qué tipo de selector es más fiable para aplicaciones dinámicas de página única?

Ninguno es intrínsecamente más fiable. La fiabilidad depende de a qué ancles tu selector, no del lenguaje del selector en sí. Los selectores que apuntan a data-testid o aria-label permanecen estables durante las recargas del marco, independientemente de si están escritos en CSS o XPath. Evita los selectores que dependan de nombres de clase generados automáticamente o de índices posicionales profundos.

¿Se admite XPath en Puppeteer y Playwright?

Sí, ambos admiten XPath. Puppeteer lo expone a través del $x() método (o page.evaluate con document.evaluate). Playwright admite XPath de forma nativa en su locator() y $() API. En ambas herramientas, los selectores CSS son los predeterminados y los más utilizados, pero XPath está disponible cuando se necesitan sus capacidades de recorrido.

Conclusión

La cuestión de XPath frente a los selectores CSS no tiene una única respuesta, ya que son herramientas complementarias que resuelven problemas que se solapan pero son distintos. Los selectores CSS deben ser tu opción predeterminada por su velocidad, legibilidad y simplicidad. XPath debe ser tu recurso cuando te topes con un obstáculo con el recorrido unidireccional, necesites una coincidencia basada en texto o trabajes con formatos de documento que no sean HTML.

El lenguaje del selector importa menos que la calidad del mismo. Ancla tus localizadores a atributos semánticos y estables. Hazlos breves. Documenta tus convenciones para que el próximo desarrollador (o tu yo futuro) no tenga que hacer ingeniería inversa para averiguar por qué existe una expresión XPath específica.

Acerca del autor
Mihai Maxim, Desarrollador Full Stack @ WebScrapingAPI
Mihai MaximDesarrollador Full Stack

Mihai Maxim es desarrollador full stack en WebScrapingAPI, donde colabora en todas las áreas del producto y ayuda a crear herramientas y funciones fiables para la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.