Browser monitoring (synthetics)
Multi-step flows (login, checkout, form) run in a real Chromium browser. When a step fails, you get an alert with the exact step number and error message; the failure screenshot is in the run detail.
# Monitor + run history
# Step types in the builder
A scenario is a list of up to 40 steps. Each step has a type and matching fields. Optionally, each step can set a retry count (0–3) for flaky selectors.
Navigate to URL, waits for networkidle. If the response returns an error status (not 2xx/3xx), the step fails. The HTTP status is remembered for a later assert_status.
Fields: url
Click a CSS selector. Waits for visible element.
Fields: selector
Set field value (text, email, password). Replaces existing content.
Fields: selector + value
Like fill, but typed character by character — for components that react to input events per character (autocomplete, masked inputs).
Fields: selector + value
Until selector is visible in DOM (configurable timeout).
Fields: selector
Static pause, 100–30 000 ms. Use sparingly — prefer wait_for.
Fields: ms
Selector text must contain a substring (contains, case-sensitive) or exactly equal a value (equals).
Fields: selector + contains | equals
Current URL must contain substring (e.g. "/dashboard").
Fields: contains
Last navigation must have returned the expected status (e.g. 200).
Fields: status
Selector must be present in the DOM and visible.
Fields: selector
Takes a screenshot (PNG), shown in the run detail. With full_page=true the entire page instead of just the viewport.
Fields: full_page?
# Scenario JSON & options
Every scenario is a JSON object with a steps list. Beyond the steps you can set the viewport, a global per-step timeout and a default retry for the whole list. The builder in the dashboard produces exactly this structure — advanced users edit it directly.
Anatomy of a scenario
A typical login flow: open the page, fill fields, click submit, wait for the dashboard and assert text plus URL. viewport (default 1280×800) and timeout_ms (global per-step timeout, 5,000–60,000 ms, default 30,000) are optional. A per-step timeout_ms (1,000–60,000 ms) overrides the global one.
{
"name": "Login-Flow",
"viewport": { "width": 1280, "height": 800 },
"timeout_ms": 30000,
"step_retry": 1,
"steps": [
{ "type": "goto", "url": "https://example.com/login" },
{ "type": "fill", "selector": "#email", "value": "monitor@example.com" },
{ "type": "fill", "selector": "#password", "value": "***" },
{ "type": "click", "selector": "button[type=submit]" },
{ "type": "wait_for", "selector": ".dashboard", "timeout_ms": 10000 },
{ "type": "assert_text", "selector": "h1", "contains": "Willkommen" },
{ "type": "assert_url", "contains": "/dashboard" }
]
}Retry against flakiness (linear backoff)
If a step fails it is retried up to retry times (0–3) before the run counts as failed. The value comes from the individual step (retry) or as step_retry from the whole scenario (default 0). Between attempts the runner waits progressively longer (500 ms × attempt). Use it sparingly — a targeted wait_for before the next step is usually the cleaner fix for SPA races.
Dedicated user agent & tracker block
Each run sends the user agent XICTRAQ-BrowserMonitor/1.0 (overridable per scenario via user_agent). The runner additionally blocks the XICTRAQ tracker (t.js plus the /api/p and /api/e endpoints) so synthetic runs do not pollute your own analytics with test pageviews.
SSRF protection on every URL
Every goto URL must be a publicly reachable http/https address. Internal or private targets (localhost, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, link-local, IPv6 ULA and others) are rejected — both on save and again immediately before each run (with DNS resolution, so DNS rebinding is caught too). A blocked URL ends the run with a clear error instead of fetching internal content.
# Run history & screenshots
Every run is stored with total duration, result and per-step results. The overview shows the latest 50 runs per monitor.
Per-step results
Per run, start and end time, duration_ms, ok, the index of the failed step (failed_step) and an error message are recorded. For each step the type, duration, success/failure and — depending on the type — the text actually found, the current URL or the HTTP status are logged. You see exactly which step fails, how often and with what message.
Run now
“Run now” marks a monitor as due — the next cron tick (every minute) picks it up and runs the flow without waiting for the next interval. Useful for checking after a deploy or during an open alert whether the flow is green again.
Screenshots stored privately
Failure screenshots (on error) and deliberate screenshot steps are stored in a private directory — not public, retrievable only via your account's authenticated, tenant-scoped endpoint. Deleting a monitor cleans up the associated image files.
# Alerting & failure screenshot
Same alert engine as uptime
A failure creates an alert of type browser_monitor_failed with severity critical. Dedupe (10 min), ACK link, escalation via default policy and postmortem export work identically to the regular uptime alert. The 10 minutes are the default; the window can be changed in the notification settings. When the flow turns green again, XICTRAQ auto-resolves the alert.
Failure screenshot captured automatically
On every failed step, a screenshot is captured at the moment of failure (without needing an explicit screenshot step) and stored with the run history. The alert email links to the dashboard, where the screenshot is available behind authentication — you see exactly what the browser saw when it broke.
Auto-resolve on recovery
As soon as a run is fully green again, the open alert is resolved. No alert flood when a flaky selector intermittently works — dedupe holds for 10 minutes by default, configurable.