- README install section now reflects reality (git URL, not PyPI) - Add a Source link at the top and a Development section at the bottom - Update Running-the-bundled-example to clone-then-uv-sync flow since examples/ is sdist-only - pyproject.toml: replace github.com/your-org placeholder with the actual git.vercanti.com URL Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
human_mouse
Replay real human mouse trajectories from the SapiMouse 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.
- Source: https://git.vercanti.com/yellowdog/human_mouse
- License: MIT
Install
The package is not on PyPI yet. Install directly from the git remote:
# core only
uv add "human_mouse @ git+https://git.vercanti.com/yellowdog/human_mouse.git"
# with the bundled CloakBrowser example
uv add "human_mouse[demo] @ git+https://git.vercanti.com/yellowdog/human_mouse.git"
Or pin to a specific commit / tag:
uv add "human_mouse @ git+https://git.vercanti.com/yellowdog/human_mouse.git@v0.1.0"
pip install works with the same git+https://... URL.
One-time dataset download
import human_mouse as hm
hm.download_sapimouse("./data") # ~8 MB, no registration
This unzips SapiMouse to ./data/sapimouse/userN/....
Quick start
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:
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.
You need a local checkout for this since examples/ ships only in the sdist:
git clone https://git.vercanti.com/yellowdog/human_mouse.git
cd human_mouse
uv sync --extra 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 coordsmulti/overlay.png+ per-run JSONs +summary.json
Development
git clone https://git.vercanti.com/yellowdog/human_mouse.git
cd human_mouse
uv sync --all-extras # core + [demo] + [dev]
uv run pytest # 23 tests, ~40s with SapiMouse present
uv build # produces wheel + sdist in dist/
Integration tests auto-skip when sapimouse_data/sapimouse/ is missing, so
the core 10 unit tests run on a fresh clone without the dataset.
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.