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"]Locations to run from, any of the supported locations. Unset or empty on create uses aws-us-east-1. More than one needs a paid Synthetic plan.
min_healthy_regionsint1Required healthy locations for overall status. At least 1, at most the number of check_regions. Capped at the number of locations reporting; see locations.
rerun_on_failurebool | nullnullRerun a failed run once from the same location before counting it. See rerun and confirmation. The dashboard turns it on for new checks.
confirmation_thresholdint | nullnullFailed runs in a row needed before the check goes failed and alerts, 1 to 10 (400 outside that range). null or 1 alerts on the first failure.
group_notification_idsuuid[]default groupNotification groups; cap of 10. On create, omitting it (or sending null) attaches your account’s default group; [] notifies no one.
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 or failed. A legacy pending_failure value exists in the enum but nothing sets it.
not_checked_reasonstring | nullderivedSet only while an active check is not being run. quota: the account’s browser check minutes for this period are used up. current_status then keeps its last value.

With rerun_on_failure: true, a failed run is held back and the same script runs once more from the same location, usually within a minute. Only the rerun’s result counts, so a one-off blip never alerts. A rerun uses browser check minutes like any run, so a failing check can use up to twice its usual minutes. A rerun is skipped when the check was paused, and a check already failed is not rerun.

confirmation_threshold counts the failures that stand after any rerun: the check goes failed only after that many in a row (per location, judged against min_healthy_regions). Recovery is immediate.

Browser checks run from 20 AWS locations in 18 countries and territories:

IdLocation
aws-us-east-1Virginia (default)
aws-us-west-2Oregon
aws-ca-central-1Montreal
aws-sa-east-1Sao Paulo
aws-eu-west-1Dublin
aws-eu-west-2London
aws-eu-west-3Paris
aws-eu-central-1Frankfurt
aws-eu-north-1Stockholm
aws-eu-south-1Milan
aws-eu-south-2Aragon
aws-af-south-1Cape Town
aws-ap-south-1Mumbai
aws-ap-northeast-1Tokyo
aws-ap-northeast-2Seoul
aws-ap-northeast-3Osaka
aws-ap-southeast-1Singapore
aws-ap-east-1Hong Kong
aws-ap-southeast-3Jakarta
aws-ap-southeast-2Sydney

The Google Cloud and Microsoft Azure locations do not run browser checks. GET /check-locations is the live list: a location that runs browser checks lists "browser" in its capabilities. See check locations for the response shape.

How check_regions is validated on create and update:

You sendResult
Nothing, or [], on createAccepted. The check runs from the default location, aws-us-east-1.
Locations from the table aboveAccepted.
A retired id: aws-us-east-2 or aws-us-west-1Accepted and replaced with its replacement location, today aws-us-east-1.
A location without "browser" in its capabilities400 with Invalid check_regions <id>: location does not run browser checks.
An id that does not exist400 with Invalid check_regions <value>.
More than one location without a paid Synthetic plan403 with multi_region_requires_paid_plan (“Multi-region checks require a paid synthetic plan”). An uptime plan does not count.

Each selected location runs the script on every scheduled run and uses its own browser check minutes. See locations for how the results are combined.

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.

The browser can only reach public addresses. A navigation, redirect or subresource aimed at a private, loopback or link-local address (10.x, 192.168.x, 127.0.0.1, localhost, 169.254.169.254, or a hostname that resolves only to one) is refused. A refused http:// request answers 403; a refused https:// request fails with net::ERR_TUNNEL_CONNECTION_FAILED, and the check’s error names the address and why. Refused subresources are listed in the console errors.

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();

There is no separate assertion DSL: an assertion is 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:

ArtifactFormatAPI endpoint
Step resultsJSONGET /browser_check/{id}/results
ScreenshotsPer-step PNGsGET /browser_check/{id}/results/{result_id}/artifact_url?artifact_type=screenshot&screenshot_index=N
HAR fileFull network captureGET /browser_check/{id}/results/{result_id}/artifact_url?artifact_type=har
Video1280×720 WebM of the runsame endpoint with artifact_type=video
Web vitalsJSON: {lcp_ms, fcp_ms, cls, ttfb_ms}GET /browser_check/{id}/vitals
Console errorsJSON arrayembedded in result
Trace IDsTrace IDs of the traceparent headers added to outgoing requests; they resolve only for backends that send traces to Site Qwalityembedded in result

The artifact URLs are presigned and expire in 1 hour. Results and artifacts are stored in us-east-1, whichever location ran the script.

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 in every location the check selects. The response’s regions lists them.
GET/browser_check/{id}/resultsList recent results.
GET/browser_check/{id}/results/{result_id}/artifact_urlA presigned URL for one artifact: artifact_type is har, video or screenshot (with screenshot_index).
GET/browser_check/{id}/vitalsAggregated web vitals over time.