XPath vs CSS Selectors: Pick Your Best Tool

Valentina Skakun Valentina Skakun
Last update: 6 Dec 2024

One of the most common questions in web scraping is: Should I use XPath or CSS selectors to locate elements? 

In this article, I’ll share my thoughts on when to use each and which works better in specific situations.

Quick Answer: Which One is Better?

When it comes to scraping data from simple, well-structured websites, CSS selectors are often the better choice. They’re fast, easy to define, and much simpler to learn. That said, in my experience, XPath tends to shine when dealing with complex site structures or when you need more advanced functionality than CSS selectors can offer.

To make the comparison clearer, I’ve included a quick summary table:

FeatureCSS SelectorsXPath
Syntax ComplexitySimpler and more intuitive syntax.Complex and harder to learn, especially with advanced queries.
PerformanceGenerally faster in browsers; optimized for modern web development.Slower in some cases, especially in browsers, due to its complexity.
FlexibilityLimited to straightforward child-parent or sibling relationships.Highly flexible. Supports navigating both forward and backward in the Document Object Model (DOM) hierarchy.
Browser SupportFully supported and natively optimized for browsers.Supported in most modern browsers and automation tools like Selenium.
Tool IntegrationPrimarily used for web development and testing tools.Commonly used in automation tools like Selenium, Appium, and WinAppDriver for both web and desktop testing.
Desktop Application TestingNot supported for desktop application testing.Widely used for locating UI elements in desktop apps with tools like Appium and WinAppDriver.
Traversal CapabilityLimited to downward traversal (child and descendant elements).Can traverse up, down, and across the DOM tree using axes (e.g., ancestor, descendant, etc.).
Attribute HandlingLimited to simpler attribute-based selection (e.g., [id=“value”]).Allows precise selection using conditions on attributes (e.g., @id, @class).
Use with Dynamic ElementsBest suited for less complex, straightforward dynamic elements.Works well with complex or deeply nested dynamic elements.
Learning CurveEasier to learn and widely used in web development.Steeper learning curve due to extensive syntax and options.
ReadabilityCleaner and more human-readable for most use cases.Harder to read and maintain, especially for complex expressions.
Advanced ConditionsLimited support for advanced conditions, which require workarounds.Supports advanced conditional logic (and, or, functions like contains() or starts-with()).
Real-World Use CasesBest for: modern web development, testing, and web scraping.Best for: handling legacy systems, testing desktop apps, and complex DOM trees.

We’ll take a look at the pros and cons of each method soon, but here’s the gist: if you value functionality, XPath is the way to go. If simplicity is your priority, stick with CSS selectors. That said, there’s no universal rule here – unless you need a specific feature, use whatever feels most comfortable to you.

Advantages and Limitations of XPath  

Let’s talk about XPath. It’s incredibly powerful, but is it better than CSS selectors? Not exactly. While XPath has some undeniable strengths, its drawbacks often make CSS selectors the more popular choice.

Pros of XPath  

XPath’s flexibility is a standout feature. It excels in complex DOM structures where simpler selectors might fail. You can combine conditions like contains() or starts-with(), add logical operators, and even navigate the DOM using axes like parent, following-sibling, or ancestor. This makes it invaluable for intricate scenarios, especially when dealing with XML or when navigating non-HTML structures.

Unlike CSS selectors, which are limited to web pages, XPath is universal. It’s widely used in automation tools like Appium, SelectorHub, and WinAppDriver to test desktop and mobile GUIs – tasks where CSS selectors simply don’t apply.

Cons  of XPath

Here’s where XPath falls short. It’s more complex, which means it takes longer to learn and write compared to CSS selectors. Performance-wise, it can also be slower, especially in browsers, since it demands more processing.

Reading and maintaining XPath expressions can be a headache, particularly in complex scenarios. And if the DOM structure changes – say, elements get added or removed – your carefully crafted XPath can break, especially if it’s based on element positions.

Browser support adds another wrinkle. Most browsers (even older ones) only support XPath 1.0, which lacks many of the advanced functions available in XPath 2.0. If you need to handle numbers or manipulate strings, you’ll find those limitations frustrating. 

Advantages and Limitations of CSS Selectors  

Let’s talk about the more popular CSS selectors. They’re way simpler than XPath, so if you’re new to web scraping or just getting started with both CSS and XPath, I’d recommend sticking with CSS selectors.

Pros of CSS selectors  

First off, CSS selectors are much easier to learn and use, especially for beginners. They’re straightforward to write, read, and maintain, which makes your life easier when working with dynamic attributes or classes that tend to change.

