---
title: Browser checks: synthetic monitoring with Playwright in WatchFor
description: Synthetic monitoring with real Playwright tests: run a journey (sign in, search, check out) on a schedule from our browser locations, with per-step results, screenshots, a trace and Web Vitals. An incident opens only when the journey really breaks.
canonical: https://watchfor.io/docs/monitors/browser-checks
---

# Browser checks: synthetic monitoring with Playwright in WatchFor

Synthetic monitoring with real Playwright tests: run a journey (sign in, search, check out) on a schedule from our browser locations, with per-step results, screenshots, a trace and Web Vitals. An incident opens only when the journey really breaks.

A **browser check** runs a Playwright Test script in a real Chromium on the
schedule you choose, one step at a time. It answers what an HTTP check can't:
*can a customer still sign in, find a product and reach the checkout?*

The script is plain Playwright. The same file runs on your laptop with
`npx playwright test`, and there is no recorder dialect to lock you in.

  - [Quickstart](/docs/monitors/browser-checks/quickstart): From an example that passes to a check on your own site in five minutes.
  - [Recipes](/docs/monitors/browser-checks/recipes): Login, 2FA codes, checkout, search, API + UI, cookie banners, iframes, mobile, downloads.
  - [Troubleshooting](/docs/monitors/browser-checks/troubleshooting): Look up the error text you got: what it means and how to fix it.
  - [Ask your agent](/docs/monitors/browser-checks/agents): Let Claude, Cursor or any MCP client write, test and fix the script for you.

## How it works

1. **Write or bring a script.** Start from one of the examples, import
   `npx playwright codegen` output, a `.spec.ts` file or a Chrome DevTools
   Recorder export, or [ask your agent](/docs/monitors/browser-checks/agents).
2. **Test run.** The script runs once from one of our browser locations while
   you watch the steps tick past. Nothing is saved or scheduled yet.
3. **Create the check.** It runs on your schedule. The first run starts at once
   and keeps full screenshots and a trace.
4. **Get told when the journey breaks.** A failed test is retried once inside
   the same run, and a failing run is confirmed by a second run about a minute
   later before an incident opens, so a flaky moment never pages anyone.

```ts

test('checkout', async ({ page }) => {
  await test.step('Open the product', async () => {
    await page.goto(process.env.TARGET_URL!);
    await expect(page.locator('h1').first()).toBeVisible();
  });

  await test.step('Add to cart', async () => {
    await page.getByRole('button', { name: /add to cart/i }).click();
  });
});
```

Name what matters with `test.step()`: steps are what results, alerts and
trends are about. A test without steps shows its Playwright actions instead.

## What you get

- **Real Playwright.** `test`, `expect`, `test.step`, `test.use`, fixtures,
  `request` for API calls, `expect.soft` and `expect.poll`, in TypeScript or
  JavaScript. [Run locally](/docs/monitors/browser-checks/run-locally) shows
  the exact versions and config to reproduce a run on your machine.
- **A result you can read.** A waterfall of steps. A failed step shows the
  error in one line (what was expected and what the page showed), the code
  frame, the page at the failure, and a
  [hint](/docs/monitors/browser-checks/troubleshooting) when we recognise the
  error. Each step's screenshot shows the element the step last clicked,
  filled, read or checked with `expect`: when it sits below the fold, the shot
  brings it into view and outlines it, then puts the page's scroll back, so
  the next step runs on the page exactly as your script left it.
- **Last-green comparison with step timings and screenshots.** Compare a
  failed run with the last passing one: each step's change in duration, and
  the two screenshots side by side.
- **The Playwright trace viewer, hosted by WatchFor.** DOM snapshots, network,
  console and a film strip of the whole run. The trace never goes to a third
  party.
- **Errors and Web Vitals.** Console errors, uncaught exceptions and failed
  requests, plus TTFB, FCP, LCP, CLS and INP for every page the run opened.
