Skip to Content
LaunchExt | Chrome Extension Dev Platform (Next.js + Plasmo) 🚀 Read more → 
BlogBrowser Extension Development: XPath vs querySelector - Element Selection Guide

Browser Extension Development: XPath vs querySelector - Element Selection Guide

by esx_ai

When you’re building browser extensions, you often need to locate specific elements on pages. Take Zhihu’s “Post Idea” button for example - it seems simple enough, but reliably finding it consistently takes some careful consideration.

Let me walk through different approaches to locate this button and which methods tend to work best in practice.

The Button We’re Trying to Find

<button class="css-usknaz" type="button">发想法</button>

Method 1: Using querySelector

The simplest approach is to target the class directly:

document.querySelector('button.css-usknaz')

When this works: If the class name is stable and predictable, this is the easiest route

The catch: Sites like Zhihu often use dynamically generated class names (like css-usknaz) that can change unpredictably. What works today might break tomorrow.

Method 2: XPath by Text Content

When classes aren’t reliable, targeting by button text becomes a solid alternative:

//button[text()="发想法"]

For text that might have whitespace variations:

//button[normalize-space(text())="发想法"]

Or for partial text matching:

//button[contains(text(), "发想法")]

The advantage: You’re not dependent on class names that might change. As long as the button text stays consistent, your selector will keep working.

Method 3: Combined Attribute and Text Matching

For even more reliability, you can combine multiple conditions:

//button[@type="button" and contains(text(), "发想法")]

Why this is robust: You’re checking both the button type and text content, giving you double the insurance against changes.

Testing XPath in the Browser

Testing your XPath expressions is straightforward with Chrome’s built-in tools:

  1. Open Zhihu and right-click → Inspect (to open DevTools)
  2. Switch to the Console tab
  3. Test your expression:
$x('//button[text()="发想法"]')

The $x function is Chrome’s built-in XPath tester. If it finds matching elements, it returns an array containing the matched buttons.

Actual Click Implementation

Once you’ve verified your XPath works, you can use it in code:

const fa = document.evaluate( '//button[normalize-space(text())="发想法"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue as HTMLElement if (fa) fa.click()

Choosing the Right Approach

From my experience, here’s how I decide:

  • Stable classes: Use querySelector - it’s the simplest option
  • Consistent text: XPath by text content - very reliable
  • Maximum reliability: Combined attribute and text matching - most robust

For sites like Zhihu that frequently update their designs, I usually go with XPath text matching. Button text tends to stay consistent even when class names change, making it a much more reliable approach.

One Thing to Keep in Mind

Element selection in browser extensions is definitely more art than science. The key is finding features that are unlikely to change - things like button text, aria-labels, or other semantic attributes.

Don’t be afraid to experiment with different approaches. Sometimes one method won’t work, but another approach might solve the problem perfectly.

If you run into tricky element selection challenges in your own projects, I’d be curious to hear what solutions you come up with!

Last updated on