> 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.

# goTo

> Navigate to a specified URL.

The `goTo` action navigates the browser to a specified URL. This is typically used to start a test at a specific page or navigate between pages during a test.

You can specify the target URL directly as a string, or use an object for more options:

* **String Shorthand:** Provide the full URL, a path (starting with `/`), or a variable reference directly as the value for the `goTo` key. If a path is provided, it navigates relative to the current URL or the global `origin` if set in the configuration.
* **Object Format:** Use an object with the following properties:
  * `url`: (Required) The URL to navigate to. Can be a full URL, a path, or a variable reference.
  * `origin`: (Optional) Protocol and domain prepended to `url` when `url` is a path. Overrides the global `origin` if set.
  * `params`: (Optional) Query parameters to append to the resolved URL. Merged with config-level `originParams`.
  * `surface`: (Optional) The browser (session, window, or tab) to navigate. Omit to navigate the active tab. Naming a browser that isn't open yet opens it. To open a browser with explicit launch options (headless, window size, viewport) before navigating, use [`startSurface`](startsurface).
  * `newTab` / `newWindow`: (Optional) Open the URL in a new tab or window instead of navigating the current one. `goTo` is the only action that opens tabs and windows.

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

## Examples

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

### Navigate to a full URL (string shorthand)

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to example.com.",
          "goTo": "https://example.com"
        }
      ]
    }
  ]
}
```

### Navigate to a relative path (string shorthand)

Assumes the browser is currently at `https://example.com` or a global `origin` is set.

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to the /about path.",
          "goTo": "/about"
        }
      ]
    }
  ]
}
```

### Navigate using an object with a full URL

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to example.com using object format.",
          "goTo": {
            "url": "https://example.com"
          }
        }
      ]
    }
  ]
}
```

### Navigate using an object with a relative path and specific origin

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to Google search using a specific origin.",
          "goTo": {
            "url": "/search",
            "origin": "https://www.google.com"
          }
        }
      ]
    }
  ]
}
```

## Query parameters

You can append query parameters to a URL using the `params` option. This is useful for authentication tokens or tracking parameters.

* **Step-level `params`:** An object specifying query parameters to append to the URL. Applies to all URLs, both relative and absolute. Values support environment variable substitution with `$VAR` syntax.
* **Config-level `originParams`:** Default query parameters in your configuration file that apply to relative URLs resolved against `origin`. Step-level `params` merge on top, with step keys taking precedence on collision.

When your URL contains a fragment such as `/page#section`, query parameters are inserted before the fragment, giving `/page?token=value#section`.

> **Warning**
>
> Values in `params` and `originParams` are embedded directly in request URLs and appear in test results, logs, and reports. Avoid storing long-lived secrets in these fields.

### Append query parameters to a URL

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to dashboard with testing token.",
          "goTo": {
            "url": "/dashboard",
            "origin": "https://my-app.com",
            "params": {
              "__clerk_testing_token": "$CLERK_TESTING_TOKEN"
            }
          }
        }
      ]
    }
  ]
}
```

### Use config-level default parameters

Set `originParams` in your configuration file to avoid repeating parameters on every step. For example, when testing a Clerk-protected application, set the testing token once:

**Configuration file:**

```json
{
  "origin": "https://my-app.com",
  "originParams": {
    "__clerk_testing_token": "$CLERK_TESTING_TOKEN"
  }
}
```

**Test specification:**

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to dashboard (testing token applied automatically).",
          "goTo": "/dashboard"
        }
      ]
    }
  ]
}
```

## Tabs, windows, and browsers

`goTo` is the only action that opens new tabs, windows, and browsers. Name what you open, then any later step can act in it with a [`surface`](/docs/test-docs/multiple-tabs-and-windows) reference.

* `newTab`: Open the URL in a new tab of the target window and focus it. `true` opens an anonymous tab; a string (or `{ "name": … }`) names the tab. `false` disables.
* `newWindow`: Open the URL in a new window and focus it. `true`, a name string, or `{ "name": …, "tab": … }`, where `tab` names the window's first tab. `false` disables.
* `newTab` and `newWindow` are mutually exclusive on one step.
* `surface`: Without an opener, this selects the browser, window, or tab to navigate. It opens the browser if it isn't running yet. With `newTab`, it selects the window the tab opens in.

