> ## Documentation Index
> Fetch the complete documentation index at: https://checkly-422f444a-herve-close-confirmed-docs-gaps.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser Check Construct

> Learn how to configure browser checks with the Checkly CLI.

<Tip>
  Learn more about Browser Checks in [the Browser Checks overview](/detect/synthetic-monitoring/browser-checks/overview).
</Tip>

Use Browser Checks to run end-to-end tests with Playwright. The examples below show how to configure browser checks for different testing scenarios.

<Accordion title="Prerequisites">
  Before creating Browser Checks, ensure you have:

  * An initialized Checkly CLI project
  * A public website you want to monitor
  * Understanding of [Playwright test syntax and structure](/learn/playwright/overview)

  For additional setup information, see [CLI overview](/cli/overview).
</Accordion>

<CodeGroup>
  ```ts Basic Example theme={null}
  import { BrowserCheck, Frequency } from "checkly/constructs"
  import * as path from "path"

  new BrowserCheck("browser-check-1", {
    name: "Browser check #1",
    description: "Loads the **home page** and asserts key elements are visible.",
    frequency: Frequency.EVERY_10M,
    locations: ["us-east-1", "eu-west-1"],
    code: {
      entrypoint: path.join(__dirname, "home.spec.ts"),
    },
  })
  ```

  ```ts Advanced Example theme={null}
  import { BrowserCheck, Frequency } from "checkly/constructs"
  import { secret } from "checkly/util"
  import * as path from "path"

  new BrowserCheck("advanced-browser-check", {
    name: "Advanced Browser Check",
    description: "Loads the **home page** and asserts key elements are visible.",
    activated: true,
    frequency: Frequency.EVERY_5M,
    locations: ["us-east-1", "eu-west-1"],
    tags: ["e2e", "critical-path"],
    runtimeId: "2025.04",
    environmentVariables: [
      { key: "TEST_USERNAME", value: "testuser" },
      { key: "TEST_PASSWORD", value: secret("TEST_PASSWORD"), secret: true },
    ],
    code: {
      entrypoint: path.join(__dirname, "advanced-flow.spec.ts"),
    },
  })
  ```
</CodeGroup>

## Configuration

The Browser Check configuration consists of specific Browser Check options and inherited general check options.

