# HumanCursor-Playwright
A Playwright adaptation of [HumanCursor](https://github.com/zajcikk/HumanCursor) that provides human-like mouse movements for web automation using Playwright/Patchright.
## Description
HumanCursor-Playwright is a Python library that enables human-like mouse movements in web automation using Playwright. It's designed to help you create more natural and less detectable web automation by simulating human-like cursor movements, clicks, and interactions.
This library is adapted from the HumanCursor-Botasaurus project, modified to work with Playwright's async API instead of Botasaurus driver.
## Features
- Human-like mouse movements using Bezier curves
- Randomized movement patterns to avoid detection
- Support for clicking, dragging, and scrolling with human-like behavior
- Full async/await support with Playwright
- Easy integration with existing Playwright scripts
- Customizable movement parameters
- Visual cursor tracking for debugging
## Installation
```bash
pip install humancursor-playwright
```
Or install from source:
```bash
git clone https://github.com/yourusername/humancursor-playwright
cd humancursor-playwright
pip install -e .
```
### Prerequisites
You'll also need to install Playwright browsers:
```bash
playwright install
```
## Usage
### Basic Example
```python
import asyncio
from playwright.async_api import async_playwright
from humancursor_playwright import PlaywrightCursor
async def main():
async with async_playwright() as playwright:
# Launch browser
browser = await playwright.chromium.launch(headless=False)
page = await browser.new_page()
try:
# Navigate to a website
await page.goto("https://www.example.com")
# Initialize HumanCursor
cursor = PlaywrightCursor(page)
# Find an element
button = page.locator("button.login")
# Move to the element and click it with human-like movement
await cursor.click_on(button)
finally:
await browser.close()
asyncio.run(main())
```
### Advanced Usage
```python
import asyncio
from playwright.async_api import async_playwright
from humancursor_playwright import PlaywrightCursor
async def main():
async with async_playwright() as playwright:
browser = await playwright.chromium.launch(headless=False)
page = await browser.new_page()
try:
await page.goto("https://www.example.com")
# Initialize HumanCursor
cursor = PlaywrightCursor(page)
# Show the cursor (adds a red dot to visualize movements)
await cursor.show_cursor()
# Find elements
input_field = page.locator("input[name='username']")
login_button = page.locator("button.login")
# Move to the input field with human-like movement and click
await cursor.click_on(input_field)
# Type something
await input_field.type("example_user")
# Find password field and click on it
password_field = page.locator("input[name='password']")
await cursor.click_on(password_field)
# Type password
await password_field.type("example_password")
# Move to login button and click
await cursor.click_on(login_button)
finally:
await browser.close()
asyncio.run(main())
```
### Drag and Drop Example
```python
import asyncio
from playwright.async_api import async_playwright
from humancursor_playwright import PlaywrightCursor
async def main():
async with async_playwright() as playwright:
browser = await playwright.chromium.launch(headless=False)
page = await browser.new_page()
try:
await page.goto("https://jqueryui.com/droppable/")
# Switch to iframe
iframe = page.frame_locator("iframe.demo-frame")
# Initialize HumanCursor
cursor = PlaywrightCursor(page)
# Find elements in iframe
drag_element = iframe.locator("#draggable")
drop_target = iframe.locator("#droppable")
# Perform drag and drop with human-like movement
await cursor.drag_and_drop(drag_element, drop_target)
finally:
await browser.close()
asyncio.run(main())
```
### Using with Patchright
HumanCursor-Playwright works seamlessly with [Patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright), the undetected Playwright fork:
```python
import asyncio
from patchright.async_api import async_playwright
from humancursor_playwright import PlaywrightCursor
async def main():
async with async_playwright() as playwright:
browser = await playwright.chromium.launch(headless=False)
page = await browser.new_page()
# The rest of the code is identical
cursor = PlaywrightCursor(page)
await cursor.click_on(page.locator("button"))
await browser.close()
asyncio.run(main())
```
## API Reference
### PlaywrightCursor
#### `__init__(page: Page)`
Initialize the cursor with a Playwright page object.
#### `async move_to(element_or_pos, relative_position=None, absolute_offset=False, origin_coordinates=None, steady=False)`
Move to an element or coordinates with human-like movement.
- `element_or_pos`: Playwright Locator or [x, y] coordinates
- `relative_position`: [x, y] relative position within element (0.0 to 1.0)
- `absolute_offset`: Whether coordinates are absolute offsets
- `origin_coordinates`: Starting coordinates
- `steady`: Use steadier, less random movement
#### `async click_on(element_or_pos, number_of_clicks=1, click_duration=0, button='left', ...)`
Move to element and click with human-like movement.
#### `async drag_and_drop(drag_from_element, drag_to_element, ...)`
Perform drag and drop operation with human-like movement.
#### `async show_cursor()` / `async hide_cursor()`
Show/hide a red dot that follows the cursor for debugging.
## Movement Parameters
The library automatically adjusts movement parameters based on distance and randomization:
- **Short distances (<100px)**: Minimal curve complexity
- **Medium distances (100-300px)**: Moderate curve complexity
- **Long distances (>300px)**: Higher curve complexity with more natural arcs
Parameters include:
- Bezier curve control points
- Movement speed variations
- Random distortions and offsets
- Easing functions (easeOutQuad, easeInOutSine, etc.)
## Comparison with Original
| Feature | HumanCursor-Botasaurus | HumanCursor-Playwright |
|---------|------------------------|-------------------------|
| Browser Support | Botasaurus | Playwright/Patchright |
| Async Support | No | Full async/await |
| API Style | Synchronous | Asynchronous |
| Browser Control | Limited | Full Playwright API |
| Performance | Good | Better (native async) |
| Detection Resistance | Good | Better with Patchright |
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## Credits
- Original [HumanCursor](https://github.com/zajcikk/HumanCursor) project by [zajcikk](https://github.com/zajcikk)
- [HumanCursor-Botasaurus](https://github.com/youroriginalrepo/humancursor-botasaurus) adaptation
- [Playwright](https://playwright.dev/) by Microsoft
- [Patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright) by Vinyzu
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Changelog
### v0.1.0
- Initial Playwright adaptation
- Full async/await support
- Compatible with both Playwright and Patchright
- Improved error handling and debugging features
Raw data
{
"_id": null,
"home_page": "https://github.com/yourusername/humancursor-playwright",
"name": "humancursor-playwright",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "playwright automation human cursor mouse movement web testing",
"author": "HumanCursor Playwright Fork",
"author_email": "example@example.com",
"download_url": "https://files.pythonhosted.org/packages/03/73/3f80a630724589419e2e813f3ca7477bdf2b681166a645853289acc6db46/humancursor_playwright-0.1.1.tar.gz",
"platform": null,
"description": "# HumanCursor-Playwright\r\n\r\nA Playwright adaptation of [HumanCursor](https://github.com/zajcikk/HumanCursor) that provides human-like mouse movements for web automation using Playwright/Patchright.\r\n\r\n## Description\r\n\r\nHumanCursor-Playwright is a Python library that enables human-like mouse movements in web automation using Playwright. It's designed to help you create more natural and less detectable web automation by simulating human-like cursor movements, clicks, and interactions.\r\n\r\nThis library is adapted from the HumanCursor-Botasaurus project, modified to work with Playwright's async API instead of Botasaurus driver.\r\n\r\n## Features\r\n\r\n- Human-like mouse movements using Bezier curves\r\n- Randomized movement patterns to avoid detection\r\n- Support for clicking, dragging, and scrolling with human-like behavior\r\n- Full async/await support with Playwright\r\n- Easy integration with existing Playwright scripts\r\n- Customizable movement parameters\r\n- Visual cursor tracking for debugging\r\n\r\n## Installation\r\n\r\n```bash\r\npip install humancursor-playwright\r\n```\r\n\r\nOr install from source:\r\n\r\n```bash\r\ngit clone https://github.com/yourusername/humancursor-playwright\r\ncd humancursor-playwright\r\npip install -e .\r\n```\r\n\r\n### Prerequisites\r\n\r\nYou'll also need to install Playwright browsers:\r\n\r\n```bash\r\nplaywright install\r\n```\r\n\r\n## Usage\r\n\r\n### Basic Example\r\n\r\n```python\r\nimport asyncio\r\nfrom playwright.async_api import async_playwright\r\nfrom humancursor_playwright import PlaywrightCursor\r\n\r\nasync def main():\r\n async with async_playwright() as playwright:\r\n # Launch browser\r\n browser = await playwright.chromium.launch(headless=False)\r\n page = await browser.new_page()\r\n \r\n try:\r\n # Navigate to a website\r\n await page.goto(\"https://www.example.com\")\r\n \r\n # Initialize HumanCursor\r\n cursor = PlaywrightCursor(page)\r\n \r\n # Find an element\r\n button = page.locator(\"button.login\")\r\n \r\n # Move to the element and click it with human-like movement\r\n await cursor.click_on(button)\r\n \r\n finally:\r\n await browser.close()\r\n\r\nasyncio.run(main())\r\n```\r\n\r\n### Advanced Usage\r\n\r\n```python\r\nimport asyncio\r\nfrom playwright.async_api import async_playwright\r\nfrom humancursor_playwright import PlaywrightCursor\r\n\r\nasync def main():\r\n async with async_playwright() as playwright:\r\n browser = await playwright.chromium.launch(headless=False)\r\n page = await browser.new_page()\r\n \r\n try:\r\n await page.goto(\"https://www.example.com\")\r\n \r\n # Initialize HumanCursor\r\n cursor = PlaywrightCursor(page)\r\n \r\n # Show the cursor (adds a red dot to visualize movements)\r\n await cursor.show_cursor()\r\n \r\n # Find elements\r\n input_field = page.locator(\"input[name='username']\")\r\n login_button = page.locator(\"button.login\")\r\n \r\n # Move to the input field with human-like movement and click\r\n await cursor.click_on(input_field)\r\n \r\n # Type something\r\n await input_field.type(\"example_user\")\r\n \r\n # Find password field and click on it\r\n password_field = page.locator(\"input[name='password']\")\r\n await cursor.click_on(password_field)\r\n \r\n # Type password\r\n await password_field.type(\"example_password\")\r\n \r\n # Move to login button and click\r\n await cursor.click_on(login_button)\r\n \r\n finally:\r\n await browser.close()\r\n\r\nasyncio.run(main())\r\n```\r\n\r\n### Drag and Drop Example\r\n\r\n```python\r\nimport asyncio\r\nfrom playwright.async_api import async_playwright\r\nfrom humancursor_playwright import PlaywrightCursor\r\n\r\nasync def main():\r\n async with async_playwright() as playwright:\r\n browser = await playwright.chromium.launch(headless=False)\r\n page = await browser.new_page()\r\n \r\n try:\r\n await page.goto(\"https://jqueryui.com/droppable/\")\r\n \r\n # Switch to iframe\r\n iframe = page.frame_locator(\"iframe.demo-frame\")\r\n \r\n # Initialize HumanCursor\r\n cursor = PlaywrightCursor(page)\r\n \r\n # Find elements in iframe\r\n drag_element = iframe.locator(\"#draggable\")\r\n drop_target = iframe.locator(\"#droppable\")\r\n \r\n # Perform drag and drop with human-like movement\r\n await cursor.drag_and_drop(drag_element, drop_target)\r\n \r\n finally:\r\n await browser.close()\r\n\r\nasyncio.run(main())\r\n```\r\n\r\n### Using with Patchright\r\n\r\nHumanCursor-Playwright works seamlessly with [Patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright), the undetected Playwright fork:\r\n\r\n```python\r\nimport asyncio\r\nfrom patchright.async_api import async_playwright\r\nfrom humancursor_playwright import PlaywrightCursor\r\n\r\nasync def main():\r\n async with async_playwright() as playwright:\r\n browser = await playwright.chromium.launch(headless=False)\r\n page = await browser.new_page()\r\n \r\n # The rest of the code is identical\r\n cursor = PlaywrightCursor(page)\r\n await cursor.click_on(page.locator(\"button\"))\r\n \r\n await browser.close()\r\n\r\nasyncio.run(main())\r\n```\r\n\r\n## API Reference\r\n\r\n### PlaywrightCursor\r\n\r\n#### `__init__(page: Page)`\r\nInitialize the cursor with a Playwright page object.\r\n\r\n#### `async move_to(element_or_pos, relative_position=None, absolute_offset=False, origin_coordinates=None, steady=False)`\r\nMove to an element or coordinates with human-like movement.\r\n\r\n- `element_or_pos`: Playwright Locator or [x, y] coordinates\r\n- `relative_position`: [x, y] relative position within element (0.0 to 1.0)\r\n- `absolute_offset`: Whether coordinates are absolute offsets\r\n- `origin_coordinates`: Starting coordinates\r\n- `steady`: Use steadier, less random movement\r\n\r\n#### `async click_on(element_or_pos, number_of_clicks=1, click_duration=0, button='left', ...)`\r\nMove to element and click with human-like movement.\r\n\r\n#### `async drag_and_drop(drag_from_element, drag_to_element, ...)`\r\nPerform drag and drop operation with human-like movement.\r\n\r\n#### `async show_cursor()` / `async hide_cursor()`\r\nShow/hide a red dot that follows the cursor for debugging.\r\n\r\n## Movement Parameters\r\n\r\nThe library automatically adjusts movement parameters based on distance and randomization:\r\n\r\n- **Short distances (<100px)**: Minimal curve complexity\r\n- **Medium distances (100-300px)**: Moderate curve complexity \r\n- **Long distances (>300px)**: Higher curve complexity with more natural arcs\r\n\r\nParameters include:\r\n- Bezier curve control points\r\n- Movement speed variations\r\n- Random distortions and offsets\r\n- Easing functions (easeOutQuad, easeInOutSine, etc.)\r\n\r\n## Comparison with Original\r\n\r\n| Feature | HumanCursor-Botasaurus | HumanCursor-Playwright |\r\n|---------|------------------------|-------------------------|\r\n| Browser Support | Botasaurus | Playwright/Patchright |\r\n| Async Support | No | Full async/await |\r\n| API Style | Synchronous | Asynchronous |\r\n| Browser Control | Limited | Full Playwright API |\r\n| Performance | Good | Better (native async) |\r\n| Detection Resistance | Good | Better with Patchright |\r\n\r\n## Contributing\r\n\r\nContributions are welcome! Please feel free to submit a Pull Request.\r\n\r\n## Credits\r\n\r\n- Original [HumanCursor](https://github.com/zajcikk/HumanCursor) project by [zajcikk](https://github.com/zajcikk)\r\n- [HumanCursor-Botasaurus](https://github.com/youroriginalrepo/humancursor-botasaurus) adaptation\r\n- [Playwright](https://playwright.dev/) by Microsoft\r\n- [Patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright) by Vinyzu\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License - see the LICENSE file for details.\r\n\r\n## Changelog\r\n\r\n### v0.1.0\r\n- Initial Playwright adaptation\r\n- Full async/await support\r\n- Compatible with both Playwright and Patchright\r\n- Improved error handling and debugging features\r\n",
"bugtrack_url": null,
"license": null,
"summary": "A Playwright adaptation of HumanCursor for human-like mouse movements",
"version": "0.1.1",
"project_urls": {
"Bug Reports": "https://github.com/yourusername/humancursor-playwright/issues",
"Homepage": "https://github.com/yourusername/humancursor-playwright",
"HumanCursor-Botasaurus": "https://github.com/youroriginalrepo/humancursor-botasaurus",
"Original HumanCursor": "https://github.com/zajcikk/HumanCursor",
"Source": "https://github.com/yourusername/humancursor-playwright"
},
"split_keywords": [
"playwright",
"automation",
"human",
"cursor",
"mouse",
"movement",
"web",
"testing"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "7d91cd0b1c5b0e07e76d3b2e8eb8b3a58b06d5fc68ea29de3548824e6008acc8",
"md5": "c485894310993843fc1f9beb85671605",
"sha256": "ace5403d586f1f68d7b3dacc3f163b6352711a8df46a67c52900df735cda6eed"
},
"downloads": -1,
"filename": "humancursor_playwright-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c485894310993843fc1f9beb85671605",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 15829,
"upload_time": "2025-08-21T16:35:19",
"upload_time_iso_8601": "2025-08-21T16:35:19.301587Z",
"url": "https://files.pythonhosted.org/packages/7d/91/cd0b1c5b0e07e76d3b2e8eb8b3a58b06d5fc68ea29de3548824e6008acc8/humancursor_playwright-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "03733f80a630724589419e2e813f3ca7477bdf2b681166a645853289acc6db46",
"md5": "83c2e1b8dc078cbaab94830a8d8736c5",
"sha256": "036b6ab799f476d5dae2c3d2ea64c8951867f1589144604e12e222ad25c146b6"
},
"downloads": -1,
"filename": "humancursor_playwright-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "83c2e1b8dc078cbaab94830a8d8736c5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 16736,
"upload_time": "2025-08-21T16:35:20",
"upload_time_iso_8601": "2025-08-21T16:35:20.953894Z",
"url": "https://files.pythonhosted.org/packages/03/73/3f80a630724589419e2e813f3ca7477bdf2b681166a645853289acc6db46/humancursor_playwright-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-21 16:35:20",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "humancursor-playwright",
"github_not_found": true,
"lcname": "humancursor-playwright"
}