Browser checks
A browser check is a synthetic monitor that runs a Playwright script in a real Chromium browser on a schedule. Use it for the things HTTP checks can’t tell you:
- Does the login flow work end-to-end with real JavaScript?
- Does the checkout button actually charge a card?
- Does the multi-step signup form submit correctly?
- Did the latest deploy break the homepage’s hero CTA?
When to use browser checks
Section titled “When to use browser checks”- You have a critical user flow with multiple steps and JavaScript-driven UI.
- You’ve ever shipped a deploy that broke a button without breaking any HTTP endpoint.
- You want to monitor third-party JavaScript (analytics, payment widgets, fonts) that an HTTP check can’t observe.
When NOT to use them
Section titled “When NOT to use them”- For “is my API up?” use HTTP checks. Browser checks cost ~30× more compute and are slower.
- For “is my page fast for real users?” use RUM. Browser checks measure synthetic latency from the cloud locations you pick, not your users’ experience.
- For low-priority pages. Reserve browser checks for the 5–10 most important user flows.
How it works
Section titled “How it works”- You write a Playwright script in JavaScript, driving the browser with the
pageAPI andstep()helpers. - Site Qwality runs your script in headless Chromium on the schedule (
5m,10m,15m,30m,1h), once in each location you select. - Each step’s pass/fail, duration, and a screenshot are captured.
- On every run, a HAR file (full network log) and a video are recorded.
- Web vitals (LCP, FCP, CLS, TTFB) are extracted from the page and reported.
- Console errors and unhandled exceptions are captured.
- A run fails when fewer locations pass than
min_healthy_regionsrequires. Status flips tofailedwhen a run fails, and alerts fire on that first confirmed failure (see rerun and confirmation). A check that keeps passing and failing is held like a flapping HTTP monitor: one notice instead of an alert pair per change. See flap hold.
The script runs inside a sandboxed async function with page (Playwright Page) and step (your wrapper for tracked steps) injected:
await step('Open homepage', async () => { await page.goto('https://example.com');});
await step('Click sign in', async () => { await page.click('text=Sign in');});
await step('Fill credentials', async () => { await page.fill('input[name="email"]', 'demo@example.com'); await page.fill('input[name="password"]', 'demo-password'); await page.click('button[type="submit"]');});
await step('Confirm dashboard loaded', async () => { await page.waitForSelector('h1:has-text("Dashboard")');});Anything you can do with Playwright works inside a step.
What’s captured
Section titled “What’s captured”| Artifact | Where |
|---|---|
| Step results | Pass/fail, duration, error message per step. |
| Screenshots | Auto-captured after each step (pass or fail). |
| HAR file | Full network capture, downloadable from the run page. |
| Video | 1280×720 WebM of the entire run. |
| Web vitals | LCP, FCP, CLS, TTFB extracted via PerformanceObserver. |
| Console errors | Anything logged at console.error or thrown. |
| Trace IDs | Every request the browser makes, to any origin, carries a W3C traceparent header, and the run records those trace IDs. If the receiving server sends its OpenTelemetry traces to Site Qwality, the ID opens that backend trace; otherwise the trace has no spans. |
Failure alerts carry the failed step and a screenshot
Section titled “Failure alerts carry the failed step and a screenshot”When a browser check fails, the email and Slack alerts name the first failed step and link to the screenshot captured at that step. Other channels get the monitor name and error message only.
You get this only when:
- The failure happens inside a
step()call. A script that throws at the top level, fails to navigate, or times out before any step runs produces no step results, so there is no step name and no screenshot. - The step has a name. An unnamed step yields no enrichment, including no screenshot link.
- The alert is not delayed. If a notification group has
delay_send_after_minutesset, the delayed alert arrives without the step name or screenshot; the immediate alert is the enriched one.
The screenshot link in an alert usually stops working within a few hours. After that, open the screenshot from the check’s run detail in the dashboard, where it does not expire.
Locations
Section titled “Locations”Browser checks run from the 20 AWS check locations, in 18 countries and territories. The Google Cloud and Microsoft Azure locations do not run browser checks. In GET /check-locations, a location that runs browser checks lists "browser" in its capabilities; the reference has the full table.
- Default. With
check_regionsunset or empty, a new check runs from the default location, Virginia (aws-us-east-1). - Plans. The free plan checks from one location. More than one needs a paid Synthetic plan; an uptime plan does not count. Without one the API returns
403withmulti_region_requires_paid_plan. - Minutes. The script runs once in every selected location, and each run uses browser check minutes, so a check on three locations uses about three times the minutes of a check on one.
- Minimum healthy locations.
min_healthy_regions(Minimum Healthy Locations in the dashboard) sets how many locations must pass. The check is down when fewer than that many pass. - No data is not a failure. A location with no result for two runs plus 10 minutes (20 minutes on a
5mcheck) is left out of the count. The minimum is capped at the number of locations reporting, so a silent location never holds a check down. - Confirmation.
confirmation_thresholdcounts failed runs of that quorum, andrerun_on_failurereruns a failed attempt once from the same location. - Run now.
POST /browser_check/{id}/runruns the script in every location the check selects, and the response’sregionslists them. - Storage. Wherever the script runs, its results, screenshots, HAR and video are stored in
us-east-1.
Start with a location near your users, and add locations on other continents to cover a global audience.
Constraints
Section titled “Constraints”- Script size: under 50KB.
- Timeout:
1–300seconds per run, including browser startup; the user script getstimeout - 30s. - Locations: AWS locations only; see locations above.