Files
human_mouse/README.md
Huang Qi 65ef838bd7 feat: initial release of human_mouse v0.1.0
A small Python library for replaying real human mouse trajectories from
the SapiMouse dataset onto a Playwright page. Designed for ML-based
bot-detection research, behavioral biometrics prototyping, and
replay-based test fixtures.

Public API: load_all_segments, pick_segments, affine_warp, upsample,
replay, replay_random, download_sapimouse.

- src/ layout with hatchling build backend
- 23 pytest tests (10 transform unit + 13 integration)
- MIT license, PEP 561 py.typed marker
- python -m human_mouse download for one-shot dataset fetch
- examples/cloakbrowser_demo.py demonstrates end-to-end use with CloakBrowser

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-12 00:30:18 +08:00

122 lines
3.9 KiB
Markdown

# human_mouse
Replay real human mouse trajectories from the [SapiMouse](https://www.ms.sapientia.ro/~manyi/sapimouse/sapimouse.html)
dataset onto a Playwright page.
Useful when you need mouse movement that is statistically indistinguishable
from a real user — for ML-based bot-detection research, behavioral biometrics
prototyping, or replay-based test fixtures.
## Install
```bash
uv add human_mouse # or: pip install human_mouse
uv add "human_mouse[demo]" # also installs cloakbrowser for the example
```
## One-time dataset download
```python
import human_mouse as hm
hm.download_sapimouse("./data") # ~8 MB, no registration
```
This unzips SapiMouse to `./data/sapimouse/userN/...`.
## Quick start
```python
import human_mouse as hm
from playwright.sync_api import sync_playwright
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://example.com")
# one-shot: pick a real human trajectory matching the distance and replay it
seg = hm.replay_random(
page,
start=(100, 100),
end=(900, 500),
data_root="./data/sapimouse",
density=4, # 4x spatial upsample for smoother visuals
seed=42,
)
print(f"replayed {seg.user}/{seg.session}, {len(seg.points)} source points")
```
## Step-by-step API
For full control over which segment is picked and how it's processed:
```python
import human_mouse as hm
segs = hm.load_all_segments("./data/sapimouse")
seg = hm.pick_segments(
segs,
n=1,
target_distance=1000, # only match segments ~1000 px long
distance_tolerance=0.3, # ±30 %
max_path_ratio=2.0, # skip erratic meanderers
seed=42,
)[0]
points = hm.affine_warp(seg, (100, 100), (900, 500))
points = hm.upsample(points, factor=4)
hm.replay(page, points, speed=1.0)
```
## Public API
| Symbol | Purpose |
|---|---|
| `Segment` | dataclass with `.points`, `.start`, `.end`, `.straight_distance`, `.path_length`, `.path_ratio`, `.duration_ms` |
| `load_all_segments(data_root)` | scan SapiMouse, return every continuous Move-only segment ≥ 50 pts |
| `pick_segments(segments, n, ...)` | filter by distance / path-ratio / distinct-session, randomly choose `n` |
| `affine_warp(seg, start, end)` | translate + rotate + uniform-scale onto new endpoints (shape preserved) |
| `upsample(points, factor)` | linearly interpolate `factor-1` sub-points between every adjacent pair |
| `replay(page, points, speed=1.0)` | drive `page.mouse.move(...)` honoring the recorded `dt` |
| `replay_random(page, start, end, data_root, ...)` | one-shot: pick + warp + upsample + replay |
| `download_sapimouse(dest)` | download and unzip the dataset |
## Running the bundled example
The `examples/` folder ships a Playwright canvas page (`demo.html`) plus a
runner script that uses [CloakBrowser](https://github.com/CloakHQ/CloakBrowser):
```bash
uv add "human_mouse[demo]"
python -m human_mouse download ./sapimouse_data # one-time, ~8 MB
uv run python examples/cloakbrowser_demo.py sapi # one trajectory
uv run python examples/cloakbrowser_demo.py multi --n 10 # 10 overlaid
```
Outputs land in `./outputs/`:
- `sapi.png` + `sapi.json` — single trajectory screenshot and per-event coords
- `multi/overlay.png` + per-run JSONs + `summary.json`
## What `replay` is and isn't
**Is**: a deterministic replay of one real human's mouse path, warped to your
endpoints. The shape (curvature, hesitation, end-point fumbling) and the
timing (`dt` distribution) come straight from a real recording.
**Isn't**: a generator. It samples from a fixed dataset of ~4 000 segments.
For per-call novelty, randomize the seed; for true synthesis, look at
trajectory generative models (e.g. SapiAgent, DMTG).
## Dataset attribution
If you use SapiMouse data in published work, cite:
> Antal, M. et al. *SapiMouse: Mouse Dynamics-based User Authentication Using
> Deep Feature Learning*. IEEE SACI 2021.
## License
MIT.