humanizer_click
Simulates human-like mouse clicks on web elements or coordinates with configurable timing, button selection, and click patterns for automated browser interactions.
Instructions
Move to an element (by CSS selector) or coordinates, then click with human-like timing. Supports left/right/middle button and multi-click (double-click, etc.).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| target_id | Yes | Chrome target ID from interceptor_chrome_launch | |
| selector | No | CSS selector to click (resolved via getBoundingClientRect) | |
| x | No | X coordinate (used if selector is not provided) | |
| y | No | Y coordinate (used if selector is not provided) | |
| button | No | Mouse button (default: left) | left |
| click_count | No | Number of clicks (default: 1, use 2 for double-click) | |
| move_duration_ms | No | Base duration for mouse movement (default: 600) |
Implementation Reference
- src/humanizer/engine.ts:240-324 (handler)The `click` method in `HumanizerEngine` handles the logic for simulating a human-like click by resolving selector or coordinate targets, moving to the target, and dispatching mousePressed and mouseReleased events via CDP.
async click( targetId: string, opts: { selector?: string; x?: number; y?: number; button?: "left" | "right" | "middle"; clickCount?: number; moveDurationMs?: number; } = {}, ): Promise<{ totalMs: number; eventsDispatched: number; clickedAt: Point }> { const state = await this.getSession(targetId); const button = opts.button ?? "left"; const clickCount = opts.clickCount ?? 1; let targetX: number; let targetY: number; if (opts.selector) { const bounds = await resolveSelectorBounds(state.session, opts.selector); const center: Point = { x: bounds.x + bounds.width / 2, y: bounds.y + bounds.height / 2, }; const offset = addRandomOffset(center, bounds); targetX = offset.x; targetY = offset.y; } else if (opts.x !== undefined && opts.y !== undefined) { targetX = opts.x; targetY = opts.y; } else { throw new Error("Either selector or x+y coordinates are required."); } // Move to target const moveResult = await this.moveMouse(targetId, targetX, targetY, opts.moveDurationMs); let eventsDispatched = moveResult.eventsDispatched; let totalMs = moveResult.totalMs; const cdpButton = button === "right" ? "right" : button === "middle" ? "middle" : "left"; const buttons = button === "right" ? 2 : button === "middle" ? 4 : 1; // Small pause before clicking (human hesitation) const preClickDelay = Math.round(rand(30, 80)); await sleep(preClickDelay); totalMs += preClickDelay; for (let c = 0; c < clickCount; c++) { // mousePressed await state.session.send("Input.dispatchMouseEvent", { type: "mousePressed", x: targetX, y: targetY, button: cdpButton, buttons, clickCount: c + 1, }); eventsDispatched++; // Brief hold const holdMs = Math.round(rand(40, 100)); await sleep(holdMs); totalMs += holdMs; // mouseReleased await state.session.send("Input.dispatchMouseEvent", { type: "mouseReleased", x: targetX, y: targetY, button: cdpButton, buttons: 0, clickCount: c + 1, }); eventsDispatched++; // Inter-click pause for multi-click if (c < clickCount - 1) { const interClickMs = Math.round(rand(50, 120)); await sleep(interClickMs); totalMs += interClickMs; } } return { totalMs, eventsDispatched, clickedAt: { x: targetX, y: targetY } }; } - src/tools/humanizer.ts:64-116 (registration)The tool `humanizer_click` is registered here in `src/tools/humanizer.ts` with its Zod schema and tool handler implementation.
server.tool( "humanizer_click", "Move to an element (by CSS selector) or coordinates, then click with human-like timing. " + "Supports left/right/middle button and multi-click (double-click, etc.).", { target_id: z.string().describe("Chrome target ID from interceptor_chrome_launch"), selector: z.string().optional().describe("CSS selector to click (resolved via getBoundingClientRect)"), x: z.number().optional().describe("X coordinate (used if selector is not provided)"), y: z.number().optional().describe("Y coordinate (used if selector is not provided)"), button: z.enum(["left", "right", "middle"]).optional().default("left") .describe("Mouse button (default: left)"), click_count: z.number().optional().default(1) .describe("Number of clicks (default: 1, use 2 for double-click)"), move_duration_ms: z.number().optional().default(600) .describe("Base duration for mouse movement (default: 600)"), }, async ({ target_id, selector, x, y, button, click_count, move_duration_ms }) => { try { const result = await humanizerEngine.click(target_id, { selector, x, y, button, clickCount: click_count, moveDurationMs: move_duration_ms, }); return { content: [{ type: "text", text: JSON.stringify({ status: "success", target_id, action: "click", clicked_at: result.clickedAt, button, click_count, stats: { total_ms: result.totalMs, events_dispatched: result.eventsDispatched, }, }), }], }; } catch (e) { return { content: [{ type: "text", text: JSON.stringify({ status: "error", target_id, action: "click", error: errorToString(e) }), }], }; } }, );