Skip to main content
Surfsky adds Human.* commands to CDP for mouse, keyboard, scroll, drag, and touch input. Each command performs a complete interaction inside the browser session. For example, Human.click moves the cursor to the element, clicks it, and pauses briefly. Your script still needs to wait for page content and check the result of each action. Human commands do not guarantee that a site will accept a session. See Human behavior for action order and timing.

How it works

Surfsky generates input with a proprietary model of human movement. It does not use open-source humanization libraries or combine Bezier curves with Fitts’ law. Commands send events through the browser’s input pipeline. Cursor movement includes changes in speed, small corrections, and tremor, with deceleration near the target. Click positions vary within the element. Typing uses variable intervals and occasionally enters an incorrect key followed by Backspace. Drags may overshoot the target before correcting their position. On Android profiles, the commands produce taps and swipes with touch contact area and pressure.

Commands

All time values are in seconds. Coordinates are CSS pixels in the viewport. Every successful response includes success: true plus the fields listed for the command. A missing required parameter returns CDP error -32602; a failure during the action, such as an element that never appears, returns -32603 with the reason in the message.

Connect a page session

Start with the Playwright or Puppeteer quickstart. Once page is connected, create a page-level CDP session:
The examples below use this cdp object. No Human.enable call or profile setting is required. Stop the browser using the lifecycle in your quickstart when finished.

Click and move

Replace the selectors with elements on your page. Wait for the expected navigation or page state after submission.

Targeting

Human.click, Human.dblclick, and Human.moveTo accept either a CSS selector or both x and y. Prefer selectors when the layout can change; Surfsky picks a natural point inside the element for you. With a selector, the command waits for the element to have a visible box, scrolls it into the viewport if it is outside, then moves to it.

Human.click

Moves to the target, then presses and releases the button. Response: x, y, button.

Human.dblclick

Same targeting and parameters as Human.click, without clickCount. Response: x, y, button.

Human.moveTo

Moves the cursor to the target without pressing anything. Use it to hover, to open a menu, or to position the cursor before Human.mouseDown. Takes only the targeting parameters. Response: x, y.
On Android profiles a finger cannot hover, so Human.moveTo records the position and dispatches nothing. A successful response confirms the input was delivered. Check the page to confirm its effect.

Type text and press keys

Human.type

Types text into the currently focused element, one keystroke at a time. Click or focus the field first. It does not clear an existing value, and it does not take a selector. Response: text. Avoid logging typed secrets. Typing includes occasional corrected mistakes: a wrong adjacent key followed by Backspace. The final field value matches text, but a page that reacts to every input event will see the correction. Do not use Human.type for fields that reject Backspace or act on the first keystroke.

Human.press

Presses and releases one key. Response: key, delay.
Use the shortcut appropriate to the browser’s OS, such as Meta+A for a Mac fingerprint.

Scroll

Human.scroll

Scrolls by a relative distance as a series of eased wheel events. On Android profiles it becomes one or more swipes. Response: deltaX, deltaY, duration.

Human.wheel

Sends a single wheel step at the current cursor position, with no easing. Use it for one notch of a scroll wheel or to nudge a scrollable element under the cursor. Response: deltaX, deltaY.

Human.scrollIntoView

Scrolls until the element is inside the viewport. Does nothing if it already is. Response: selector, behavior.

Human.scrollTo

Scrolls to an absolute document position. Response: x, y, behavior.
A scroll can trigger lazy loading. Wait for the resulting content before reading it.

Drag and hold

Human.drag

Moves to the start point, presses the button, drags to the end point, and releases. Drags decelerate into the target and may overshoot and correct, which suits sliders and drag-and-drop targets. Response: x, y, button, where x and y are the release position.
If the drag fails part way, Surfsky releases the button before returning the error.

Human.mouseDown and Human.mouseUp

Press and release separately when you need a custom hold or a path with intermediate stops. Response for both: x, y, button. Human.mouseDown presses at x, y without moving there first. Call Human.moveTo with the same coordinates before it so the cursor arrives along a natural path. While the button is held, the cursor keeps a small tremor until Human.mouseUp. Release the button even if an intermediate action fails:

Android profiles

When the profile’s fingerprint is Android, Surfsky switches input to touch. The commands and parameters stay the same, and the following changes apply:
  • Human.click and Human.dblclick become taps. button and clickCount are ignored.
  • Human.moveTo records the target and sends no event.
  • Human.scroll, Human.wheel, Human.scrollIntoView, and Human.scrollTo become swipes. Long distances are split into several swipes with the finger lifting in between, so they take longer than duration.
  • Human.mouseDown, Human.mouseUp, and Human.drag become touch start, touch end, and a finger drag.
  • Human.type and Human.press send keyboard events as on desktop.

Selector and timing problems

Selectors are resolved in the main document. An element inside an iframe or shadow root does not resolve, and the error message says so. Use your framework’s frame or shadow-root support to find the element, then pass its viewport coordinates as x and y. If a click lands in the wrong place, inspect the page for overlays, scrolling, and layout changes. Recalculate coordinates after a resize or navigation. See debugging. Human timing values are in seconds. CAPTCHA timeouts and most Playwright timeouts are in milliseconds; do not copy those values between APIs.

Using the SDK

The Python and TypeScript browser APIs wrap these commands. Use them when you want browser actions without managing CDP sessions yourself.