The Worker class represents a WebWorker or Service Worker. Worker event is emitted on the page object to signal a worker creation.
page.on('worker', worker => {
console.log(`Worker created: ${worker.url()}`);
});
Events
close
Emitted when the worker is closed.
worker.on('close', worker => {
console.log('Worker closed');
});
console
Emitted when JavaScript within the worker calls console.log or other console API methods.
worker.on('console', msg => {
console.log(`Worker console: ${msg.text()}`);
});
You need to subscribe to the ‘console’ event before the worker sends any console messages.
Methods
url
Returns the URL of the worker.
Returns: string - Worker URL
page.on('worker', worker => {
console.log(`Worker URL: ${worker.url()}`);
});
evaluate
Evaluates a function in the worker context.
Function to be evaluated in the worker context
Optional argument to pass to the function
Returns: Promise<R> - Promise that resolves to the return value
const worker = await page.waitForEvent('worker');
const result = await worker.evaluate(() => {
return self.location.href;
});
console.log(result);
evaluateHandle
Evaluates a function in the worker context and returns a JSHandle.
Optional argument to pass to the function
Returns: Promise<JSHandle> - Promise that resolves to a JSHandle
const workerHandle = await worker.evaluateHandle(() => self);
waitForEvent
Waits for an event to fire and returns its value.
Event name (e.g., ‘close’, ‘console’)
Optional waiting parameters
Returns: Promise<any> - Promise that resolves to the event data
const closePromise = worker.waitForEvent('close');
// ... do something that closes the worker
await closePromise;
Examples
Monitoring worker creation
import { test, expect } from '@playwright/test';
test('monitor workers', async ({ page }) => {
await page.goto('https://example.com');
// Listen for workers
page.on('worker', worker => {
console.log(`Worker created: ${worker.url()}`);
// Listen for console messages from worker
worker.on('console', msg => {
console.log(`Worker console: ${msg.text()}`);
});
// Listen for worker close
worker.on('close', () => {
console.log('Worker terminated');
});
});
// Trigger worker creation
await page.evaluate(() => {
new Worker('/worker.js');
});
});
Communicating with workers
test('communicate with worker', async ({ page }) => {
await page.goto('https://example.com');
const workerPromise = page.waitForEvent('worker');
await page.evaluate(() => {
const worker = new Worker('/worker.js');
worker.postMessage({ type: 'start', value: 42 });
});
const worker = await workerPromise;
// Evaluate code in worker context
const result = await worker.evaluate(() => {
return 'Worker is running';
});
console.log(result);
});
Testing Service Workers
test('service worker', async ({ page, context }) => {
await context.grantPermissions(['notifications']);
await page.goto('https://example.com');
// Register service worker
await page.evaluate(() => {
return navigator.serviceWorker.register('/sw.js');
});
// Wait for service worker
const serviceWorker = await context.waitForEvent('serviceworker');
console.log(`Service worker URL: ${serviceWorker.url()}`);
// Evaluate in service worker context
const swVersion = await serviceWorker.evaluate(() => {
return self.registration.scope;
});
console.log(`Service worker scope: ${swVersion}`);
});
Accessing worker from page
test('access workers from page', async ({ page }) => {
await page.goto('https://example.com');
// Create a worker
await page.evaluate(() => {
new Worker('/worker.js');
});
// Wait for worker to be created
await page.waitForEvent('worker');
// Access workers
const workers = page.workers();
console.log(`Active workers: ${workers.length}`);
for (const worker of workers) {
console.log(`Worker URL: ${worker.url()}`);
}
});
Best practices
Always set up event listeners (console, close) before the worker is created to avoid missing events.
Workers run in a separate execution context from the page. They don’t have access to the DOM or the page’s JavaScript scope.