Overview
nodriver provides utility functions in the nodriver.core.util module and exports commonly used ones at the top level. These functions help with event loops, browser management, DOM traversal, and more.
Event Loop Functions
loop()
Create a new asyncio event loop.
def loop() -> asyncio.AbstractEventLoop
See the loop() API reference for details.
Example:
import nodriver as uc
async def main():
browser = await uc.start()
# Your code here
browser.stop()
uc.loop().run_until_complete(main())
Browser Management
start()
Launch a browser instance.
async def start(
config: Optional[Config] = None,
*,
user_data_dir: Optional[PathLike] = None,
headless: Optional[bool] = False,
browser_executable_path: Optional[PathLike] = None,
browser_args: Optional[List[str]] = None,
sandbox: Optional[bool] = True,
lang: Optional[str] = None,
host: Optional[str] = None,
port: Optional[int] = None,
expert: Optional[bool] = None,
**kwargs: Optional[dict],
) -> Browser
See the start() API reference for details.
get_registered_instances()
Get all active browser instances.
def get_registered_instances() -> Set[Browser]
Returns: Set of all Browser instances that have been started.
Example:
import nodriver as uc
from nodriver.core import util
browser1 = await uc.start()
browser2 = await uc.start()
instances = util.get_registered_instances()
print(f"Active browsers: {len(instances)}")
for browser in instances:
browser.stop()
deconstruct_browser()
Clean up browser instances and temporary profiles.
def deconstruct_browser(browser: Browser = None)
Specific browser to clean up. If None, cleans up all registered instances.
Example:
import nodriver as uc
from nodriver.core import util
browser = await uc.start()
# Do work...
# Clean up specific browser
util.deconstruct_browser(browser)
# Or clean up all browsers
util.deconstruct_browser()
free_port()
Find an available port for browser debugging.
Returns: Available port number.
Example:
from nodriver.core import util
port = util.free_port()
print(f"Using port: {port}")
browser = await uc.start(port=port)
DOM Traversal
filter_recurse()
Find the first element matching a predicate by recursively traversing the DOM tree.
def filter_recurse(
doc: Union[cdp.dom.Node, Element],
predicate: Callable[[cdp.dom.Node, Element], bool]
) -> Union[cdp.dom.Node, Element]
doc
cdp.dom.Node | Element
required
Root node to start traversal from.
Function that takes a node and returns True to select it.
Returns: First node matching the predicate, or None.
Example:
from nodriver.core import util
from nodriver import cdp
# Get document tree
doc = await tab.send(cdp.dom.get_document(-1, True))
# Find first button element
button = util.filter_recurse(
doc,
lambda node: node.node_name == 'BUTTON'
)
filter_recurse_all()
Find all elements matching a predicate by recursively traversing the DOM tree.
def filter_recurse_all(
doc: Union[cdp.dom.Node, Element],
predicate: Callable[[cdp.dom.Node, Element], bool]
) -> List[Union[cdp.dom.Node, Element]]
doc
cdp.dom.Node | Element
required
Root node to start traversal from.
Function that takes a node and returns True to include it.
Returns: List of all nodes matching the predicate.
Example:
from nodriver.core import util
# Find all link elements
links = util.filter_recurse_all(
doc,
lambda node: node.node_name == 'A'
)
print(f"Found {len(links)} links")
Frame Tree Functions
flatten_frame_tree()
Flatten a hierarchical frame tree into a flat list of frames.
def flatten_frame_tree(
tree: Union[cdp.page.FrameResourceTree, cdp.page.FrameTree]
) -> Generator[cdp.page.Frame, None, None]
tree
cdp.page.FrameResourceTree | cdp.page.FrameTree
required
Frame tree to flatten.
Yields: Frame objects from the tree.
Example:
from nodriver.core import util
from nodriver import cdp
# Get frame tree
frame_tree = await tab.send(cdp.page.get_frame_tree())
# Flatten to list of frames
frames = list(util.flatten_frame_tree(frame_tree))
for frame in frames:
print(f"Frame: {frame.url}")
flatten_frame_tree_resources()
Flatten frame tree and yield frame-resource pairs.
def flatten_frame_tree_resources(
tree: cdp.page.FrameResourceTree
) -> Generator[Tuple[cdp.page.Frame, cdp.page.FrameResource], None, None]
Yields: Tuples of (frame, resource) for each resource in the tree.
Geometry Functions
circle()
Generate coordinates around a circle for smooth circular motion.
def circle(
x: float,
y: float = None,
radius: int = 10,
num: int = 10,
dir: int = 0
) -> Generator[Tuple[float, float], None, None]
Center Y coordinate. If None, uses x value.
Number of points to generate (higher = smoother but slower).
Direction: 0 for clockwise, 1 for counter-clockwise.
Yields: (x, y) coordinate tuples around the circle.
Example:
import nodriver as uc
from nodriver.core import util
async def main():
browser = await uc.start()
tab = await browser.get('https://example.com')
# Move window in a circle
window_id, bounds = await tab.get_window()
center_x, center_y = bounds.left, bounds.top
for x, y in util.circle(center_x, center_y, radius=100, num=50):
await tab.set_window_size(int(x), int(y))
browser.stop()
uc.loop().run_until_complete(main())
CDP Helper Functions
cdp_get_module()
Get a CDP module by domain name.
def cdp_get_module(domain: Union[str, types.ModuleType]) -> types.ModuleType
Domain name (e.g., ‘page’, ‘network’) or module object.
Returns: CDP domain module.
Example:
from nodriver.core import util
# Get page domain
page_module = util.cdp_get_module('page')
# Use it
command = page_module.navigate(url='https://example.com')
Comparison Functions
compare_target_info()
Compare two TargetInfo objects and return differences.
def compare_target_info(
info1: cdp.target.TargetInfo,
info2: cdp.target.TargetInfo
) -> List[Tuple[str, Any, Any]]
Returns: List of tuples (field_name, old_value, new_value) for changed fields.
Example:
from nodriver.core import util
changes = util.compare_target_info(old_target, new_target)
for field, old_val, new_val in changes:
print(f"{field}: {old_val} -> {new_val}")
Advanced Functions
create_from_undetected_chromedriver()
Create a nodriver Browser from an undetected_chromedriver instance.
async def create_from_undetected_chromedriver(
driver: "undetected_chromedriver.Chrome"
) -> Browser
driver
undetected_chromedriver.Chrome
required
Running undetected_chromedriver instance.
Returns: nodriver Browser instance connected to the same browser.
Example:
import undetected_chromedriver as uc_driver
from nodriver.core import util
# Create undetected_chromedriver instance
driver = uc_driver.Chrome()
# Convert to nodriver
browser = await util.create_from_undetected_chromedriver(driver)
# Now use nodriver API
tab = browser.main_tab
await tab.get('https://example.com')
html_from_tree()
Extract HTML from a DOM tree.
async def html_from_tree(
tree: Union[cdp.dom.Node, Element],
target: Tab
) -> str
tree
cdp.dom.Node | Element
required
DOM tree or element.
Tab instance for sending CDP commands.
Returns: HTML string.
remove_from_tree()
Remove a node from a DOM tree.
def remove_from_tree(
tree: cdp.dom.Node,
node: cdp.dom.Node
) -> cdp.dom.Node
Returns: Modified tree with node removed.
Examples
Clean up all browsers on exit
import nodriver as uc
from nodriver.core import util
import atexit
# Register cleanup
atexit.register(util.deconstruct_browser)
async def main():
browser = await uc.start()
tab = await browser.get('https://example.com')
# Cleanup happens automatically on exit
uc.loop().run_until_complete(main())
Find elements with custom logic
import nodriver as uc
from nodriver.core import util
from nodriver import cdp
async def main():
browser = await uc.start()
tab = await browser.get('https://example.com')
# Get document
doc = await tab.send(cdp.dom.get_document(-1, True))
# Find all elements with specific attribute
elements = util.filter_recurse_all(
doc,
lambda node: (
hasattr(node, 'attributes') and
node.attributes and
'data-test' in node.attributes
)
)
print(f"Found {len(elements)} test elements")
browser.stop()
uc.loop().run_until_complete(main())
Circular window animation
import nodriver as uc
from nodriver.core import util
async def animate_window(tab, center_x, center_y):
"""Move window in circular pattern"""
for x, y in util.circle(
center_x,
center_y,
radius=150,
num=100,
dir=0
):
await tab.set_window_size(int(x), int(y))
async def main():
browser = await uc.start()
tab = await browser.get('https://example.com')
# Get starting position
window_id, bounds = await tab.get_window()
# Animate
await animate_window(tab, bounds.left, bounds.top)
browser.stop()
uc.loop().run_until_complete(main())
See also