A Python library for simulating human-like behavior in Playwright browser automation. This library helps you create more realistic automated scenarios by mimicking natural mouse movements, typing patterns, and user interactions.
- 🖱️ Realistic Mouse Movements: Smooth, curved mouse trajectories using spline interpolation with natural acceleration and deceleration
- ⌨️ Human-like Typing: Simulates typing with occasional typos and corrections
- 🎯 Smart Element Interaction: Automatically calculates realistic click offsets within element boundaries
- 📜 Natural Scrolling: Human-like scrolling patterns with variable speeds
- ⏳ Loading Behavior: Simulates user behavior during page loads (mouse movements in circles, figure-8, or chaotic patterns)
- 🎨 Customizable Speed: Adjustable movement speeds and timing variations
- ⚡ Async & Sync Support: Both asynchronous and synchronous APIs available
pip install -r requirements.txtMake sure you have Playwright browsers installed:
playwright installimport asyncio
from playwright.async_api import async_playwright
from human_behavior_playwright import HumanBehaviorControllerAsync
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
controller = HumanBehaviorControllerAsync()
# Navigate with human-like behavior
await controller.goto_with_loading_behavior(page, "https://example.com")
# Human-like click
await controller.human_click(page, "button#submit")
# Human-like typing
await controller.human_type(page, "input#search", "Hello World")
# Random mouse movement
await controller.random_mouse_movement(page)
# Human-like scrolling
await controller.human_scroll(page, direction="down", amount=3)
await browser.close()
asyncio.run(main())from playwright.sync_api import sync_playwright
from human_behavior_playwright import HumanBehaviorControllerSync
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
controller = HumanBehaviorControllerSync()
# Navigate with human-like behavior
controller.goto_with_loading_behavior(page, "https://example.com")
# Human-like click
controller.human_click(page, "button#submit")
# Human-like typing
controller.human_type(page, "input#search", "Hello World")
# Random mouse movement
controller.random_mouse_movement(page)
# Human-like scrolling
controller.human_scroll(page, direction="down", amount=3)
browser.close()Main controller classes for human-like behavior simulation.
Performs a human-like click with realistic mouse movement to the element.
Parameters:
page: Playwright Page object (async or sync depending on controller)selector: CSS selector string to locate the element to click
# Async
await controller.human_click(page, "button#submit")
# Sync
controller.human_click(page, "button#submit")Types text with human-like patterns, including occasional typos and corrections.
Parameters:
page: Playwright Page objectselector: CSS selector string to locate the input fieldtext: Text string to type into the field
# Async
await controller.human_type(page, "input#email", "user@example.com")
# Sync
controller.human_type(page, "input#email", "user@example.com")Performs a random mouse movement to simulate user activity.
Parameters:
page: Playwright Page object
# Async
await controller.random_mouse_movement(page)
# Sync
controller.random_mouse_movement(page)Performs human-like scrolling with variable speeds.
Parameters:
page: Playwright Page objectdirection: Scroll direction, either "down" or "up". Default is "down"amount: Number of scroll actions to perform. Default is 3
# Async
await controller.human_scroll(page, direction="down", amount=5)
# Sync
controller.human_scroll(page, direction="up", amount=2)Simulates user behavior during loading (mouse movements in circles, figure-8, or chaotic patterns).
Parameters:
page: Playwright Page objecttimeout: Duration in milliseconds to simulate waiting behavior. Default is 5000
# Async
await controller.loading_wait_behavior(page, timeout=3000)
# Sync
controller.loading_wait_behavior(page, timeout=3000)Navigates to a URL and simulates human behavior after page load.
Parameters:
page: Playwright Page objecturl: URL string to navigate totimeout: Navigation timeout in milliseconds. Default is 30000
# Async
await controller.goto_with_loading_behavior(page, "https://example.com")
# Sync
controller.goto_with_loading_behavior(page, "https://example.com")Low-level mouse controllers for advanced usage.
Moves the mouse cursor to target coordinates with organic movement patterns.
Parameters:
page: Playwright Page objecttarget_x: Target X coordinate in pixelstarget_y: Target Y coordinate in pixelsspeed_factor: Speed multiplier (1.0 = normal, >1.0 = faster, <1.0 = slower). Default is 1.0
# Async
await mouse_controller.move(page, 500, 300, speed_factor=1.5)
# Sync
mouse_controller.move(page, 500, 300, speed_factor=1.5)Moves the cursor to an element with organic movement patterns.
Parameters:
page: Playwright Page objectselector: CSS selector string to locate the elementspeed_factor: Speed multiplier. Default is 1.0offset_x: Custom X offset in pixels from element center (0 = auto-generate). Default is 0offset_y: Custom Y offset in pixels from element center (0 = auto-generate). Default is 0
# Async
await mouse_controller.move_to_element(page, "button#submit", speed_factor=1.2)
# Sync
mouse_controller.move_to_element(page, "button#submit", speed_factor=1.2)move_to_element_and_click(page, selector, speed_factor=1.0, offset_x=0, offset_y=0, click_delay=0.1)
Moves the cursor to an element and clicks it.
Parameters:
page: Playwright Page objectselector: CSS selector string to locate the elementspeed_factor: Speed multiplier. Default is 1.0offset_x: Custom X offset in pixels (0 = auto-generate). Default is 0offset_y: Custom Y offset in pixels (0 = auto-generate). Default is 0click_delay: Delay in seconds between mouse arrival and click. Default is 0.1
# Async
await mouse_controller.move_to_element_and_click(page, "a#link")
# Sync
mouse_controller.move_to_element_and_click(page, "a#link")Moves the cursor to an element and hovers over it.
Parameters:
page: Playwright Page objectselector: CSS selector string to locate the elementspeed_factor: Speed multiplier. Default is 1.0offset_x: Custom X offset in pixels (0 = auto-generate). Default is 0offset_y: Custom Y offset in pixels (0 = auto-generate). Default is 0
# Async
await mouse_controller.move_to_element_and_hover(page, "div#menu")
# Sync
mouse_controller.move_to_element_and_hover(page, "div#menu")You can adjust the speed factor to make movements faster or slower:
# Faster movement
await mouse_controller.move_to_element(page, "button", speed_factor=2.0)
# Slower movement
await mouse_controller.move_to_element(page, "button", speed_factor=0.5)Specify custom offsets for clicking elements:
await mouse_controller.move_to_element_and_click(
page,
"button#submit",
offset_x=10,
offset_y=5
)If you don't specify offsets (or use 0, 0), the library will automatically generate realistic offsets within the element's clickable area.
# Async example
async def fill_form():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
controller = HumanBehaviorControllerAsync()
await controller.goto_with_loading_behavior(page, "https://example.com/form")
# Fill form fields
await controller.human_type(page, "input[name='name']", "John Doe")
await controller.human_type(page, "input[name='email']", "john@example.com")
await controller.human_type(page, "textarea[name='message']", "Hello!")
# Submit
await controller.human_click(page, "button[type='submit']")
await browser.close()- Path Calculation: Calculates the number of path nodes based on distance
- Coordinate Generation: Generates path coordinates with natural variance
- Spline Interpolation: Uses scipy's spline interpolation to create smooth curves
- Dynamic Intervals: Applies bell-shaped acceleration/deceleration curves
- Execution: Moves the mouse through the trajectory with variable timing
The library uses normal distribution to generate click offsets within 60-80% of the element's size, making clicks appear more natural and less robotic.
- Python 3.8+
- Playwright 1.40.0+
- NumPy 1.24.0+
- SciPy 1.10.0+
MIT License
If you encounter any issues or have questions, please open an issue on GitHub.