<Tabs>
  <Tab title="Browser Check">
    | Parameter | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `code` | `object` | ✅ | - | The Playwright test code |
  </Tab>

  <Tab title="General Check">
    | Property | Type | Required | Default | Description |
    | - | - | - | - | - |
    | `name` | `string` | ✅ | - | Friendly name for your check |
    | `description` | `string` | ❌ | `null` | A description of the check. Supports markdown. Max 500 characters |
    | `intent` | `CheckIntent` | ❌ | - | Structured guidance for root cause analysis and check repair. See [General Check Options](#general-check-options). |
    | `aiAutoRepairEnabled` | `boolean \| null` | ❌ | - | Enable or disable automatic repair, or inherit the account setting. Requires CLI 9.4.0 or later. See [General Check Options](#general-check-options). |
    | `activated` | `boolean` | ❌ | `true` | Whether the check is enabled |
    | `alertChannels` | `AlertChannel[]` | ❌ | `[]` | Array of AlertChannel objects for notifications |
    | `alertEscalationPolicy` | `AlertEscalationPolicy` | ❌ | - | Advanced alert settings |
    | `environmentVariables` | `object[]` | ❌ | `[]` | Check-level environment variables |
    | `frequency` | `Frequency` | ❌ | - | How often to run your check |
    | `group` | `CheckGroup` | ❌ | - | The CheckGroup this check belongs to |
    | `locations` | `string[]` | ❌ | `[]` | Public locations for this monitor/check |
    | `muted` | `boolean` | ❌ | `false` | Whether alert notifications are muted |
    | `privateLocations` | `string[]` | ❌ | `[]` | Private Location slugs |
    | `retryStrategy` | `RetryStrategy` | ❌ | - | Strategy for configured retries |
    | `runtimeId` | `string` | ❌ | - | The ID of the runtime to use |
    | `runParallel` | `boolean` | ❌ | `false` | Whether to run checks in parallel across locations |
    | `tags` | `string[]` | ❌ | `[]` | Tags to organize checks/monitors |
    | `testOnly` | `boolean` | ❌ | `false` | Only run with test, not during deploy |
    | `triggerIncident` | `IncidentTrigger` | ❌ | - | Create and resolve an incident based on the check's alert configuration |
  </Tab>
</Tabs>

### Browser Check Options

<ResponseField name="code" type="object" required>
  The Playwright test code that defines how to execute your end-to-end browser monitor. This is the core component of any browser check.

  **Usage:**

  ```ts theme={null}
  // Using file reference
  code: {
    entrypoint: path.join(__dirname, "login-flow.spec.ts")
  }

  // Using inline content
  code: {
    content: `
      import { test, expect } from '@playwright/test'

      test("homepage loads", async ({ page }) => {
        await page.goto("https://example.com");
        await expect(page).toHaveTitle(/Example/);
      });
    `
  }
  ```

  **Parameters:**

  | Parameter | Type | Required | Description |
  | - | - | - | - |
  | `entrypoint` | `string` | ❌ | Path to a `.spec.js` or `.spec.ts` file containing the Playwright test |
  | `content` | `string` | ❌ | Inline JavaScript/TypeScript code as a string |

  <Info>
    You must provide either `entrypoint` or `content`, but not both.
  </Info>

  **Examples:**

  <CodeGroup>
    ```ts File Reference theme={null}
    new BrowserCheck("login-flow-check", {
      name: "User Login Flow",
      code: {
        entrypoint: path.join(__dirname, "tests/login.spec.ts"),
      },
    })
    ```

    ```ts Inline Content theme={null}
    new BrowserCheck("quick-test", {
      name: "Quick Homepage Test",
      code: {
        content: `
          import { test, expect } from '@playwright/test'

          test('homepage loads correctly', async ({ page }) => {
            await page.goto('https://example.com')
            await expect(page).toHaveTitle(/Example/)
            await expect(page.locator('h1')).toContainText('Welcome')
          })
        `,
      },
    })
    ```

    ```ts Complex Test File theme={null}
    import { secret } from "checkly/util"

    new BrowserCheck("e2e-purchase", {
      name: "E-commerce Purchase Flow",
      code: {
        entrypoint: path.join(__dirname, "tests/purchase-flow.spec.ts"),
      },
      environmentVariables: [
        { key: "TEST_USER_EMAIL", value: "test@example.com" },
        { key: "TEST_PASSWORD", value: secret("TEST_PASSWORD"), secret: true },
      ],
    })
    ```
  </CodeGroup>

  **Use cases**: E2E testing, user journey validation, performance testing, visual regression testing.
</ResponseField>

### General Check Options

<ResponseField name="name" type="string" required>
  Friendly name for your Browser Check that will be displayed in the Checkly dashboard and used in notifications.

  **Usage:**

  ```ts highlight={2} theme={null}
  new BrowserCheck("my-check", {
    name: "User Login Flow Test",
    /* More options... */
  })
  ```
</ResponseField>

<ResponseField name="frequency" type="Frequency">
  How often the Browser Check should run. Use the `Frequency` enum to set the check interval.

  **Usage:**

  ```ts highlight={5} theme={null}
  import { Frequency } from 'checkly/constructs'

  new BrowserCheck("my-check", {
    name: "My Browser Check",
    frequency: Frequency.EVERY_5M,
    /* More options... */
  })
  ```

  **Examples:**

  <CodeGroup>
    ```ts High Frequency theme={null}
    // For critical user journeys
    new BrowserCheck("critical-login", {
      name: "Critical Login Flow",
      frequency: Frequency.EVERY_1M, // Every minute
      tags: ["critical", "high-priority"],
      /* More options... */
    })
    ```

    ```ts Standard Frequency theme={null}
    // For regular monitoring
    new BrowserCheck("standard-check", {
      name: "Standard User Flow",
      frequency: Frequency.EVERY_10M, // Every 10 minutes
      tags: ["monitoring"],
      /* More options... */
    })
    ```
  </CodeGroup>

  **Available frequencies**: `EVERY_1M`, `EVERY_2M`, `EVERY_5M`, `EVERY_10M`, `EVERY_15M`, `EVERY_30M`, `EVERY_1H`, `EVERY_2H`, `EVERY_6H`, `EVERY_12H`, `EVERY_24H`
</ResponseField>

<ResponseField name="runtimeId" type="string">
  The Checkly runtime version used to execute the Browser Check. Runtimes are managed execution environments for Browser and Multistep Checks. They include fixed Checkly-provided dependencies, such as Playwright, browser binaries, and runtime libraries.

  Use `runtimeId` for Browser Checks and Multistep Checks. For Playwright Check Suites, use [`engine`](/constructs/playwright-check#engine) instead to select the JavaScript engine version that runs your own Playwright project.

  **Usage:**

  ```ts highlight={3} theme={null}
  new BrowserCheck("my-check", {
    name: "My Browser Check",
    runtimeId: "2025.04",
    /* More options... */
  })
  ```

  <Tip>Learn more about [Checkly runtimes in the general documentation](/platform/runtimes/overview).</Tip>
</ResponseField>

<ResponseField name="locations" type="string[]" default="[]">
  Array of public location codes where the Browser Check should run. Multiple locations provide geographic coverage and redundancy.

  **Usage:**

  ```ts highlight={3} theme={null}
  new BrowserCheck("my-check", {
    name: "My Browser Check",
    locations: ["us-east-1", "eu-west-1", "ap-southeast-1"],
    /* More options... */
  })
  ```

  **Examples:**

  <CodeGroup>
    ```ts Global Coverage theme={null}
    // Comprehensive global monitoring
    new BrowserCheck("global-check", {
      name: "Global User Experience",
      locations: [
        "us-east-1", // N. Virginia
        "us-west-1", // N. California
        "eu-west-1", // Ireland
        "ap-southeast-1", // Singapore
        "ap-northeast-1", // Tokyo
      ],
      /* More options... */
    })
    ```

    ```ts Regional Focus theme={null}
    // Focus on specific regions
    new BrowserCheck("europe-check", {
      name: "European User Flow",
      locations: ["eu-west-1", "eu-central-1"],
      /* More options... */
    })
    ```
  </CodeGroup>

  **Use cases**: Global user experience monitoring, regional performance testing, compliance requirements.
</ResponseField>

<ResponseField name="activated" type="boolean" default="true">
  Whether the browser check is enabled and will run according to its schedule.

  **Usage:**

  ```ts highlight={3} theme={null}
  new BrowserCheck("my-check", {
    name: "My Browser Check",
    activated: false, // Disabled check
    /* More options... */
  })
  ```
</ResponseField>

<ResponseField name="tags" type="string[]" default="[]">
  Array of tags to organize and categorize your Browser Checks in the Checkly infrastructure.

  **Usage:**

  ```ts highlight={3} theme={null}
  new BrowserCheck("my-check", {
    name: "My Browser Check",
    tags: ["e2e", "critical-path", "user-journey"],
    /* More options... */
  })
  ```

  **Examples:**

  <CodeGroup>
    ```ts Functional Tags theme={null}
    new BrowserCheck("login-test", {
      name: "User Authentication",
      tags: ["authentication", "login", "security"],
      code: { entrypoint: path.join(__dirname, "auth.spec.ts") },
      /* More options... */
    })
    ```

    ```ts Priority Tags theme={null}
    new BrowserCheck("checkout-flow", {
      name: "Checkout Process",
      tags: ["critical", "revenue", "high-priority"],
      code: { entrypoint: path.join(__dirname, "checkout.spec.ts") },
      /* More options... */
    })
    ```

    ```ts Environment Tags theme={null}
    new BrowserCheck("staging-test", {
      name: "Staging Environment Test",
      tags: ["staging", "pre-production", "validation"],
      /* More options... */
    })
    ```
  </CodeGroup>

  **Use cases**: Organization, filtering, alerting rules, reporting.
</ResponseField>

<ResponseField name="environmentVariables" type="object[]" default="[]">
  Check-level environment variables that will be available during test execution. Useful for test configuration and sensitive data.

  **Usage:**

  ```ts highlight={5-8} theme={null}
  import { secret } from "checkly/util"

  new BrowserCheck("my-check", {
    name: "My Browser Check",
    environmentVariables: [
      { key: "TEST_USERNAME", value: "testuser@example.com" },
      { key: "TEST_PASSWORD", value: secret("TEST_PASSWORD"), secret: true },
    ],
    /* More options... */
  })
  ```

  **Parameters:**

  | Parameter | Type | Required | Description |
  | - | - | - | - |
  | `key` | `string` | ✅ | Environment variable name |
  | `value` | `string` | ✅ | Environment variable value |
  | `secret` | `boolean` | ❌ | Whether the value should be encrypted and hidden |

  **Examples:**

  <CodeGroup>
    ```ts Test Credentials theme={null}
    import { secret } from "checkly/util"

    new BrowserCheck("user-flow", {
      name: "User Account Flow",
      environmentVariables: [
        { key: "TEST_EMAIL", value: "test@example.com" },
        { key: "TEST_PASSWORD", value: secret("TEST_PASSWORD"), secret: true },
        { key: "BASE_URL", value: "https://staging.example.com" },
      ],
      code: { entrypoint: path.join(__dirname, "user-flow.spec.ts") },
    })
    ```

    ```ts Feature Flags theme={null}
    new BrowserCheck("feature-test", {
      name: "Feature Flag Test",
      environmentVariables: [
        { key: "FEATURE_ENABLED", value: "true" },
        { key: "TEST_VARIANT", value: "A" },
      ],
      code: { entrypoint: path.join(__dirname, "feature-flags.spec.ts") },
    })
    ```
  </CodeGroup>

  **Use cases**: Test configuration, authentication, API keys, feature flags, environment-specific settings.
</ResponseField>

<ResponseField name="intent" type="CheckIntent">
  Describe what your check is intended to verify and the behavior that should be preserved. Checkly uses intent for root cause analysis across all check types. It is separate from `description` and does not replace executable assertions.

  <Note>
    Intent is used for [automatic repair](/resolve/automatic-check-repair) only for Browser and Multistep Checks.
  </Note>

  The object accepts the following fields:

  | Field | Type | Required | Description |
  | - | - | - | - |
  | `goal` | `string` | Yes | The outcome your check should verify. Must contain 1–2,000 characters after trimming. |
  | `constraints` | `CheckIntentConstraint[]` | No | Outcomes and guardrails that refine the goal. Omitted constraints become an empty array. |

  Each constraint has a required `type` and `statement`:

  * `REQUIRED_OUTCOME`: an outcome the check must verify.
  * `MUST_PRESERVE`: behavior or an assertion that should be preserved when repairing the check.

  Each `statement` must contain 1–1,000 characters after trimming. You can specify at most 20 constraints of each type. The CLI trims leading and trailing whitespace from the goal and statements and rejects unknown fields.

  For example, configure intent on a Browser Check:

  ```ts theme={null}
  import { BrowserCheck } from "checkly/constructs"

  new BrowserCheck("dashboard-intent", {
    name: "Authenticated dashboard",
    code: {
      entrypoint: "./dashboard.spec.ts",
    },
    intent: {
      goal: "Verify that authenticated users can open the dashboard.",
      constraints: [
        {
          type: "REQUIRED_OUTCOME",
          statement: "Authentication succeeds for a valid user.",
        },
        {
          type: "MUST_PRESERVE",
          statement: "Do not remove or weaken the authentication assertion.",
        },
      ],
    },
  })
  ```
</ResponseField>

<ResponseField name="aiAutoRepairEnabled" type="boolean | null">
  Requires Checkly CLI 9.4.0 or later. Set `true` to enable automatic repair, `false` to disable it, or `null` to follow your account default. Omit the property to preserve an existing setting when you deploy.

  You also need a valid check intent. See [Configure automatic repair](../resolve/automatic-check-repair#define-intent-with-monitoring-as-code) for a complete example and repair prerequisites.
</ResponseField>

## Examples

<CodeGroup>
  ```ts Login Flow theme={null}
  new BrowserCheck("login-flow-check", {
    name: "User Login Flow",
    frequency: Frequency.EVERY_15M,
    locations: ["us-east-1", "eu-west-1"],
    code: {
      entrypoint: path.join(__dirname, "login.spec.ts"),
    },
  })

  // login.spec.ts
  import { expect, test } from "@playwright/test"

  test("user can login successfully", async ({ page }) => {
    await page.goto("https://app.example.com/login")

    await page.getByLabel('email', { name: /email/i }).fill(process.env.TEST_USERNAME)
    await page.getByLabel('password', { name: /password/i }).fill(process.env.TEST_PASSWORD)
    await page.getByRole('button', { name: /login/i }).click()

    await expect(page).toHaveURL(/dashboard/)
    await expect(page.getByTestId('user-menu')).toBeVisible()
  })
  ```

  ```ts E-commerce Purchase theme={null}
  new BrowserCheck("purchase-flow-check", {
    name: "Purchase Flow",
    frequency: Frequency.EVERY_30M,
    locations: ["us-east-1", "eu-west-1"],
    tags: ["e2e", "critical", "revenue"],
    code: {
      entrypoint: path.join(__dirname, "purchase.spec.ts"),
    },
  })

  // purchase.spec.ts
  import { test, expect } from "@playwright/test"

  test("user can complete purchase", async ({ page }) => {
    await page.goto("https://shop.example.com")

    // Add item to cart
    await page.getByTestId("product-1").click()
    await page.getByTestId("add-to-cart").click()

    // Go to checkout
    await page.getByTestId("cart-button").click()
    await page.getByTestId("checkout-button").click()

    // Fill checkout form
    await page.getByLabel("email").fill("test@example.com")
    await page.getByLabel("card-number").fill("4242424242424242")

    // Complete purchase
    await page.getByTestId("complete-purchase").click()

    await expect(page.getByTestId("success-message")).toBeVisible()
  })
  ```

  ```ts Form Submission theme={null}
  new BrowserCheck("contact-form-check", {
    name: "Contact Form Submission",
    frequency: Frequency.EVERY_10M,
    code: {
      entrypoint: path.join(__dirname, "contact-form.spec.ts"),
    },
  })

  // contact-form.spec.ts
  import { test, expect } from "@playwright/test"

  test("contact form works correctly", async ({ page }) => {
    await page.goto("https://example.com/contact")

    await page.getByLabel('name').fill("John Doe")
    await page.getByLabel('email').fill("john@example.com")
    await page.getByLabel('message').fill("This is a test message")

    await page.getByLabel('submit').click()

    await expect(page.getByText("Thank you")).toBeVisible()
  })
  ```
</CodeGroup>

<Warning>
  Browser checks require Playwright test files. Make sure your test files use the `@playwright/test` framework and follow Playwright's testing conventions.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.