### Open a second browser

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Open a second, named browser session for the admin account.",
          "goTo": {
            "url": "https://my-app.com/admin",
            "surface": { "browser": "firefox", "name": "admin" }
          }
        },
        {
          "description": "A bare engine keyword opens (or selects) a browser of that engine.",
          "goTo": { "url": "https://my-app.com", "surface": "chrome" }
        }
      ]
    }
  ]
}
```

### Open a named tab, then act in it

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Open the checkout in a new tab named 'cart'.",
          "goTo": {
            "url": "https://my-app.com/checkout",
            "newTab": "cart"
          }
        },
        {
          "description": "Click in the cart tab by name.",
          "click": {
            "elementText": "Place order",
            "surface": { "browser": "chrome", "tab": "cart" }
          }
        }
      ]
    }
  ]
}
```

### Open a named window with a named first tab

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Open the admin console in its own window.",
          "goTo": {
            "url": "https://my-app.com/admin",
            "newWindow": { "name": "admin", "tab": "overview" }
          }
        }
      ]
    }
  ]
}
```

### Navigate an existing tab or window

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate the admin window to the orders page.",
          "goTo": {
            "url": "https://my-app.com/orders",
            "surface": { "browser": "chrome", "window": "admin" }
          }
        }
      ]
    }
  ]
}
```

See [Test across multiple tabs, windows, and browsers](/docs/test-docs/multiple-tabs-and-windows) for the full selector grammar. It covers names, indexes, `-1` for newest, and title and URL criteria. It also covers addressing tabs a page opens itself, and driving multiple browsers at once.

## Wait conditions

The `goTo` action supports advanced waiting conditions after navigation to ensure pages are fully loaded and ready before the next step runs.

When using the object format, you can configure:

* `timeout`: (Optional) Maximum time in milliseconds to wait for all conditions to be met. If exceeded, the goTo action fails (default: 30000).
* `waitUntil`: (Optional) Object specifying conditions to wait for:
  * `networkIdleTime`: (Optional) Wait for network activity to be idle, meaning no new requests, for this duration in milliseconds. This check always runs and you can't skip it. Set it to `0` to treat the page as network-idle as soon as the first check completes, rather than waiting for a quiet period. Defaults to `500`.
  * `domIdleTime`: (Optional) Wait for DOM mutations to stop for this duration in milliseconds. This check always runs; you can't skip it. Set it to `0` to treat the DOM as stable as soon as the first check completes rather than waiting for a quiet period (default: 1000).
* `find`: (Optional) Wait for a specific element to be present in the DOM. At least one of `selector` or `elementText` must be specified.
  * `selector`: (Optional) CSS selector for the element to wait for.
  * `elementText`: (Optional) Display text of the element to wait for. Doc Detective matches this against the element's full visible text with whitespace normalized, so text that a framework splits across several nodes still matches. To match a substring with a regular expression instead of the whole text, wrap the value in slashes (`/pattern/`). See [How text matching works](/docs/actions/find#how-text-matching-works).

### Wait for network idle

Navigate to a page and wait for network activity to settle.

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate and wait for network idle.",
          "goTo": {
            "url": "https://www.example.com",
            "waitUntil": {
              "networkIdleTime": 500
            }
          }
        }
      ]
    }
  ]
}
```

### Wait for a specific element

Navigate to a dashboard and wait for a specific element to appear.

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to dashboard and wait for it to load.",
          "goTo": {
            "url": "https://www.example.com/dashboard",
            "waitUntil": {
              "find": {
                "selector": "[data-testid='dashboard-loaded']"
              }
            }
          }
        }
      ]
    }
  ]
}
```

### Wait for element with text

Wait for an element with specific text to appear.

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to status page and wait for operational message.",
          "goTo": {
            "url": "https://www.example.com/status",
            "waitUntil": {
              "find": {
                "elementText": "System operational"
              }
            }
          }
        }
      ]
    }
  ]
}
```

### Combine multiple wait conditions

Use multiple wait conditions together with a custom timeout.

```json
{
  "tests": [
    {
      "steps": [
        {
          "description": "Navigate to app with comprehensive wait conditions.",
          "goTo": {
            "url": "https://www.example.com/app",
              "timeout": 60000,
            "waitUntil": {
              "networkIdleTime": 500,
              "domIdleTime": 1000,
              "find": {
                "selector": ".main-content",
                "elementText": "Dashboard"
              }
            }
          }
        }
      ]
    }
  ]
}
```