v0.8MIT licensedBuilt on Playwright

Humanize the cursor.The typing.The pace.

The Playwright wrapper that gives browser automation a heartbeat. Real Bezier paths, real typing rhythm, real pre-click dwell — driven by four personalities you can extend, compose, or replace.

Bezier · jitter · dwell4 personalitiesDeterministic by seed
human.click()
submit
await human.click('#submit');travel

Live. Powered by @humanjs/core rerolls every cycle

Side by side

The click stays the same. Everything around it changes.

Same selector. Same Playwright underneath. The library only edits how it gets to the button — and how it leaves.

Playwright
page.click(selector)
instant jump0.0s
HumanJS
human.click(selector)
bezier · jitter · dwell0.0s
Playwright
ts
// Playwright — straight to the click
await page.click('button[type=submit]');

// Done. No hover, no path,
// no human signal whatsoever.
HumanJS
ts
// HumanJS — humanized click
import { createHuman } from '@humanjs/playwright';

const human = await createHuman(page, {
  personality: 'careful',
  seed: 'session-42',
});

await human.click('button[type=submit]');
// Bezier path · micro-jitter
// pre-click dwell · post-action settle

Try it

Stop reading. Move it yourself.

Click anywhere in the box. The cursor draws a real Bezier path to the point you picked — exactly the same code that drives human.click() in tests.

Personality
playground
personality: careful

Now the keyboard

Real rhythm. Real typos.

The cursor isn’t the only thing that gives an automation away. HumanJS types at the personality’s natural pace — with optional typos and the backspace recovery a real user would do without thinking.

Personality
human.type()
personality: careful
Live demonstration of HumanJS’s `human.type()` typing the phrase “Real keystrokes. Real rhythm. Real backspace recovery.” with the careful personality — including occasional typos and backspace recovery. Switch personality with the controls above to compare rhythms.

And the pace

The space between clicks. Worth modeling.

Real users pause to read before they click. HumanJS models that pause from word count and the personality’s reading speed — code reads slower than prose, scan mode skims, and `<pre>` tags auto-detect when you don’t specify.

Personality
human.read()
personality: careful
Live demonstration of HumanJS’s `human.read()` modeling the dwell time a real person would take to read a passage with the carefulpersonality. Each word lights up as the reader’s attention moves through, paced by `personality.reading.wpm` scaled by personality and speed-mode factors. Switch personality with the controls above to compare reading rhythms.

And the motion between

Real scrolling is a wave. Not a jump.

Robotic scroll fires one big delta. Humans roll a wheel — accelerate, peak, decelerate, occasionally pause, sometimes overshoot. `human.scroll()` models that from a deterministic planner, and `distracted` will pass the target and correct back the way real eyes do.

Personality
human.scroll()
personality: careful
Live demonstration of HumanJS’s `human.scroll()` driving the same `planScroll` planner the Playwright adapter walks against `page.mouse.wheel`. The bounded list scrolls from top to bottom with a bell-curve velocity profile, mid-scroll pauses, and (on the distracted personality) an overshoot-and-correct phase, then returns to the top and repeats. Switch personality with the controls above to compare scroll rhythms.

Bottled motion

Every session, captured. Every action, observable.

`human.record()` wraps any session — `toVideo()` writes an mp4 of what the user actually saw, `toTimeline()` writes the structured action log AI agents and tests can replay. Drag the scrubber to step through a captured session, or switch personalities to see how each shapes the recording.

Personality
REC·humanjs-careful.mp4
0.0s / 11.8s
CapturedSession ready.
rec.toVideo()
  • click0.3s
  • type1.4s
  • scroll5.0s
  • read6.6s
  • end of recording

Three audiences

Built for the people who can't afford to be obvious.

AI agent builders

Playwright MCP and custom agents — without the giveaway robotic clicks that flag your agent as a bot.

MCP · Playwright · agents

QA engineers

Catch race conditions that only surface at real human pace. One flag flips to instant mode for fast CI.

Playwright · Vitest · CI

Demo & tutorial creators

Record polished walkthroughs without driving the cursor by hand. Same script, smoother output.

Loom · YouTube · screencasts

Under the hood

Realism, all the way down.

Bezier mouse paths

Curved trajectories with overshoot, sub-pixel jitter, and bell-curve velocity. No straight lines, no instant teleports.

Deterministic

Same seed, same trajectory. Snapshot-test friendly.

speed: 'instant'

One flag bypasses all humanization. Tests stay fast in CI.

Typing rhythm

Per-character timing with typo + backspace recovery.

Reading dwell

human.read(text) pauses based on word count.

Plugin system

Extend personalities, actions, primitives. Day-one architecture.

The lab

Four shapes of human. Mess with them.

Personalities are pure data. Pick one, drag the sliders, watch the cursor change live. Then ship that config as a preset of your own.

careful

Reads everything twice.

High dwell, medium curvature. Slow, deliberate trajectories.

travel
450ms
per 1000px
curvature
0.40
0 – 1
jitter
±15%
of travel

live from @humanjs/core

Live overrides

{ personality: 'careful',}

Get started

One install. One line of code different.

HumanJS wraps Playwright. Same selectors, same locator API. The only thing that changes is what happens between two points.

01Install

$ pnpm add @humanjs/playwright

02Use it

example.ts
ts
import { chromium } from 'playwright';
import { createHuman } from '@humanjs/playwright';

const browser = await chromium.launch();
const page = await browser.newPage();

const human = await createHuman(page, {
  personality: 'careful',
  seed: 'session-42',
});

await human.goto('https://example.com');
await human.click('button[type=submit]');

await browser.close();

03Or drive it from an AI agent

MCP — Claude Code, Cursor, Codex…
ts
claude mcp add humanjs -- npx -y @humanjs/mcp

· Designed scope

Small surface. Big honesty.

HumanJS humanizes the timing between two points. It doesn't pretend to be a full anti-detection stack. Here's what we ship — and what we leave to others.

MIT licensedlatest v0.8

In v1

  • Bezier mouse paths with overshoot & micro-jitter
  • Typing rhythm with typo + backspace recovery
  • Reading dwell tied to word count
  • Four personalities, composable & extendable
  • Deterministic by seed (snapshot-friendly)
  • Plugin contract from day one

Out of scope

  • Browser fingerprint masking
  • TLS / request-pattern stealth
  • CAPTCHA solving or bypass
  • Proxy rotation & IP management
  • Puppeteer & Selenium adapters (later)