Playwright Synthetic Browser Checks
Run real browser-based checks using Playwright scripts. Validate full user journeys like logins, checkouts, and form submissions.
Overview
Playwright synthetic checks go beyond simple HTTP monitoring by executing real browser interactions against your web application. Using custom Playwright scripts, you can simulate complete user journeys, including navigating pages, filling forms, clicking buttons, and verifying that the correct content appears on screen.
This is the most powerful monitoring type in upti.my. It catches issues that API-level checks miss, such as broken JavaScript, rendering errors, authentication flows that fail silently, and third-party widget failures.
How It Works
Each Playwright check runs your custom JavaScript script in a real Chromium browser instance. The browser is launched and cleaned up for you â your script receives a context object with everything it needs, allowing you to:
- Navigate to pages and wait for elements to load
- Fill in forms, click buttons, and interact with UI components
- Assert that specific text, elements, or conditions are present
- Handle authentication flows, including multi-step logins
- Verify that API-driven content renders correctly in the browser
- Test multi-page workflows like checkout or onboarding flows
Script Environment
Scripts run top-level in an async context â no imports, browser launch, or teardown required. The injected context object provides:
| Property | Description |
|---|---|
page | A Playwright Page connected to the Chromium instance, with the full Playwright page API |
step(name, fn) | Wraps a phase of your check in a named step. Steps appear in the execution logs, so a failure pinpoints exactly which phase broke |
expect(value) | Assertions such as toBe, toContain, and toBeLessThan. A failed assertion fails the check |
env | Environment variables configured on the check â use these for target URLs and monitoring credentials instead of hardcoding them |
Built-in Code Editor
upti.my provides a built-in code editor for writing and editing your Playwright scripts directly in the dashboard. The editor includes syntax highlighting, making it easy to write and maintain your monitoring scripts without switching between tools.
Example Script
Here is a simple Playwright script that verifies a login flow works correctly:
const { page, step, expect, env } = context;
await step("Navigate to the login page", async () => {
await page.goto(env.APP_URL || "https://app.example.com/login");
});
await step("Fill in credentials", async () => {
await page.fill("#email", env.MONITOR_EMAIL);
await page.fill("#password", env.MONITOR_PASSWORD);
});
await step("Submit and wait for the dashboard", async () => {
await page.click('button[type="submit"]');
await page.waitForSelector(".dashboard-header", {
timeout: 10000,
});
});
await step("Verify the dashboard loaded correctly", async () => {
const title = await page.textContent(".dashboard-header");
expect(title).toContain("Dashboard");
});
console.log("Login check passed successfully");đĄ Script Best Practices
Keep your scripts focused on critical user paths. Wrap each logical phase in a step with a descriptive name so failures pinpoint exactly what broke. Use explicit waits (waitForSelector) instead of fixed timeouts, and keep credentials and target URLs in env rather than hardcoding them.
Response Data
Each Playwright health check execution captures the following data:
| Field | Description |
|---|---|
| Execution Logs | Post-run output from the script, including console.log statements, browser errors, and failed assertions |
| Stack Trace | Error stack trace showing where the script failed when an exception or assertion error occurs |
| Screenshots | Captured screenshots showing the browser state during execution |
| Duration | Total time taken to execute the entire script in milliseconds |
Common Use Cases
- Login Flows - Verify that users can sign in and reach the dashboard
- Checkout Processes - Ensure e-commerce checkout flows work end to end
- Form Submissions - Validate that contact forms, sign-up forms, and surveys submit correctly
- Search Functionality - Test that search returns relevant results
- Third-Party Integrations - Check that embedded widgets, payment forms, and analytics load properly
- Single-Page Applications - Monitor SPAs where content loads dynamically via JavaScript
Advanced Example
Here is a more advanced script that checks a search feature and validates the results:
const { page, step, expect } = context;
await step("Open the storefront", async () => {
await page.goto("https://shop.example.com");
});
await step("Search for a product", async () => {
await page.fill('input[name="search"]', "wireless headphones");
await page.press('input[name="search"]', "Enter");
await page.waitForSelector(".search-results", {
timeout: 15000,
});
});
await step("Verify results are displayed", async () => {
const resultCount = await page.locator(".product-card").count();
expect(resultCount > 0).toBe(true);
console.log("Found " + resultCount + " products");
});â ī¸ Execution Limits
Playwright synthetic checks are available on Growth, Scale, and Enterprise plans. They count toward your regular healthcheck limit rather than a separate synthetic check quota. Scripts also have a maximum execution time based on your plan. Keep scripts concise and focused on the critical path.
âšī¸ Dedicated Monitoring Credentials
Create dedicated monitoring accounts for your Playwright checks rather than using personal credentials. This avoids interference with real user sessions and makes it easy to identify monitoring traffic in your application logs.