Browser Checks

Updated April 28, 2026

Browser Checks run a Playwright script in headless Chromium on a schedule. The check fails when an assertion breaks or the global timeout fires, and every run keeps logs, screenshots, video, and a Playwright trace for replay.

Browser Check overview with the Playwright editor, Web Vitals chart, and run logs
A Browser Check: the Playwright script, Web Vitals, run history, and per-step logs in one view
Default runtime
2026.05 · Node 24 · Playwright 1.59.1
Legacy runtime
2023.04 · Node 16 · Playwright 1.33
Browser
Chromium, headless
Run timeout
2 minutes per run
Test timeout
30 seconds, configurable
Retention
Logs kept indefinitely

Create a browser check

  1. Open the dashboard

    Go to app.hyperping.io and click New monitor.

  2. Pick the Browser protocol

    Select Browser as the ping protocol and give the monitor a name. Pick the runtime from the runtime card, the default is 2026.05.

  3. Write the script and save

    Paste a Playwright script into the editor, add any secrets as environment variables, click Run to test, then save to schedule the monitor.

Runtime 2026.05

The 2026.05 runtime is the default for new browser checks. It runs on Node 24 with Playwright 1.59.1 and adds three capabilities on top of the script API.

What 2026.05 adds 3 features

Web VitalsLCP / CLS / TBT / FCP / TTFB
Core Web Vitals are collected from each navigation in your script with no code changes. The dashboard plots them as a time-series chart on the overview, and shows per-run values on every log row.
Step reportingtest.step()
Every test.step('...') call shows up in the run view with a green or red status and its own duration. A failed multi-step check points at the exact stage that broke instead of dropping a wall of logs on the on-call engineer.
Trace and videoretain-on-failure
Failed runs attach a Playwright trace and a video of the run, alongside the screenshot already captured today. The trace deep-links into trace.playwright.dev for step-by-step replay.

Web Vitals

The runtime injects a PerformanceObserver into every page your script opens. After each navigation it captures the five Core Web Vitals and stores them on the run, so you can watch them trend without writing any custom timing code.

LCP
≤ 2,500 ms
Largest Contentful Paint. Time to render the largest visible element. High values mean users wait too long before the most useful part of the page loads.
CLS
≤ 0.1
Cumulative Layout Shift. Visual stability score. Low values mean the layout doesn't jump around as the page loads.
TBT
≤ 200 ms
Total Blocking Time. How long the main thread was blocked from handling user input. High values mean sluggish interactions.
FCP
≤ 1,800 ms
First Contentful Paint. Time until any content is rendered. Large values mean users see a white screen for too long.
TTFB
≤ 800 ms
Time to First Byte. Server response time for the navigation request. Varies by region and network conditions.

Packages available in 2026.05

Bundled libraries 12 packages

playwright1.59.1
Browser automation API.
@playwright/test1.59.1
Test runner with fixtures, locators, and expect.
typescript^5.6
TypeScript compiler. Use .spec.ts files directly.
expect^29
Standalone Jest-style assertion library.
uuid^9.0.1
RFC4122 UUID generator.
lodash4.17.21
Utility functions for arrays, objects, and collections.
moment^2.30.1
Date and time parsing, formatting, and arithmetic.
axios^1.13.2
HTTP client. Useful for hitting APIs alongside the UI flow.
btoa1.2.1
Base64 encoding helper for Node.
jsonwebtoken^9.0.2
Sign and verify JWTs.
date-fns^2.30.0
Modular date utilities, lighter alternative to moment.
crypto-js^4.2.0
Hashes, HMAC, and symmetric ciphers.

Runtime 2023.04

The 2023.04 runtime runs on Node 16 with Playwright 1.33 and is kept around for existing checks. New checks default to 2026.05 and there's no automatic migration, switch the runtime on the monitor's settings page when you're ready.

Node
16.x
Playwright
playwright ^1.33.0, @playwright/test 1.33
TypeScript
typescript ^5.0.4
Same package set
Lodash, moment, axios, date-fns, crypto-js, jsonwebtoken, uuid, btoa, expect, on the older versions that shipped at the time.
Web Vitals
Not collected on this runtime. Switch to 2026.05 to enable them.

Environment variables

Secrets, tokens, and per-monitor configuration belong in environment variables, not in the script. Add them in the monitor's settings panel below the editor and reference them from the script as process.env.NAME.

Double check

Double check is enabled by default. When a run fails, the runtime immediately retries from a different region before opening an outage. This filters out network blips and one-shot flake without making you wait for the next scheduled run.

Timeouts

Each browser check has a 2-minute global timeout for the entire run. Individual tests inherit Playwright's 30-second default. Override the per-test timeout when you have a slow flow:

test.setTimeoutJS
test.setTimeout(120_000); // 2 minutes in milliseconds

Long flows are usually better split into separate checks, one per critical path, rather than packed into a single 2-minute run.

Run logs and storage

Every run keeps its logs, screenshots, video, and trace indefinitely. Failed runs in 2026.05 attach a video of the run and a Playwright trace to the log row, so you can replay exactly what the browser did.

Example script

A login flow with two assertions, using process.env for credentials:

login.spec.tsTS
import { test, expect } from '@playwright/test';

test.beforeEach(async ({ page }) => {
  await page.goto('https://app.acme.com/login');
  await page.locator('input[type="text"]').type(process.env.EMAIL);
  await page.locator('input[type="password"]').type(process.env.PASSWORD);
  await page.getByRole('button', { name: 'Sign in', exact: true }).click();
});

test('has title', async ({ page }) => {
  await expect(page).toHaveTitle(/Acme/);
});

test('is logged in', async ({ page }) => {
  const content = page.locator('#project-id');
  await expect(content).toHaveText('project_12345');
});

Troubleshooting

The check fails with 'Test timeout of 30000ms exceeded'

One step in the test never completed, usually a locator that matches nothing or a page that never finished loading. Open the trace on the failed run to see where time was spent. If the flow is legitimately slow, raise the limit with test.setTimeout, and keep the whole run under the 2-minute cap.

A locator that works locally fails in the check

The page often renders differently in headless Chromium: cookie banners, geo popups, and A/B variants show up for a fresh session in a datacenter region. Watch the video of the failed run to see what the browser saw, then dismiss the overlay in the script or use a locator that doesn't depend on it. Prefer getByRole over CSS selectors so a class rename doesn't break the check.

The check is flaky, alternating pass and fail

Most flake comes from racing the app: asserting before data loads, or a hard waitForTimeout that is sometimes too short. Replace sleeps with web-first assertions like await expect(locator).toBeVisible(), which retry until the condition is met. Double check already retries failures from a second region before opening an outage, so a persistent alternation points at the script or the app, not the network.

Login works in the browser but not in the script

Check that the credentials are set as environment variables on the monitor and read with process.env, they are not copied from your local .env. Bot protection and captchas also trigger more often for datacenter IPs, so whitelist the probe regions or use a dedicated test account on a captcha-free path.

The run passes but takes most of the 2-minute budget

Split the flow into separate checks, one per critical path. Shorter checks give clearer alerts, and a slow step in one flow won't push another into the global timeout.

Next steps

New to Playwright? The Learn Playwright guides cover locators, assertions, waits, and codegen from scratch. For the full API, see the upstream Playwright docs.