Skip to main content
Glama

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
NameRequiredDescriptionDefault
target_idYesChrome target ID from interceptor_chrome_launch
selectorNoCSS selector to click (resolved via getBoundingClientRect)
xNoX coordinate (used if selector is not provided)
yNoY coordinate (used if selector is not provided)
buttonNoMouse button (default: left)left
click_countNoNumber of clicks (default: 1, use 2 for double-click)
move_duration_msNoBase duration for mouse movement (default: 600)

Implementation Reference

  • 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 } };
    }
  • 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) }),
            }],
          };
        }
      },
    );
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yfe404/proxy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server