Run Playwright locally

Updated April 28, 2026

Mirror the Hyperping browser-check runtime on your laptop. Same Playwright version, same package set, same timeout cap, so a script that passes locally runs the same way in production. Pick the runtime that matches your monitor and follow the install for that version.

Default runtime
2026.05 ยท Node 24 ยท Playwright 1.59.1
Legacy runtime
2023.04 ยท Node 16 ยท Playwright 1.33
Browser
Chromium, headless
Run cap
2 minutes per run
๐Ÿ“˜Pick the runtime first

Open the monitor in Hyperping and check the runtime card. Install Playwright at the version that matches it, otherwise locator behavior, fixture syntax, and reporter output can drift between local and production.

Install

Runtime 2026.05

Node 24 with Playwright 1.59.1. Web Vitals are collected by the runtime, so they only appear once the check runs in Hyperping.

TerminalBASH
mkdir hyperping-browser-checks
cd hyperping-browser-checks
npm init -y

# Playwright versions used by the 2026.05 runtime
npm install playwright@1.59.1 @playwright/test@1.59.1

# Same package set as the runtime
npm install typescript@^5.6 expect@^29 uuid@^9.0.1 \
  lodash@4.17.21 moment@^2.30.1 axios@^1.13.2 \
  btoa@1.2.1 jsonwebtoken@^9.0.2 date-fns@^2.30.0 crypto-js@^4.2.0

# Download Chromium
npx playwright install chromium

Runtime 2023.04

Node 16 with Playwright 1.33. Use this only if the monitor is still on the 2023.04 runtime.

TerminalBASH
mkdir hyperping-browser-checks
cd hyperping-browser-checks
npm init -y

# Playwright versions used by the 2023.04 runtime
npm install playwright@1.33.0 @playwright/test@1.33.0

# Same package set as the runtime
npm install typescript@^5.0.4 expect@^27.5.1 uuid@^9.0.0 \
  lodash@4.17.21 moment@^2.29.4 axios@^1.4.0 \
  btoa@1.2.1 jsonwebtoken@^9.0.0 date-fns@^2.30.0 crypto-js@^4.1.1

# Download Chromium
npx playwright install chromium

Configure Playwright

Match the run cap and the workers count Hyperping uses. The 2-minute global timeout is the most common gotcha, scripts that pass locally with no cap will fail in production when they sneak past 120 seconds.

playwright.config.jsJS
// playwright.config.js
const config = {
  globalTimeout: 120 * 1000, // match Hyperping's 2-minute run cap
  workers: 1,
  expect: { timeout: 30 * 1000 },
  projects: [
    {
      name: 'chromium',
      use: {
        viewport: { width: 1280, height: 720 },
        deviceScaleFactor: 1,
        defaultBrowserType: 'chromium',
      },
    },
  ],
};

export default config;

Write your first test

Drop a script under tests/ and run it. Playwright auto-detects .spec.ts and .spec.js files in that directory.

tests/example.spec.tsTS
// tests/example.spec.ts
import { test, expect } from '@playwright/test';

test('homepage renders', async ({ page }) => {
  await page.goto('https://example.com');
  await expect(page).toHaveTitle(/Example Domain/);
  await expect(page.locator('h1')).toContainText('Example Domain');
});

Run with a visible browser

Hyperping runs scripts headless. Locally you'll usually want a visible browser while you're authoring, so you can see exactly what the script does.

HeadedBASH
npx playwright test --headed

For step-by-step debugging, open the Playwright Inspector:

DebugBASH
npx playwright test --debug

After a run, the HTML report shows traces, screenshots, and the step tree:

ReportBASH
npx playwright show-report

Environment variables

Hyperping injects environment variables at run time and exposes them as process.env.NAME. Mirror that locally with a .env file or shell exports so the same script works in both places.

.envBASH
# .env
EMAIL=test@example.com
PASSWORD=changeme
API_TOKEN=...
BASE_URL=https://staging.your-app.com

Use the bundled package set

Lodash, moment, axios, date-fns, and the other libraries that ship with the runtime are all available in your script. Importing them locally with the same versions keeps the behavior identical.

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

test('cart roundtrip', async ({ page }) => {
  test.setTimeout(120_000);

  await page.goto(process.env.BASE_URL);
  await page.click('[data-testid="add-to-cart"]');
  await expect(page.locator('.cart-count')).toHaveText('1');

  // Cross-check via the API
  const { data } = await axios.get(`${process.env.BASE_URL}/api/cart`, {
    headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
  });
  expect(data.items).toHaveLength(1);
});

Available packages

Runtime 2026.05 12 packages

playwright1.59.1
Browser automation API.
@playwright/test1.59.1
Test runner with fixtures, locators, and expect.
typescript^5.6
TypeScript compiler.
expect^29
Standalone Jest-style assertion library.
uuid^9.0.1
RFC4122 UUIDs.
lodash4.17.21
Array, object, and collection utilities.
moment^2.30.1
Date and time parsing and arithmetic.
axios^1.13.2
HTTP client for API cross-checks.
btoa1.2.1
Base64 encoding for Node.
jsonwebtoken^9.0.2
Sign and verify JWTs.
date-fns^2.30.0
Modular date utilities.
crypto-js^4.2.0
Hashes, HMAC, and symmetric ciphers.

Runtime 2023.04 12 packages

playwright^1.33.0
Browser automation API.
@playwright/test1.33
Test runner.
typescript^5.0.4
TypeScript compiler.
expect^27.5.1
Standalone assertion library.
uuid^9.0.0
RFC4122 UUIDs.
lodash4.17.21
Utility functions.
moment^2.29.4
Date and time helpers.
axios^1.4.0
HTTP client.
btoa1.2.1
Base64 encoding for Node.
jsonwebtoken^9.0.0
JWT sign and verify.
date-fns^2.30.0
Modular date utilities.
crypto-js^4.1.1
Hashes, HMAC, ciphers.

Move the script to Hyperping

Step 01
Create a Browser monitor
In app.hyperping.io click New monitor, pick Browser, and select the matching runtime.
Step 02
Paste the script and add secrets
Copy the test body straight into the editor. Add every process.env.NAME reference under Environment variables in the settings panel.
Step 03
Run, then schedule
Click Run to execute the script once on a Hyperping droplet. When it passes, save the monitor to put it on the schedule.

Best practices

Habits that survive the move to production 5 rules

Stable selectorsrole / data-testid
Use getByRole and getByTestId instead of CSS classes. Stylesheet rewrites won't break them.
Auto-waiting assertionsexpect()
await expect(locator).toBeVisible() retries on its own. Most waitForTimeout calls are unnecessary and add flake.
Stay under 2 minutesrun cap
Split long journeys into separate checks. One mega-test fails the whole flow when one step times out.
Secrets in env varsprocess.env
Never paste tokens into the script body. Anything sensitive belongs in Environment variables.
Log the values you watchconsole.log
A console.log for latency, counts, or IDs lands in the run logs and makes post-mortem analysis easier.

Where to go next