Another plus is that they’re supported by all modern browsers and work seamlessly with automation tools like Selenium. Oh, and did I mention they’re faster? Browsers are optimized to handle CSS selectors, so performance is on their side.  

Cons  of CSS selectors

But CSS selectors aren’t perfect. They struggle with more complex DOM navigation, like moving up to a parent element. They also can’t handle conditional logic - so if you need to select elements based on text, you’re out of luck.

Another issue: if developers frequently tweak class names or attributes, your CSS-based scripts can break easily. Lastly, don’t forget CSS selectors are strictly for the web. Unlike XPath, they’re not usable for desktop applications or more versatile testing environments.  

Key Differences Between XPath and CSS Selectors  

Now that we’ve covered the basics of CSS selectors and XPath let’s dive into the key features to find out which one is better suited for specific situations.

Speed and Performance  

There’s a lot of talk about CSS selectors being faster than XPath. But without proof, that’s just an opinion, right? So, let’s test it out.

Here’s the test we ran: 

We wrote a Selenium script to extract elements from a page (or even a local file) using both CSS selectors and XPath. The script runs ten iterations, each performing 1,000 extractions. We then calculated the average time for both methods.

css_selector = "div.product_price"  
xpath = "//div[@class='product_price']"  

def measure_average_time_css(selector, repetitions=1000):
    times = []
    for _ in range(repetitions):
        start_time = time.time()
        driver.find_element(By.CSS_SELECTOR, selector)
        times.append(time.time() - start_time)
    average_time = sum(times) / len(times)
    return average_time

def measure_average_time_xpath(selector, repetitions=1000):
    times = []
    for _ in range(repetitions):
        start_time = time.time()
        driver.find_element(By.XPATH, selector)
        times.append(time.time() - start_time)
    average_time = sum(times) / len(times)
    return average_time

for _ in range(10):
    css_time = measure_average_time_css(css_selector)
    print(f"Time for CSS Selector: {css_time:.4f} sec")

    xpath_time = measure_average_time_xpath(xpath)
    print(f"Time for: {xpath_time:.4f} sec")

To make the results easier to digest, we plotted them in a graph:

While the difference in a single extraction is negligible, things change drastically when you scale to thousands of iterations. Performance matters when you’re running large-scale tests or scraping big amounts of data. 

Syntax Complexity  

I’ve written detailed guides on CSS selectors and XPath syntax before, so I won’t rehash everything here. Instead, let’s compare how common tasks look with each approach:

