◉
24observe
DOCUMENTATION • BROWSER MONITORS • 5 MIN READ

Browser (synthetic) monitors.

A browser monitor loads your URL in real headless Chromium, executes the page's JavaScript, and evaluates the fully rendered page. An http or keyword check sees only the raw HTTP response; a browser check sees what a user's browser actually paints. Use it for single-page apps, JavaScript-gated content, and "does the page actually render" checks where a 200 on the raw HTML tells you nothing.

Start free → Quickstart

TL;DR

A browser monitor loads your URL in real headless Chromium, executes the page's JavaScript, and evaluates the fully rendered page. An http or keyword check sees only the raw...

Docs · browser monitors

Browser (synthetic) monitors.

A browser monitor loads your URL in real headless Chromium, executes the page's JavaScript, and evaluates the fully rendered page. An http or keyword check sees only the raw HTTP response; a browser check sees what a user's browser actually paints. Use it for single-page apps, JavaScript-gated content, and "does the page actually render" checks where a 200 on the raw HTML tells you nothing.

When to reach for it

  • Single-page apps — React / Vue / Svelte shells that ship an empty <div id="root"> and hydrate client-side. The raw response is a skeleton; the rendered page is the product.
  • JavaScript-gated content — anything that only appears after the bundle loads, fetches, and renders.
  • "Does it actually render" checks — assert on text that only exists post-hydration, so a broken bundle or a failed XHR flips the monitor even when the server returns 200.

Create one — API

A browser monitor is created like any other: POST /api/v1/monitors with type: "browser". Use a PAT with the monitors:write scope.

curl -X POST https://api.24observe.com/api/v1/monitors \
  -H 'Authorization: Bearer obs_<token>' \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "app.example dashboard renders",
    "url": "https://app.example.com/dashboard",
    "type": "browser",
    "intervalSec": 300,
    "timeoutMs": 30000,
    "expectedStatusCode": 200,
    "keyword": "Welcome back",
    "keywordMatchType": "contains",
    "degradedResponseTimeMs": 4000,
    "alertEmail": "alerts@yourco.com"
  }'

The keyword above is matched against the rendered DOM (post-JavaScript), so "Welcome back" can be text the app only paints once it has hydrated and fetched the user's session — not something present in the initial HTML.

Create one — dashboard

Open login.24observe.com, click New monitor, and pick "Browser (headless Chromium — renders JS)" from the type dropdown. Fill in the URL, interval, timeout, and any keyword assertion exactly as above.

Fields it honors

  • url (required) — the full https URL to load.
  • intervalSec — how often the check runs. The free plan's minimum interval is 300s.
  • timeoutMs — how long the load may take before it counts as down (e.g. 30000).
  • expectedStatusCode (optional) — assert the document response status.
  • keyword + keywordMatchType (optional) — "contains" or "not_contains", matched against the rendered DOM after JavaScript has run.
  • degradedResponseTimeMs (optional) — render time above this marks a slow-but-up page as degraded instead of up.

Result semantics

  • up — the page loaded (status < 400) and any keyword assertion passed.
  • degraded — the page loaded, but render time exceeded degradedResponseTimeMs.
  • down — a 4xx / 5xx, a failed keyword assertion, or a load timeout.

Reported response time is the time to the load event — the same number you'll see in the dashboard charts and SLO calculations.

Isolation

Browser checks run on a dedicated browser execution pool, kept separate from the standard check pipeline. Rendering a page is heavier than a plain HTTP request, so isolating it means a slow or stuck browser check never delays your http, ping, or keyword monitors.

Security

Every request the page makes — the initial navigation, every redirect, and every sub-resource it pulls — is checked against an SSRF guard. A browser monitor cannot be pointed at private, loopback, or cloud-metadata addresses, and a page can't be used to reach them indirectly through a redirect or an embedded resource. The same defense that protects alert and webhook targets applies to what the browser is allowed to load.

Alerting, incidents, and status pages

A browser monitor behaves like every other monitor type once it's running. Configured alert channels (email / webhook / Slack / Discord / Teams / Telegram / PagerDuty / Opsgenie) fire on the same alertThreshold rules, incidents open and auto-resolve the same way, and the monitor can be added to a public status page like any other. Nothing about the result handling is special — only the check itself renders the page.

Other resources

Ready to build with 24Observe?

Explore live telemetry, zero-friction integration, and automated SOC investigation.

+ Get Free Trial / Demo