CSS selectors perform far better than XPath selectors, and it is well documented in Selenium community. Here are some reasons:

  • XPath engines are different in each browser, hence making them inconsistent
  • Internet Explorer does not have a native XPath engine, and therefore Selenium injects its own XPath engine for compatibility of its API. Hence we lose the advantage of using native browser features that WebDriver inherently promotes.
  • XPath expressions tend to become complex and hence make them hard to read in my opinion

However, there are some situations where you need to use an XPath selector, for example, searching for a parent element or searching element by its text (I wouldn't recommend the latter).

You can read blog from Simon here. He also recommends CSS over XPath.

If you are testing content, then do not use selectors that are dependent on the content of the elements. That will be a maintenance nightmare for every locale. Try talking with developers and use techniques that they used to externalize the text in the application, like dictionaries or resource bundles, etc. Here is my blog post that explains it in detail.

Thanks to parishodak, here is the link which provides the numbers proving that CSS performance is better.

Answer from nilesh on Stack Overflow
🌐
Testsigma
testsigma.com › testsigma home › blog › xpath vs css selector : key differences
Xpath Vs CSS Selector : Key Differences
June 5, 2025 - It works across devices and responsive screens. CSS selectors are more reliable as it is mostly tied to single HTML element. CSS is unidirectional; it allows node traversal from parent to child only. When there are complex scenarios, it is difficult to construct locators. CSS selectors don’t provide methods to handle complex element locators as we have the Axes method in XPath.
🌐
BrowserStack
browserstack.com › home › guide › xpath vs css selector: key differences
Xpath Vs CSS Selector: Key Differences | BrowserStack
May 30, 2025 - XPath: It is a query language used to navigate and locate elements in XML or HTML documents. CSS Selectors: They are patterns used to select and style HTML elements based on their attributes, classes, IDs, or hierarchy.
Discussions

selenium - What is the difference between a CSS and XPath selector? And which is better with respect to performance for cross-browser testing? - Stack Overflow
I am working with the Selenium WebDriver 2.25.0 on a multilingual web application and mainly test the page content (for different languages, like Arabic, English, Russian, and so on). For my applic... More on stackoverflow.com
🌐 stackoverflow.com
html - How can I find an element by CSS class with XPath? - Stack Overflow
The function normalize-space strips leading and trailing whitespace, and also replaces sequences of whitespace characters by a single space. If you need many of these Xpath queries, you might want to use a library that converts CSS selectors to XPath, as CSS selectors are usually a lot easier ... More on stackoverflow.com
🌐 stackoverflow.com
Need help and explanation on CSS selector/Xpath for finding urls of products in this site
When you use scrapy, requests, etc, you are making HTTP requests and receiving the responses. When you use an "Actual Web Browser", the same HTTP requests are made, however, any JavaScript code present in the responses is also executed by the browser. JavaScript itself can make HTTP requests which means if JavaScript is used by a site, the data you receive in your Python code will differ from what you see in the web browser. This is one reason why people go straight to Playwright, Selenium, etc. as they drive "actual web browsers" so you generally get the same data in your code. You can also debug things a little further: When debugging sites, it's usually helpful to view the site with JavaScript disabled at some point. e.g. https://i.stack.imgur.com/4bIDe.png No products are there which is probably why your selector returns nothing (the data differs). You can use Dev Tools to search through HTTP responses. I took a random product and used part of the name to search: https://i.stack.imgur.com/4HBNT.png It is found in 2 of the requests made, the category and trousers Taking the first request as an example, we can "Copy as fetch" to see the equivalent JavaScript code. https://i.stack.imgur.com/xLf9j.png Result: fetch("https://api.depict.ai/v2/recommend/products/category", { "headers": { "accept": "*/*", "content-type": "text/plain;charset=UTF-8", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "cross-site" }, "referrer": "https://www.ginatricot.com/", "referrerPolicy": "strict-origin-when-cross-origin", "body": "{\"tenant\":\"ginatricot\",\"market\":\"dk\",\"user_id\":\"u540cp575r7t63ic0p41s\",\"type\":\"category_page\",\"category_id\":\"toj/bukser\"}", "method": "POST", "mode": "cors", "credentials": "omit" }); It is a POST request and has a JSON body. In Python: import requests r = requests.post( url = "https://api.depict.ai/v2/recommend/products/category", json = { "tenant": "ginatricot", "market": "dk", "user_id": "u540cp575r7t63ic0p41s", "type": "category_page", "category_id": "toj/bukser" } ) I removed most of the headers here but depending on the request it may fail without some/all of them, so one strategy is to just keep them all. Example from the response: >>> r.json()['displays'][0] {'brand': 'Gina Tricot', 'variants': [{'color': 'Stone (7419)', 'page_url': 'https://www.ginatricot.com/dk/toj/bukser/flare-bukser/flare-trousers-216717419', 'image_url': 'https://ginatricotpc.imgix.net/pim/product-images/216717419/swatch.jpg'}, {'color': 'Black (9000)', 'page_url': 'https://www.ginatricot.com/dk/toj/bukser/flare-bukser/flare-trousers-216719000', 'image_url': 'https://ginatricotpc.imgix.net/pim/product-images/216719000/swatch.jpg'}, {'color': 'Ecru (1045)', 'page_url': 'https://www.ginatricot.com/dk/toj/bukser/flare-bukser/flare-trousers-216711045', 'image_url': 'https://ginatricotpc.imgix.net/pim/product-images/216711045/swatch.jpg'}, {'color': 'Black iris (5980)', 'page_url': 'https://www.ginatricot.com/dk/toj/bukser/yoga-pants/flare-trousers-216715980', 'image_url': 'https://ginatricotpc.imgix.net/pim/product-images/216715980/swatch.jpg'}, {'color': 'Grey melange (8181)', 'page_url': 'https://www.ginatricot.com/dk/toj/bukser/yoga-pants/flare-trousers-216718181', 'image_url': 'https://ginatricotpc.imgix.net/pim/product-images/216718181/swatch.jpg'}], 'ga_product_id': '216717419', 'full_data': '"{\\"id\\": \\"216717419103\\", \\"sku\\": \\"216717419103\\", \\"item_group_id\\": \\"216717419\\", \\"title\\": \\"Soft touch folded flare trousers\\", \\"description\\": ... 'variant_skus': ['216717419'], 'product_id': '216717419', 'title': 'Soft touch folded flare trousers', 'original_price': 279.95, 'sale_price': 279.95, 'page_url': 'https://www.ginatricot.com/dk/toj/bukser/flare-bukser/flare-trousers-216717419', 'image_url': 'https://ginatricotpc.imgix.net/pim/product-images/216717419/21671741901.jpg', 'recommendation_id': 'ae58cadb-d0bf-48f3-886c-2a5138e08173'} I had to truncate full_data - it contains quite a lot of info and you should be able to json.loads() it. Not sure what data you're looking for exactly, but you should be able to use this information to debug further requests to find what you're after. More on reddit.com
🌐 r/Python
2
1
September 18, 2023
Different ways to get xpath elements and CSS selectors

It's contentious.

personally, I do everything with xpath. For a few reasons. Firstly, I've never found an element I couldn't get with xpath. Secondly, xpath allows me to navigate a DOM's hierarchy at will. And lastly, since xpath satisfies the first two, I don't feel the need to remember any extra syntax.

I have heard it said it's slower. If so, it's measured in milliseconds and the several hundred thread.sleeps left over in the framework from the devs before me are of much greater concern than me using xpath.

More on reddit.com
🌐 r/selenium
11
4
December 15, 2022
People also ask

Why do CSS Selectors have higher priority over XPath expressions?
CSS Selectors are used in CSS for styling HTML or XML elements, while XPath is a query language designed to select elements based on their properties and relationships. Though both can be used to select elements, they serve different functions and are distinct technologies.
🌐
testmuai.com
testmuai.com › testmu ai › blog › xpath vs css selectors: a detailed guide | testmu ai
XPath vs CSS Selectors: A Detailed Guide | TestMu AI (Formerly ...
Which XPath can be replaced by CSS Selector?
Some XPath expressions can be replaced by CSS Selectors, such as selecting elements by tag name, class, ID, or attribute value. However, CSS Selectors have limitations compared to XPath, especially for complex queries or selecting elements based on relationships, making XPath the better choice for advanced criteria.
🌐
testmuai.com
testmuai.com › testmu ai › blog › xpath vs css selectors: a detailed guide | testmu ai
XPath vs CSS Selectors: A Detailed Guide | TestMu AI (Formerly ...
Why Is XPath Preferred Over CSS Selector?
XPath is preferred over CSS selectors for its precision and advanced capabilities. It excels at granular element selection from highly nested web pages. Unlike CSS selectors, it also allows you to retrieve attributes and text nodes. Plus, its bidirectional tree traversal capabilities are crucial for navigating hierarchical layouts. While CSS selectors are ideal for basic tasks, XPath shines in complex scenarios.
🌐
zenrows.com
zenrows.com › blog › xpath-vs-css-selector
XPath vs. CSS Selectors: The Difference and Winner (2026) - ZenRows
🌐
ZenRows
zenrows.com › blog › xpath-vs-css-selector
XPath vs. CSS Selectors: The Difference and Winner (2026) - ZenRows
February 21, 2025 - At the same time, XPath enjoys wider document type compatibility (CSS selectors only work with HTML documents). It also offers advanced selection features and flexibility, which might be especially relevant when handling more complex HTML structures.
🌐
Observepoint
help.observepoint.com › all collections › audits › using xpaths and css selectors
Using XPaths and CSS Selectors | Help Center
Cascading Style Sheet (CSS) selectors is a syntax used in style definitions to locate items on a web page and apply styling to them (color, font family, positioning, etc). These selectors can also be used with jQuery to locate HTML elements. XML Path Language (XPath) is a syntax for locating ...
🌐
Testim
testim.io › blog › xpath-vs-css-selector-difference-choose
XPath vs CSS Selector: The Difference and How to Choose
March 31, 2025 - The CSS selectors identify the various elements in the DOM, and they affect or connect to these parts of the interface. CSS selectors come in many types. This is mostly because unlike the tree or map build-up of the XPath option, selectors have ...
🌐
LambdaTest
lambdatest.com › home › blog › xpath vs css selectors: a detailed guide
XPath vs CSS Selectors: A Detailed Guide | LambdaTest
April 23, 2024 - Learn the differences between XPath and CSS Selectors in selecting and styling elements on web pages.
Find elsewhere
🌐
BugBug
bugbug.io › blog › test automation
Ultimate Guide to Selectors: XPath vs CSS Selector
April 10, 2025 - XPath offers advanced features like bidirectional traversal and complex queries, making it ideal for XML and complex HTML documents. CSS selectors are simpler, faster, and better suited for straightforward HTML element selection.
🌐
Testmuai
testmuai.com › testmu ai › blog › xpath vs css selectors: a detailed guide | testmu ai
XPath vs CSS Selectors: A Detailed Guide | TestMu AI (Formerly LambdaTest)
December 29, 2025 - Learn the differences between XPath and CSS Selectors in selecting and styling elements on web pages.
Top answer
1 of 3
121

CSS selectors perform far better than XPath selectors, and it is well documented in Selenium community. Here are some reasons:

  • XPath engines are different in each browser, hence making them inconsistent
  • Internet Explorer does not have a native XPath engine, and therefore Selenium injects its own XPath engine for compatibility of its API. Hence we lose the advantage of using native browser features that WebDriver inherently promotes.
  • XPath expressions tend to become complex and hence make them hard to read in my opinion

However, there are some situations where you need to use an XPath selector, for example, searching for a parent element or searching element by its text (I wouldn't recommend the latter).

You can read blog from Simon here. He also recommends CSS over XPath.

If you are testing content, then do not use selectors that are dependent on the content of the elements. That will be a maintenance nightmare for every locale. Try talking with developers and use techniques that they used to externalize the text in the application, like dictionaries or resource bundles, etc. Here is my blog post that explains it in detail.

Thanks to parishodak, here is the link which provides the numbers proving that CSS performance is better.

2 of 3
70

I’m going to hold the unpopular on SO Selenium tag opinion that an XPath selector is preferable to a CSS selector in the long run.

This long post has two sections - first I'll put a back-of-the-napkin proof the performance difference between the two is 0.1-0.3 milliseconds (yes; that's 100 microseconds), and then I'll share my opinion why XPath is more powerful.


Performance difference

Let's first tackle "the elephant in the room" – that XPath is slower than CSS.

With the current CPU power (read: anything x86 produced since 2013), even on BrowserStack, Sauce Labs, and AWS VMs, and the development of the browsers (read: all the popular ones in the last five years) that is hardly the case.

The browser's engines have developed, the support of XPath is uniform, and Internet Explorer is out of the picture (hopefully for most of us). This comparison in the other answer is being cited all over the place, but it is very contextual – how many are running – or care about – automation against Internet Explorer 8?

If there is a difference, it is in a fraction of a millisecond.

Yet, most higher-level frameworks add at least 1 ms of overhead over the raw selenium call anyway (wrappers, handlers, state storing, etc.); my personal weapon of choice – Robot Framework – adds at least 2 ms, which I am more than happy to sacrifice for what it provides. A network round trip from an AWS US-East-1 to BrowserStack's hub is usually 11 milliseconds.

So with remote browsers, if there is a difference between XPath and CSS, it is overshadowed by everything else, in orders of magnitude.


The measurements

There are not that many public comparisons (I've really seen only the cited one), so – here's a rough single-case, dummy and simple one.

It will locate an element by the two strategies X times, and compare the average time for that.

The target – BrowserStack's landing page, and its "Sign Up" button; a screenshot of the HTML content as writing this post:

Here's the test code (Python):

from selenium import webdriver
import timeit


if __name__ == '__main__':

    xpath_locator = '//div[@class="button-section col-xs-12 row"]'
    css_locator = 'div.button-section.col-xs-12.row'

    repetitions = 1000

    driver = webdriver.Chrome()
    driver.get('https://www.browserstack.com/')

    css_time = timeit.timeit("driver.find_element_by_css_selector(css_locator)",
                             number=repetitions, globals=globals())
    xpath_time = timeit.timeit('driver.find_element_by_xpath(xpath_locator)',
                               number=repetitions, globals=globals())

    driver.quit()

    print("CSS total time {} repeats: {:.2f} s, per find: {:.2f} ms".
          format(repetitions, css_time, (css_time/repetitions)*1000))
    print("XPATH total time for {} repeats: {:.2f} s, per find: {:.2f} ms".
          format(repetitions, xpath_time, (xpath_time/repetitions)*1000))

For those not familiar with Python – it opens the page, and finds the element – first with the CSS locator, then with the XPath locator; the find operation is repeated 1,000 times. The output is the total time in seconds for the 1,000 repetitions, and average time for one find in milliseconds.

The locators are:

  • for XPath – "a div element having this exact class value, somewhere in the DOM";
  • the CSS is similar – "a div element with this class, somewhere in the DOM".

It is deliberately chosen not to be over-tuned; also, the class selector is cited for the CSS as "the second fastest after an id".

The environment – Chrome v66.0.3359.139, ChromeDriver v2.38, CPU: ULV Core M-5Y10 usually running at 1.5 GHz (yes, a "word-processing" one, not even a regular Core i7 beast).

Here's the output:

CSS total time 1000 repeats: 8.84 s, per find: 8.84 ms

XPath total time for 1000 repeats: 8.52 s, per find: 8.52 ms

Obviously, the per find timings are pretty close; the difference is 0.32 milliseconds. Don't jump "the XPath selector is faster" – sometimes it is, but sometimes it's CSS.


Let's try with another set of locators. It is a tiny-bit more complicated—an attribute having a substring (common approach at least for me, going after an element's class when a part of it bears functional meaning):

xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'

The two locators are again semantically the same – "find a div element having in its class attribute this substring".

Here are the results:

CSS total time 1000 repeats: 8.60 s, per find: 8.60 ms

XPath total time for 1000 repeats: 8.75 s, per find: 8.75 ms

A difference of 0.15 ms.


As an exercise—the same test as done in the linked blog in the comments/other answer—the test page is public, and so is the testing code.

They are doing a couple of things in the code - clicking on a column to sort by it, then getting the values, and checking the UI sort is correct.

I'll cut it - just get the locators, after all - this is the root test, right?

The same code as above, with these changes in:

  • The URL is now http://the-internet.herokuapp.com/tables; there are two tests.

  • The locators for the first one - "Finding Elements By ID and Class" - are:

css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"

And here is the outcome:

CSS total time 1000 repeats: 8.24 s, per find: 8.24 ms

XPath total time for 1000 repeats: 8.45 s, per find: 8.45 ms

A difference of 0.2 milliseconds.

The "Finding Elements By Traversing":

css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"

The result:

CSS total time 1000 repeats: 9.29 s, per find: 9.29 ms

XPath total time for 1000 repeats: 8.79 s, per find: 8.79 ms

This time it is 0.5 ms (in reverse, XPath turned out "faster" here).

So five years later (better browsers engines) and focusing only on the locators performance (no actions like sorting in the UI, etc), the same testbed - there is practically no difference between CSS and XPath.


The Best/Fastest/Hip Strategy?

So, out of XPath and CSS, which of the two to choose for performance? The answer is simple – choose locating by id.

Long story short, if the id of an element is unique (as it's supposed to be according to the specifications), its value plays an important role in the browser's internal representation of the DOM, and thus is usually the fastest.

Fun fact - the webdriver protocol actually does not support locator strategy "by id". When one uses By.ID in selenium, what it actually does is to transform it to a css selector in the form "any element having an id attribute with the requested value". Still, the browsers optimize the css engines heavily, and it ends up in the advantage section of the DOM representation.

Yet, unique and constant (e.g. not auto-generated) ids are not always available, which brings us to "why XPath if there's CSS?"


The XPath advantage

With the performance out of the picture, why do I think XPath is better? Simple – versatility, and power.

XPath is a language developed for working with XML documents; as such, it allows for much more powerful constructs than CSS.

For example, navigation in every direction in the tree—find an element, then go to its grandparent and search for a child of it having certain properties. It allows embedded boolean conditions—cond1 and not(cond2 or not(cond3 and cond4)); embedded selectors —"find a div having these children with these attributes, and then navigate according to it".

XPath allows searching based on a node's value (its text)—however frowned upon this practice is. It does come in handy especially in badly structured documents (no definite attributes to step on, like dynamic ids and classes - locate the element by its text content).

The stepping in CSS is definitely easier—one can start writing selectors in a matter of minutes; but after a couple of days of usage, the power and possibilities XPath has quickly overcomes CSS.

And purely subjective – a complex CSS expression is much harder to read than a complex XPath expression.

Outro ;)

Finally, again very subjective - which one should we chose?

IMO, there isn’t any right or wrong choice—they are different solutions to the same problem, and whatever is more suitable for the job should be picked.

Being "a fan" of XPath I'm not shy to use in my projects a mix of both - heck, sometimes it is much faster to just throw a CSS one, if I know it will do the work just fine.

🌐
testRigor
testrigor.com › home › blog › css selector vs xpath: your pocket cheat sheet
CSS Selector vs XPath: Your Pocket Cheat Sheet - testRigor AI-Based Automated Testing Tool
August 21, 2025 - XPath also has predicates (always embedded in square brackets), that you can use to find any specific node, or a node with a certain value. A CSS Selector is a string representation of different HTML tags, classes, attributes, and ids.
🌐
ScrapingBee
scrapingbee.com › blog › xpath-vs-css-selector
XPath vs CSS selectors | ScrapingBee
January 17, 2026 - In this context, CSS selectors have always had a very strong (and almost exclusive) focus on the web and web pages. While XPath stayed (mostly) true to its original purpose, of providing a query language for XML document structures (which includes HTML), CSS selectors eventually surpassed their styling-only use and emerged as stand-alone technology for querying web documents.
🌐
mabl help
help.mabl.com › hc › en-us › articles › 19078174270612-When-to-use-CSS-selectors-vs-XPath-expressions
When to use CSS selectors vs. XPath expressions – mabl help
June 20, 2025 - When creating a custom find step, you might be wondering if it's advantageous to use CSS selectors or XPath expressions for element selection. While both are powerful tools used to access web elements and have access to the entire DOM of a site, neither of them is objectively "better".
🌐
GeeksforGeeks
geeksforgeeks.org › software testing › xpath-vs-css-selector-in-java
Xpath Vs CSS Selector in Java - GeeksforGeeks
July 27, 2025 - Both forward and backward navigation in the DOM composition is possible through the same. XPath is particularly effective in cases where there are dynamic attribute changes: therefore, it is very reliable in the identification of elements. Compared to CSS Selectors it is usually slower, mainly because of the complexity of the expression language used.
🌐
Mozilla
developer.mozilla.org › en-US › docs › Web › XML › XPath › Guides › Comparison_with_CSS_selectors
Comparison of CSS Selectors and XPath - MDN Web Docs
November 7, 2025 - This article seeks to document the difference between CSS Selectors and XPath for web developers to be able to better choose the right tool for the right job.
🌐
Exadel
exadel.com › news › how-to-choose-selectors-for-automation-to-make-your-life-a-whole-lot-easier
how-to-choose-selectors-for-automation-to-make-your-life-a-whole-lot-easier/
An important difference between CSS and XPath locators in Selenium is that CSS looks for elements going down the DOM, while XPath allows you to navigate both up and down. This means that using XPath, you can find child web elements and then easily capture their parent or other ancestor.
🌐
Bright Data
brightdata.com › blog › web-data › xpath-vs-css-selectors
XPath vs CSS Selector: Comprehensive Comparison Guide
June 11, 2025 - Limited support and popularity: Not all HTML parsing libraries support XPath. This is because CSS selectors are much more popular among web developers, and libraries tend to focus on them. Plus, most XPath-based libraries like HtmlAgilityPack still rely on XPath 1.0, released in 1999.
🌐
Johnresig
johnresig.com › blog › xpath-css-selectors
John Resig - XPath and CSS Selectors
December 13, 2005 - I must’ve been copying that line to create other lines, and it slipped through. Regarding footnote 1: Unless I’m missing something, you can use the xpath “//*[@class=’foo’]” to match all elements with class=’foo’. This should do the same as the CSS selector “.foo”.
🌐
ScrapingBee
scrapingbee.com › blog › xpath-css-cheat-sheet
XPath/CSS Cheat Sheet | ScrapingBee
January 10, 2026 - A comprehensive cheat sheet for XPath and CSS selectors.
🌐
SelectorsHub
selectorshub.com › xpath-and-cssselector-functions
XPath and cssSelector functions - SelectorsHub
September 18, 2024 - The || combinator selects nodes which belong to a column. Syntax: A || B Example: col || td will match all CSS pseudo-