FunctionCSS SelectorXPath
Select by ID#elementID//*[@id=‘elementID’]
Select by class.className//*[contains(@class, ‘className’)]
Select by attribute[attr=‘value’]//*[@attr=‘value’]
Child elementparent > childparent/child
Any descendant elementparent childparent//child
Select by textNot supported//*[text()=‘Text’]
Partial text matchNot supported//*[contains(text(), ‘PartialText’)]
Pseudo-classes (e.g., first)ul > li:first-child//ul/li[1]
Last elementul > li:last-child//ul/li[last()]
Element by indexul > li:nth-child(3)//ul/li[3]
Combined conditionsdiv[attr1=‘value1’][attr2=‘value2’]//div[@attr1=‘value1’ and @attr2=‘value2’]
Element without an attributediv:not([attr])//div[not(@attr)]
Navigate up (to parent)Not supported//child/../parent
Multiple conditionsdiv[attr=‘value’], span.class`//div[@attr=‘value’]
Partial attribute value[attr*=‘partial’]//*[contains(@attr, ‘partial’)]
Element with empty attribute[attr=”]//*[@attr=”]

As you can see, CSS selectors are simpler and more intuitive for most use cases. However, XPath has some powerful tricks up its sleeve, like searching by text or navigating to parent elements — features that CSS selectors can’t match. 

Flexibility and Compatibility  

In short, anything you can do with CSS selectors, you can also achieve with XPath. But the reverse isn’t true.

CSS selectors are part of CSS itself, so they’re supported universally by browsers. XPath 1.0 is also widely supported, even in older browsers, while newer versions work in most modern ones.

When it comes to frameworks and tools, CSS selectors are well-supported. However, XPath’s flexibility gives it an edge for handling complex structures or working with non-web environments, like mobile and desktop applications.

How to Create and Test XPath and CSS Selectors  

Let’s break down how to create, test, and refine XPath and CSS selectors while sharing some tips to simplify the process. I’ll also touch on how you can test these selectors effectively.

Finding Selectors in Browser DevTools  

The easiest way to grab a CSS selector or XPath is to let your browser do the heavy lifting. Open DevTools (F12 or right-click and choose “Inspect”). Use the element selection tool to highlight what you’re interested in.

Once you’ve located the element in the page’s source, right-click it and choose to copy its CSS selector or XPath:

For example, the auto-generated selector for a header element might look like this:

body > div:nth-child(1) > h1

/html/body/div[1]/h1

While this works, these auto-generated selectors tend to be overly verbose. For instance, if there’s only one <h1> inside a <div>, you don’t need the entire path – you can simplify it:

div > h1

//div/h1

If you’re new to XPath and CSS selectors, this approach can be a helpful starting point, but learning to refine them is key.

Build XPath or CSS Expressions  

To craft your own selectors, you’ll still rely on DevTools, but instead of copying what’s generated, look for unique traits of the element.

Take our earlier example: the <h1> tag stands out as unique on the page. You could simplify the selector down to just the tag name:

h1

//h1

Now, let’s tackle something trickier, like identifying a product title on Amazon. The structure is more complex, but here’s the trick: look for unique attributes.

For instance, an element’s ID is meant to be unique – it’s a reliable way to pinpoint a specific element. Using that, we can create a CSS selector or an XPath for the product title:

#productTitle

//span[@id='productTitle']

Experiment with other elements on the page – try writing your own selectors and compare them with the ones I shared in my Amazon scraping guide.

This hands-on approach helps you create clean, readable XPath and CSS selectors. If you want more examples or a deeper dive into the syntax, check out my separate article on CSS selectors or dig into the nuances of XPath and how to use it in scripts.

Tools for Validating Selectors

Now, let’s talk about how to make sure the selector or expression you’ve chosen is actually correct. It’s better to check it beforehand than to fix it later in the code. There are a few main ways to validate a CSS selector or XPath expression:

  1. Use DevTools to search for an element using your chosen selector or expression and also test relevant expressions via the console.
  2. Use third-party tools or extensions to automatically get the XPath or CSS selector, which removes the risk of making a mistake.
  3. If you’re looking for an XPath for mobile or desktop testing, tools like Appium Inspector, WinAppDriver Recorder, or built-in inspectors in certain systems are great options.

Let’s focus on the most popular and easiest method, which is checking your selector and expression via DevTools. Go to the “Elements” tab and use the search bar (Ctrl+F) in the website structure to enter your desired selector:

The same goes for XPath:

Now, let’s check these elements using the DevTools console. First, here’s a small table to make it easier to understand the methods:

MethodPurposeResult
$(‘<selector>‘)Finds the first element by CSS selectorA single element (HTMLElement)
$$(‘<selector>‘)Finds all elements by CSS selectorAn array of elements (Array)
$x(‘<XPath>‘)Finds all elements by XPathAn array of elements (Array)

Using these methods is pretty simple. Just go to the “Console” tab in DevTools on the page where you want to test the selector:

Now, let’s use the table and check the selector:

If you type the selector, it will return the whole element. So, like we did in the previous example, if you need to get the text of the element, you can use the innerText method.

Let’s now do the same for an XPath expression:

Overall, these methods should be enough to check your chosen selector and improve the quality and reliability of your code.

When to Use XPath vs CSS Selectors

Instead of arguing over whether CSS selectors or XPath expressions are “better,” I’d rather focus on where each one really shines. Let’s break it down, starting with the simpler option: CSS selectors. 

You should use CSS selectors if:

  1. You’re scraping data from a website with a clean, straightforward structure (nothing too complicated or messy).
  2. You’re a beginner and haven’t worked with  XPath or CSS selectors before.
  3. You’re dealing with modern web apps that have dynamic content, where elements change frequently or are generated on the fly.
  4. You prefer selectors and find that they cover everything you need.

XPath expressions can seem more complex, but they’re the better choice in certain cases. Consider using XPath if:

  1. You need to scrape or test web pages with a complex, deeply nested DOM.
  2. You’re working with desktop or mobile apps and need more control over interactions.
  3. You’re working with XML or need to deal with intricate data structures.
  4. You need specific functionality, like searching for text or targeting a parent element.
  5. You need to perform logical operations to find the right element.

Overall, CSS selectors are great for simple and quick tasks like scraping data or interacting with web apps. XPath is a more powerful tool that is better suited for handling complex DOM structures, XML documents, and automating desktop applications.

Conclusion  

As you can see, there’s no clear-cut answer to the question: Should I use XPath or CSS selectors to locate elements? 

However, there are situations where one method is clearly more suitable. If you’re just starting out with data extraction, my advice would be to focus on learning CSS selectors first. They’re easier to understand, and for most tasks, they’re more than enough. Still, you shouldn’t overlook XPath. Its advanced features make it the go-to for complex scenarios. Choosing between them boils down to your specific needs and the level of flexibility required.

Blog

Might Be Interesting