DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

XPath in Firefox: Console Shortcuts, JavaScript API, DevTools Inspector, and Selenium Integration

XPath (XML Path Language) is a query language for selecting nodes in XML/HTML documents. Firefox has XPath support both in JavaScript and as a built-in DevTools feature. Here's how to use it.

XPath in Firefox DevTools Console

Firefox DevTools Console has a built-in $x() function that evaluates XPath against the current page:

// Find all h2 elements
$x('//h2')

// Find elements with a specific attribute
$x('//*[@class="highlighted"]')

// Find links containing specific text
$x('//a[contains(text(), "Download")]')

// Find elements by attribute value
$x('//input[@type="email"]')

// Find parent of an element with specific class
$x('//*[@class="child"]/parent::*')

// Find next sibling
$x('//h1/following-sibling::p[1]')

// Count elements
$x('count(//li)')  // Returns a number

// Find text content of specific elements
$x('//title/text()')  // Array of text nodes
Enter fullscreen mode Exit fullscreen mode

Using XPath in JavaScript

The JavaScript XPath API is verbose but powerful:

// Find all paragraphs (returns XPathResult)
const result = document.evaluate(
  '//p',                              // XPath expression
  document,                           // context node
  null,                               // namespace resolver
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,  // result type
  null                                // existing result (null = new)
);

// Iterate through results
for (let i = 0; i < result.snapshotLength; i++) {
  const node = result.snapshotItem(i);
  console.log(node.textContent);
}

// Single node
const single = document.evaluate(
  '//h1[1]',
  document,
  null,
  XPathResult.FIRST_ORDERED_NODE_TYPE,
  null
).singleNodeValue;

console.log(single?.textContent);
Enter fullscreen mode Exit fullscreen mode

Result types:

  • XPathResult.ORDERED_NODE_SNAPSHOT_TYPE — Array-like of all matching nodes (most useful)
  • XPathResult.FIRST_ORDERED_NODE_TYPE — Just the first match
  • XPathResult.NUMBER_TYPE — For count() and similar numeric XPath
  • XPathResult.STRING_TYPE — For string expressions
  • XPathResult.BOOLEAN_TYPE — For boolean expressions

XPath in DevTools Inspector

Find element with XPath:
Ctrl+F in the Inspector panel → change filter from "selector" to "XPath" → type your XPath.

Copy element's XPath:
In the Inspector, right-click an element → Copy → XPath (or Copy → Full XPath)

The "XPath" option gives the shortest unique path. "Full XPath" gives the absolute path from the document root.

Example output:

//*[@id="main-content"]/p[3]      (shortest)
/html/body/div[2]/main/p[3]       (full path)
Enter fullscreen mode Exit fullscreen mode

XPath vs CSS Selectors

XPath is more powerful than CSS selectors in some ways:

XPath can (CSS can't):

  • Select parent nodes: //span/parent::div
  • Select based on text content: //p[contains(text(), "Firefox")]
  • Navigate sibling axes: //h1/following-sibling::*[1]
  • Use string functions: normalize-space(), translate(), contains()

CSS can (XPath is awkward):

  • :hover, :focus, pseudo-classes
  • ~ (general sibling) — XPath equivalent is verbose
  • CSS is generally more readable for standard selectors

Rule of thumb: Use CSS selectors for element selection in code. Use XPath when you need text-based selection or parent/ancestor traversal.

XPath for Web Scraping

When scraping structured data from HTML:

// Extract all article titles and links
const titles = document.evaluate(
  '//article//h2/a',
  document,
  null,
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  null
);

const articles = [];
for (let i = 0; i < titles.snapshotLength; i++) {
  const link = titles.snapshotItem(i);
  articles.push({
    title: link.textContent.trim(),
    href: link.href
  });
}
console.table(articles);
Enter fullscreen mode Exit fullscreen mode

Test in console first: Use $x('//article//h2/a') in the DevTools console to verify your XPath before putting it in code.

XML Namespaces in XPath

For XML documents with namespaces (SVG, XHTML, Atom feeds), you need a namespace resolver:

// For SVG documents (namespace: http://www.w3.org/2000/svg)
function nsResolver(prefix) {
  const namespaces = {
    'svg': 'http://www.w3.org/2000/svg',
    'xhtml': 'http://www.w3.org/1999/xhtml'
  };
  return namespaces[prefix] || null;
}

const svgPaths = document.evaluate(
  '//svg:path[@fill="red"]',
  document,
  nsResolver,
  XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  null
);
Enter fullscreen mode Exit fullscreen mode

For HTML documents: Namespaces aren't needed (HTML5 parsers don't require them). Use $x('//path') directly.

Common XPath Patterns

// nth child of type
$x('//ul[1]/li[3]')             // Third li in first ul

// Last child
$x('//ul/li[last()]')

// Elements with specific text
$x('//button[text()="Submit"]')

// Elements where attribute starts with
$x('//*[starts-with(@class, "btn")]')

// Elements where attribute contains value in space-separated list
$x('//*[contains(concat(" ", @class, " "), " active ")]')
// (This is the correct way to match a class in a class list)

// Count children
$x('count(//div[@id="list"]/li)')

// Find by position
$x('(//table)[2]//tr')          // All rows in the second table

// Conditional
$x('//img[@src and not(@alt)]') // Images missing alt text (accessibility!)
Enter fullscreen mode Exit fullscreen mode

XPath in Selenium/Playwright Tests

XPath is commonly used in automated tests:

Selenium (Python):

# Find element by XPath
element = driver.find_element(By.XPATH, '//button[text()="Login"]')
elements = driver.find_elements(By.XPATH, '//table//tr')
Enter fullscreen mode Exit fullscreen mode

Playwright:

// XPath in Playwright
const button = page.locator('xpath=//button[text()="Login"]');
const rows = page.locator('xpath=//table//tr');

// Or using the direct xpath: prefix
await page.locator('//button[text()="Login"]').click();
Enter fullscreen mode Exit fullscreen mode

Test in DevTools first: Before writing Playwright/Selenium code with XPath, test the expression in the Firefox console with $x(). If it returns the right elements, the same XPath will work in tests.

Firefox XPath Extensions

The standard $x() in Firefox console is equivalent to:

// What $x() does under the hood:
function $x(xpath, context = document) {
  const result = context.evaluate(
    xpath, context, null,
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
  );
  const nodes = [];
  for (let i = 0; i < result.snapshotLength; i++) {
    nodes.push(result.snapshotItem(i));
  }
  return nodes;
}
Enter fullscreen mode Exit fullscreen mode

You can save this to a utility if you need it outside of DevTools.

XPath 2.0 and 3.0

The browser XPath implementation is XPath 1.0 only. XPath 2.0 (with sequences, types, regular expressions) is not supported in browsers.

If you need XPath 2.0 features: use a JavaScript XPath library like fontoxpath which implements XPath 3.1.

For most web development use cases, XPath 1.0 is sufficient.

Top comments (0)