Zendriver provides comprehensive methods for interacting with page elements, from simple clicks to complex drag-and-drop operations.
Clicking elements
The most common interaction is clicking elements:
import asyncio
import zendriver as zd
async def main ():
browser = await zd.start()
tab = await browser.get( "https://www.google.com" )
# Find and click a button
button = await tab.find( "I'm Feeling Lucky" , best_match = True )
await button.click()
if __name__ == "__main__" :
asyncio.run(main())
Elements are automatically flashed for 0.25 seconds when clicked, making debugging easier.
Mouse click with position
For precise control, use mouse_click() to click at specific coordinates:
element = await tab.select( ".dropdown-toggle" )
# Click at element's position
await element.mouse_click()
# Click at specific coordinates on the page
await tab.mouse_click( x = 100 , y = 200 )
Typing text
Send keyboard input to elements using send_keys():
# Find input field and type text
search_box = await tab.select( "input[name='search']" )
await search_box.send_keys( "zendriver automation" )
# Type with special keys
await search_box.send_keys( "query \n " ) # Enter key
Clear text from input fields before typing:
# Quick clear
await search_box.clear_input()
# Clear by simulating delete key presses (for custom inputs)
await search_box.clear_input_by_deleting()
Use clear_input_by_deleting() when dealing with custom input handlers that don’t respond to direct value changes.
Complete form filling example:
# Fill out a form
username = await tab.select( "#username" )
await username.send_keys( "myuser" )
password = await tab.select( "#password" )
await password.send_keys( "secretpass123" )
email = await tab.select( "#email" )
await email.send_keys( "[email protected] " )
# Submit form
submit_btn = await tab.find( "Sign Up" )
await submit_btn.click()
Select dropdowns
Work with select elements:
# Find the select element
select_elem = await tab.select( "select#country" )
await select_elem.focus()
# Get all options
options = await select_elem.query_selector_all( "option" )
# Select an option
for option in options:
if option.text == "United States" :
await option.select_option()
break
File uploads
Upload files to file input elements:
file_input = await tab.select( "input[type='file']" )
# Upload single file
await file_input.send_file( "/path/to/image.png" )
# Upload multiple files
await file_input.send_file(
"/path/to/file1.pdf" ,
"/path/to/file2.pdf"
)
Provide absolute paths to files. Multiple files are only supported if the input accepts them.
Focusing elements
Set focus on form elements:
input_field = await tab.select( "#email" )
await input_field.focus()
Ensure elements are visible before interacting:
button = await tab.find( "Load More" )
await button.scroll_into_view()
await button.click()
Hover effects
Trigger hover states by moving the mouse:
menu_item = await tab.select( ".dropdown-menu" )
await menu_item.mouse_move()
# Wait for dropdown to appear
await tab.sleep( 0.5 )
submenu = await tab.select( ".submenu-item" )
await submenu.click()
Applying JavaScript
Execute JavaScript directly on elements:
element = await tab.select( "#my-element" )
# Call a method
await element.apply( "(elem) => elem.scrollIntoView()" )
# Modify properties
await element.apply( '(elem) => { elem.style.background = "red" }' )
# Get return values
value = await element.apply( "(elem) => elem.value" )
print (value)
Method shorthand
Call JavaScript methods directly:
video = await tab.select( "video" )
# These are equivalent:
await video.apply( "(e) => e.play()" )
await video( "play" ) # Shorthand
await video( "pause" )
await video( "load" )
Modifying element content
Setting values
input_elem = await tab.select( "#quantity" )
# Set value directly
await input_elem.apply( '(elem) => { elem.value = "5" }' )
# Set text for text nodes
text_elem = await tab.select( ".message" )
children = text_elem.children
if children and children[ 0 ].node_type == 3 :
await children[ 0 ].set_text( "New message" )
Modifying HTML
Change element attributes and structure:
element = await tab.select( ".banner" )
# Modify attributes via the attrs object
element.attrs[ 'data-status' ] = 'active'
element.attrs[ 'class' ] = 'banner highlighted'
# Save changes to the DOM
await element.save_to_dom()
Removing elements
Remove elements from the page:
# Remove annoying overlays
overlay = await tab.select( ".popup-overlay" )
await overlay.remove_from_dom()
# Continue interacting with the page
Visual feedback
Highlight elements during automation:
element = await tab.select( ".important-button" )
# Flash red dot (default 0.5 seconds)
await element.flash()
# Custom duration
await element.flash( duration = 1.0 )
# DevTools-style highlight (toggle on/off)
await element.highlight_overlay()
await tab.sleep( 2 )
await element.highlight_overlay() # Toggle off
Complete interaction example
Here’s a complete example from the source repository:
import asyncio
import zendriver as zd
from pathlib import Path
async def main ():
browser = await zd.start()
tab = await browser.get( "https://imgur.com" )
# Accept cookies
consent = await tab.find( "Consent" , best_match = True )
await consent.click()
# Start new post
await ( await tab.find( "new post" , best_match = True )).click()
# Upload file
file_input = await tab.select( "input[type=file]" )
await file_input.send_file(Path( "screenshot.jpg" ).resolve())
# Wait for upload
await tab.wait( 2 )
await tab.select( ".Toast-message--check" )
# Fill title
title_field = await tab.find(
"give your post a unique title" ,
best_match = True
)
await title_field.send_keys( "undetected zendriver" )
# Get the link
grab_link = await tab.find( "grab link" , best_match = True )
await grab_link.click()
await tab.wait( 2 )
input_thing = await tab.select( "input[value^=https]" )
link = input_thing.get( "value" )
print ( f "Uploaded: { link } " )
await browser.stop()
if __name__ == "__main__" :
asyncio.run(main())
Source: examples/imgur_upload_image.py
Next steps
Keyboard and mouse Advanced keyboard and mouse control
Waiting and timing Handle dynamic content and timing