- **Secrets scrubbed in scheduled runs too.** Secrets are masked in logs,
  error messages, step titles, trace text and screenshots of every run, not
  only the test run in the editor. See
  [Variables and secrets](/docs/monitors/browser-checks/variables).

Failed runs keep a failure screenshot and a trace. Passing runs keep nothing,
except the first run after a script change, **Run now**, and one run per day,
so there is always a recent passing run to compare with. Screenshots and traces
are kept for your plan's artefact window and runs for its check history — see
[Data retention](/docs/organization/data-retention).

## Alerts

**Journey failed** is on by default: a test fails after its retry, on two runs
in a row. A pass on the retry is reported as **flaky** and never opens an
incident. The second failing run is a confirmation run about a minute later,
from another location when the check has one.

Optional budgets on the check's Alerting tab: **Journey slow**, **Step budgets**
(per step), **Console errors**, **Failed requests**, **Slow page (LCP)** and
**Flaky journey**.

If a run can't start on our side, it shows **Couldn't run**. That never opens
an incident and never lowers uptime.

## Safety

Every run gets a fresh, disposable, sandboxed browser with no access to
WatchFor's network or other customers' runs, and a memory and time limit. It
can reach the public internet only: requests to private addresses are refused
and listed under Errors. Browser traffic identifies itself with a Chrome user
agent ending in `WatchFor-BrowserCheck/1.0 (+https://watchfor.io/bot)` and
comes from the addresses listed on [/bot](/bot). It is not `WatchForBot`: that
name belongs to the probes, whose requests carry a Web Bot Auth signature.

## Limits

Plans set how many browser checks you can have, the shortest interval, the
longest run, how many test runs an hour you get in the editor, and how many
runs a month the schedules may add up to.

| Plan | Checks | Shortest interval | Runs a month | Longest run | Test runs an hour |
| --- | --- | --- | --- | --- | --- |
| Free | 1, from one location | 1 hour | 750 | 60 s | 5 |
| Starter | 2 | 10 minutes | 9,000 | 90 s | 15 |
| Pro | 10 | 5 minutes | 45,000 | 120 s | 30 |
| Business | 25 | 1 minute | 110,000 | 180 s | 60 |
| Enterprise | Unlimited | 1 minute | from 1,000,000 | 180 s | 120 |

**Runs a month is a budget your schedules share.** When you save a check we
work out its runs from its interval and locations (a parallel check counts
every location), and all your checks together must fit. 45,000 runs is 5
checks every 5 minutes, or 10 checks every 10 minutes; a check every minute
alone is 43,200. The retry inside a run and the confirmation run before an
alert never count. A paused check counts nothing, so you can pause one to make
room. [Pricing](/pricing) always has the current numbers.

**A check never runs twice at once.**

- A run with its retry can take up to 2 × the timeout + 30 s (browser
  start-up and upload), so the timeout has to fit the interval:
  2 × timeout + 30 s must be less than the interval. Every minute allows a
  timeout of up to 14 s, every 2 minutes up to 44 s, every 5 minutes up to
  134 s. The editor only offers timeouts that fit, and a save (dashboard, API
  or MCP) that doesn't fit is refused with the numbers.
- If a scheduled run comes due while the previous one is still going on
  that location, for example while an incident has sped the check up to every
  minute, it is skipped. A skipped run shows as *Skipped* in the run list,
  doesn't count as a failure and never opens an incident.

On the Free plan you need a verified email address, which every sign-in
already requires, and the check runs from one location at a time (round
robin).

## More

- [Runtime and versions](/docs/monitors/browser-checks/runtime): what a
  script can import and how new Playwright versions arrive.
- [Variables and secrets](/docs/monitors/browser-checks/variables).
- [API, MCP and SDK](/docs/monitors/browser-checks/api): test runs, runs and
  script versions from code.

---

Canonical page: https://watchfor.io/docs/monitors/browser-checks · All docs: https://watchfor.io/docs · Site guide: https://watchfor.io/llms.txt
