> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.doc-detective.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.doc-detective.com/_mcp/server.

# click

> Click or tap an element on the page.

The `click` action allows you to click or tap an element on the page. You can specify which mouse button to use and target elements using text or selectors.

The `click` action works in several ways:

* **String Shorthand:** The display text or selector of the element to find and click.
* **Object Format:** Use an object with detailed properties for more control over the click action.

To find an element before clicking it, consider the [`find`](/docs/actions/find) action. It locates elements and optionally clicks them in a single step.

**Note:** A `click` action with no target, meaning no element text or selector, clicks the active element or the element at the current cursor position.

## Properties

When using the object format, you can specify:

* `button`: (Optional) Kind of click to perform. Can be `"left"`, `"right"`, or `"middle"`. Default is `"left"`.
* `duration`: (Optional) How long to hold the press, in milliseconds. It's a long-press on mobile app surfaces and a press-and-hold of the primary button on desktop apps. On browsers it's a press-and-hold of the given `button`. Omit it for a normal click. A long-press on an app surface is primary-button only, so `duration` with a non-left `button` fails the step. On browsers, a held click needs the W3C actions endpoint. Like non-left buttons, it's desktop-browser-only.
* `selector`: (Optional) [CSS selector](/docs/selectors/css) or [XPath selector](/docs/selectors/xpath) of the element to click. If combined with `elementText`, the element must match both the text and the selector.
* `elementText`: (Optional) Display text of the element to click. If combined with `selector`, the element must match both the text and the selector.
* `surface`: (Optional) The browser session, window, or tab the element lives in, such as `{ "browser": "chrome", "tab": "cart" }` or a named browser `{ "browser": "firefox", "name": "admin" }`. It can also be the [native app surface](/docs/actions/startsurface) the element lives in, such as `{ "app": "notepad" }`. Omit it to act on the active surface, the most recently opened, focused, or explicitly targeted one, whether a browser tab or an app window. Specifying a surface switches the active surface for the steps that follow. On an app surface, `elementText`, `elementId`, and `elementAria` map to native controls. `selector` there accepts a native locator, either XPath or a `~`-prefixed accessibility ID, instead of a CSS selector. See [Test across multiple tabs, windows, and browsers](/docs/test-docs/multiple-tabs-and-windows) and [Target an app surface](/docs/actions/startsurface#target-an-app-surface).

**Outputs:** when you target an element by text or selector, the action exposes `outputs.found`, a boolean indicating whether the element was located. To capture it for later steps, use the step-level `variables` object with the expression `$$found`.

> For comprehensive options, see the full [`click`](/reference/schemas/click) reference.

## Examples

Here are a few ways you might use the `click` action:

### Click by element text (string shorthand)

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Click on an element with text 'Submit'",
          "click": "Submit"
        }
      ]
    }
  ]
}
```

### Click by selector (string shorthand)

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Click on an element matching the CSS selector",
          "click": "#submit-button"
        }
      ]
    }
  ]
}
```

### Click an element by text (object format)

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Left-click on a button with specific text",
          "click": {
            "elementText": "Submit",
            "button": "left"
          }
        }
      ]
    }
  ]
}
```

### Click an element by selector (object format)

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Middle-click on an element with a specific selector",
          "click": {
            "selector": "#open-in-new-tab",
            "button": "middle"
          }
        }
      ]
    }
  ]
}
```

### Click an element by both selector and text

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Click on a specific element matching both selector and text",
          "click": {
            "selector": ".btn",
            "elementText": "Download",
            "button": "left"
          }
        }
      ]
    }
  ]
}
```

### Long-press an element on a mobile app surface

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Touch and hold a message for 800ms",
          "click": {
            "elementText": "Message",
            "duration": 800,
            "surface": { "app": "myapp" }
          }
        }
      ]
    }
  ]
}
```

## Mobile app surfaces

On an app surface, `click` is a tap, and `duration` makes it a long-press. The `button` field (`left`, `right`, or `middle`) works where the platform's driver supports it. Windows honors all three. macOS honors right-click and rejects middle-click, which the Mac2 driver can't do. Android and iOS reject any non-left button with a clear message, because touch input has no right or middle button. On Windows, plain left clicks activate the element through the UI Automation Invoke pattern. That's coordinate-free, so display scaling can't misdirect them. They fall back to a physical click for elements that don't support it. Non-left and held clicks stay physical. To click in a specific window of the app, add a `window` selector. See [App windows](find#app-windows). Two more patterns are worth knowing:

* **Permission dialogs are just elements.** When your documentation walks the reader through granting a permission, click the dialog's button like any other element: `{ "click": { "elementText": "Allow", "surface": { "app": "myapp" } } }`. System dialogs expose their buttons through the platform accessibility tree, so `elementText` matches them.
* **When the dialog isn't the point**, suppress it at session start instead of scripting around it. Pass the driver's own knob through `startSurface.driverOptions`, such as `{ "driverOptions": { "appium:autoGrantPermissions": true } }` on Android. Use this when the procedure you're testing starts *after* the reader grants permissions.

## Related Actions

* [`find`](/docs/actions/find): Find an element and optionally interact with it
* [`type`](/docs/actions/type): Type text or special keys
* [`swipe`](/docs/actions/swipe): Swipe or scroll a surface