How to Enable Zendriver's best_match for Precise Element Lookup

Pass best_match=True to Tab.find() or Tab.find_element_by_text() to enable length‑based string matching that returns the most relevant element rather than the first DOM hit.

Zendriver, the async Python library for browser automation built on Chrome DevTools Protocol (CDP), provides a powerful best_match parameter for precise element lookup. When you enable Zendriver's best_match feature, the library switches from a fast first‑match strategy to an intelligent length‑based algorithm that identifies the most semantically relevant DOM element.

Understanding Zendriver's best_match Parameter

The best_match boolean flag controls whether Zendriver returns the first element containing your search text or performs additional analysis to find the "best" candidate. This distinction matters when many elements share similar text fragments—such as a "Login" button surrounded by script tags, meta descriptions, and navigation links all containing the word "login."

How best_match Works Under the Hood

When best_match=True, Zendriver calculates the absolute difference between the length of your target text and the length of each candidate element's text_all property. The element with the smallest difference—meaning its full text content most closely matches your query length—is returned as the best match.

This approach prioritizes exact or near‑exact text matches over partial substring hits, dramatically reducing false positives when searching for specific buttons, labels, or headings.

Default Behaviors in Tab.find vs Tab.find_element_by_text

Zendriver applies different defaults depending on which method you call:

  • Tab.find(text, best_match=True, ...) — Defaults to best_match=True. This high‑level helper repeatedly searches until an element is found or a timeout occurs, automatically using the precise matching algorithm.

  • Tab.find_element_by_text(text, best_match=False, ...) — Defaults to best_match=False. This lower‑level method returns the first matching element unless you explicitly enable the feature.

Enabling best_match in Your Code

You can enable Zendriver's best_match functionality by passing the parameter explicitly or relying on the default behavior of Tab.find().

Basic Usage with Tab.find

Since Tab.find() already defaults to best_match=True, you get precise matching automatically:


# best_match is True by default

login_button = await tab.find("Login", timeout=5)

This searches the DOM for elements containing "Login," compares text lengths, and returns the button or link whose full text most closely matches the string "Login."

Explicit best_match in find_element_by_text

When using the lower‑level find_element_by_text() method, you must explicitly enable the feature:


# Enable best_match explicitly

elem = await tab.find_element_by_text(
    "Continue",
    best_match=True,
    return_enclosing_element=True
)

This is useful when you need specific control over the search parameters while still benefiting from the length‑based relevance algorithm.

Disabling best_match for Performance

If you prioritize speed over precision—such as when scanning for any instance of a common word—you can disable the feature:


# Fast first-match strategy

elem = await tab.find_element_by_text(
    "login",
    best_match=False,
    return_enclosing_element=True
)

# Or override Tab.find's default

elem = await tab.find("login", best_match=False, timeout=2)

Disabling best_match returns the first DOM element containing the text, which executes faster but may return script tags, meta elements, or navigation links rather than the intended button.

Source Code Implementation

The best_match logic is implemented in zendriver/core/tab.py within the Tab class.

The find() method signature at lines 191‑207 declares best_match: bool = True as the default:

async def find(
    self,
    text: str,
    best_match: bool = True,
    return_enclosing_element: bool = True,
    timeout: int | float = 10,
) -> Element:
    ...

The find_element_by_text() method at lines 627‑656 implements the length‑based selection algorithm when best_match is enabled:

async def find_element_by_text(
    self,
    text: str,
    best_match: bool = False,
    return_enclosing_element: bool = True,
) -> Element | None:
    ...
    if best_match:
        # Select element with minimum length difference

        elem = min(
            elems,
            key=lambda el: abs(len(text) - len(el.text_all))
        )

Summary

  • Enable best_match by passing best_match=True to find_element_by_text() or using Tab.find() which defaults to True.
  • Algorithm: When enabled, Zendriver compares the length of your search text against each candidate's text_all property, returning the element with the smallest difference.
  • Trade‑off: best_match improves relevance by finding exact or near‑exact text matches but consumes more CPU cycles than the default first‑match strategy.
  • Source location: Implementation resides in zendriver/core/tab.py within the find() (lines 191‑207) and find_element_by_text() (lines 627‑656) methods.

Frequently Asked Questions

What is the difference between Tab.find and Tab.find_element_by_text?

Tab.find is a high‑level helper that repeatedly calls find_element_by_text until an element is found or a timeout occurs, and it defaults to best_match=True. Tab.find_element_by_text is the lower‑level method that performs a single search and defaults to best_match=False for faster first‑match retrieval.

Does enabling best_match affect performance significantly?

Yes, enabling best_match requires Zendriver to gather all matching elements and calculate text length differences for each candidate, which is O(n) complexity relative to the number of matches. For pages with hundreds of elements containing common substrings, this can add noticeable latency compared to the immediate first‑match return.

Can I use best_match with the find_all method?

No, the best_match parameter is not applicable to find_all (or find_elements_by_text). These methods return every matching element as a list, so there is no single "best" candidate to select. The length‑based algorithm only applies when returning a single element.

Why does Tab.find default to best_match=True while find_element_by_text defaults to False?

Tab.find is designed for robust automation scripts where returning the wrong element (such as a script tag) causes flaky tests, so it prioritizes accuracy over speed. find_element_by_text serves as a lightweight primitive for developers who may want to implement their own filtering logic or who prioritize execution speed when scanning large documents.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →