Skip to content

Browser check reference

The full request schema is in the auto-generated API Reference. Cheat sheet below.

FieldTypeDefaultDescription
namestringrequiredDisplay name; validated as a “friendly name.”
scriptstringrequiredThe Playwright script body. Wrapped in an async IIFE; max ~50KB.
frequencyenumrequired5m, 10m, 15m, 30m, or 1h.
timeout_secondsint60Max script runtime, 1–300. The actual user-script budget is timeout - 30s.
check_regionsstring[]["aws-us-east-1"]Regions to run from. Subset of supported regions.
min_healthy_regionsint1Required healthy regions for overall status. Must be ≤ region count.
group_notification_idsuuid[][]Notification groups; cap of 10.
stateenumactiveactive or paused. Paused checks don’t run.
tagsstring[][]Free-form labels for filtering and maintenance windows.
service_iduuid | nullnullOptional logical service grouping.
current_statusenumderivedsuccess, pending_failure, failed.
  • aws-us-east-1 — N. Virginia
  • aws-us-east-2 — Ohio
  • aws-us-west-1 — N. California
  • aws-eu-west-2 — London

Two globals are injected: page (Playwright Page) and step (your wrapper).

await step('Open homepage', async () => {
await page.goto('https://example.com');
});
  • name is the display label in the result UI.
  • fn is an async () => Promise<void>.
  • A step that throws fails. Subsequent steps are skipped.
  • A screenshot is captured after every step (pass or fail).

The full Playwright API is available — anything documented at https://playwright.dev/docs/api/class-page works.

Common helpers:

await page.goto(url, { waitUntil: 'networkidle' });
await page.click('text=Sign in');
await page.fill('input[name=email]', 'demo@example.com');
await page.waitForSelector('h1:has-text("Welcome")', { timeout: 10000 });
const text = await page.textContent('h1');
const ok = await page.isVisible('.success-banner');
const url = page.url();

Browser checks don’t have a separate assertion DSL — assertions are just JavaScript that throws.

// Wait for an element
await step('Dashboard loaded', async () => {
await page.waitForSelector('h1:has-text("Dashboard")', { timeout: 10000 });
});
// Assert text content
await step('Welcome message correct', async () => {
const text = await page.textContent('h1');
if (!text?.includes('Welcome')) {
throw new Error(`Expected "Welcome", got "${text}"`);
}
});
// Assert URL
await step('Redirected to dashboard', async () => {
if (!page.url().endsWith('/dashboard')) {
throw new Error(`Expected dashboard, got ${page.url()}`);
}
});
// Assert HTTP response
await step('Submit form', async () => {
const [response] = await Promise.all([
page.waitForResponse(/\/api\/login$/),
page.click('button[type="submit"]'),
]);
if (response.status() !== 200) {
throw new Error(`Expected 200, got ${response.status()}`);
}
});

For every result:

ArtifactStored asAPI endpoint
Step resultsInline JSON in the result rowGET /browser_check/{id}/results
ScreenshotsPer-step PNGs in S3embedded in step results
HAR fileFull network capture, S3GET /browser_check/{id}/results/{result_id}/artifact_url
Video1280×720 MP4 of the run, S3same artifact_url endpoint
Web vitalsInline JSON: {lcp_ms, fcp_ms, cls, ttfb_ms}GET /browser_check/{id}/vitals
Console errorsInline JSON arrayembedded in result
Trace IDsList of traceparent IDs from outgoing requestsembedded in result

The HAR and video URLs are presigned, expire in 1 hour, and are S3-direct (no proxying through SiteQwality’s API).

MethodPathPurpose
POST/browser_checkCreate.
GET/browser_checkList all.
GET/browser_check/{id}Detail.
PUT/browser_check/{id}Update (partial body).
DELETE/browser_check/{id}Delete.
POST/browser_check/{id}/runTrigger an immediate run.
GET/browser_check/{id}/resultsList recent results.
GET/browser_check/{id}/results/{result_id}/artifact_urlPresigned HAR + video URLs.
GET/browser_check/{id}/vitalsAggregated web vitals over time.