A high-level API to automate Chromium
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Request and response interception, network monitoring, and request routing capabilities for comprehensive network testing and automation scenarios.
Monitor and inspect HTTP requests made by the page, including headers, body, and timing information.
/**
* HTTP request representation and inspection
*/
interface Request {
/** Get request URL */
url(): string;
/** Get HTTP method */
method(): string;
/** Get request headers */
headers(): { [key: string]: string; };
/** Get request body as string */
postData(): string | null;
/** Get request body as JSON */
postDataJSON(): any | null;
/** Get request body as buffer */
postDataBuffer(): Buffer | null;
/** Get frame that initiated request */
frame(): Frame;
/** Check if this is a navigation request */
isNavigationRequest(): boolean;
/** Get request that was redirected to this one */
redirectedFrom(): Request | null;
/** Get request this was redirected to */
redirectedTo(): Request | null;
/** Get failure details if request failed */
failure(): { errorText: string; } | null;
/** Get request timing information */
timing(): RequestTiming;
/** Get resource type */
resourceType(): string;
/** Get associated response */
response(): Promise<Response | null>;
/** Get request and response sizes */
sizes(): Promise<RequestSizes>;
/** Get all headers (including multiple values) */
allHeaders(): Promise<{ [key: string]: string; }>;
/** Get headers array */
headersArray(): Promise<{ name: string; value: string; }[]>;
/** Get header value */
headerValue(name: string): Promise<string | null>;
}Usage Examples:
// Monitor all requests
page.on('request', request => {
console.log(`${request.method()} ${request.url()}`);
console.log('Headers:', request.headers());
if (request.postData()) {
console.log('Body:', request.postData());
}
});
// Filter specific requests
page.on('request', request => {
if (request.url().includes('/api/')) {
console.log('API request:', request.url());
console.log('Resource type:', request.resourceType());
}
});
// Check request properties
page.on('request', async request => {
const timing = request.timing();
const response = await request.response();
if (response) {
console.log(`Request took: ${timing.responseEnd - timing.requestStart}ms`);
}
});Access and analyze HTTP responses including status, headers, and body content.
/**
* HTTP response representation and data access
*/
interface Response {
/** Get response URL */
url(): string;
/** Get HTTP status code */
status(): number;
/** Get status text */
statusText(): string;
/** Get response headers */
headers(): { [key: string]: string; };
/** Get all headers (including multiple values) */
allHeaders(): Promise<{ [key: string]: string; }>;
/** Get headers array */
headersArray(): Promise<{ name: string; value: string; }[]>;
/** Get single header value */
headerValue(name: string): Promise<string | null>;
/** Get multiple header values */
headerValues(name: string): Promise<string[]>;
/** Parse response as JSON */
json(): Promise<any>;
/** Get response as text */
text(): Promise<string>;
/** Get response as buffer */
body(): Promise<Buffer>;
/** Check if status indicates success (200-299) */
ok(): boolean;
/** Get originating request */
request(): Request;
/** Get associated frame */
frame(): Frame;
/** Get TLS security details */
securityDetails(): SecurityDetails | null;
/** Get server address */
serverAddr(): ServerAddr | null;
/** Get response sizes */
sizes(): Promise<ResponseSizes>;
}Usage Examples:
// Monitor responses
page.on('response', async response => {
console.log(`${response.status()} ${response.url()}`);
if (!response.ok()) {
console.log('Failed response:', response.statusText());
}
if (response.url().includes('/api/data')) {
const data = await response.json();
console.log('API data:', data);
}
});
// Check response details
page.on('response', async response => {
const headers = response.headers();
const contentType = headers['content-type'];
if (contentType?.includes('application/json')) {
try {
const json = await response.json();
console.log('JSON response:', json);
} catch (error) {
console.log('Invalid JSON response');
}
}
});
// Security information
page.on('response', response => {
const security = response.securityDetails();
if (security) {
console.log('TLS protocol:', security.protocol);
console.log('Certificate issuer:', security.issuer);
}
});Intercept and modify network requests, provide custom responses, or block requests entirely.
/**
* Route handler for intercepting and modifying requests
*/
interface Route {
/** Fulfill request with custom response */
fulfill(response: RouteFullfillResponse): Promise<void>;
/** Continue request with optional modifications */
continue(overrides?: RouteContinueOverrides): Promise<void>;
/** Abort the request with error code */
abort(errorCode?: string): Promise<void>;
/** Fetch request and get response for inspection */
fetch(overrides?: RouteFetchOverrides): Promise<APIResponse>;
/** Fall back to default request handling */
fallback(overrides?: RouteFallbackOverrides): Promise<void>;
/** Get original request */
request(): Request;
}
/**
* Set up request routing
* @param url - URL pattern to match
* @param handler - Route handler function
*/
route(url: string | RegExp | ((url: URL) => boolean), handler: (route: Route) => void): Promise<void>;
/**
* Remove request routing
* @param url - URL pattern
* @param handler - Handler to remove (optional)
*/
unroute(url: string | RegExp | ((url: URL) => boolean), handler?: (route: Route) => void): Promise<void>;Usage Examples:
// Mock API responses
await page.route('**/api/users', route => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
])
});
});
// Modify request headers
await page.route('**/api/**', route => {
route.continue({
headers: {
...route.request().headers(),
'Authorization': 'Bearer fake-token'
}
});
});
// Block requests
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Conditional routing
await page.route('**/api/data', async route => {
const request = route.request();
if (request.method() === 'POST') {
// Mock POST response
route.fulfill({
status: 201,
body: JSON.stringify({ success: true })
});
} else {
// Let GET requests through
route.continue();
}
});
// Fetch and modify response
await page.route('**/api/config', async route => {
const response = await route.fetch();
const body = await response.json();
// Modify response data
body.environment = 'test';
route.fulfill({
status: response.status(),
headers: response.headers(),
body: JSON.stringify(body)
});
});Record and replay network traffic using HAR files for testing and debugging.
/**
* Route requests using HAR file
* @param har - Path to HAR file
* @param options - HAR routing options
*/
routeFromHAR(har: string, options?: RouteFromHAROptions): Promise<void>;Usage Examples:
// Route from HAR file
await context.routeFromHAR('recordings/api-calls.har', {
url: '**/api/**',
update: false // Use recorded responses
});
// Update HAR file with new responses
await context.routeFromHAR('recordings/api-calls.har', {
url: '**/api/**',
update: true // Record new responses
});
// Route specific URLs from HAR
await context.routeFromHAR('recordings/full-session.har', {
url: /.*\.(css|js|png|jpg)$/,
update: false
});// Page-level network events
page.on('request', (request: Request) => void);
page.on('response', (response: Response) => void);
page.on('requestfailed', (request: Request) => void);
page.on('requestfinished', (request: Request) => void);
// Context-level network events (for all pages)
context.on('request', (request: Request) => void);
context.on('response', (response: Response) => void);
context.on('requestfailed', (request: Request) => void);
context.on('requestfinished', (request: Request) => void);Usage Examples:
// Track failed requests
page.on('requestfailed', request => {
const failure = request.failure();
console.log(`Request failed: ${request.url()}`);
console.log(`Error: ${failure?.errorText}`);
});
// Monitor request completion
page.on('requestfinished', async request => {
const response = await request.response();
const timing = request.timing();
console.log(`${request.method()} ${request.url()}`);
console.log(`Status: ${response?.status()}`);
console.log(`Duration: ${timing.responseEnd - timing.requestStart}ms`);
});
// Context-wide monitoring
context.on('request', request => {
if (request.resourceType() === 'xhr') {
console.log('AJAX request:', request.url());
}
});interface RouteFullfillResponse {
/** HTTP status code */
status?: number;
/** Response headers */
headers?: { [key: string]: string; };
/** Response body */
body?: string | Buffer;
/** Content type header */
contentType?: string;
/** Response body as JSON (automatically serialized) */
json?: any;
/** Response body from file path */
path?: string;
}
interface RouteContinueOverrides {
/** Override request URL */
url?: string;
/** Override HTTP method */
method?: string;
/** Override request headers */
headers?: { [key: string]: string; };
/** Override request body */
postData?: string | Buffer;
}
interface RouteFetchOverrides {
/** Override request URL */
url?: string;
/** Override HTTP method */
method?: string;
/** Override request headers */
headers?: { [key: string]: string; };
/** Override request body */
postData?: string | Buffer;
/** Request timeout */
timeout?: number;
}
interface RouteFromHAROptions {
/** URL pattern to match */
url?: string | RegExp;
/** Whether to update HAR with new responses */
update?: boolean;
/** Update if missing in HAR */
updateContent?: 'embed' | 'attach';
/** Update mode for existing entries */
updateMode?: 'full' | 'minimal';
}interface RequestTiming {
/** Request start time */
startTime: number;
/** Domain lookup start */
domainLookupStart: number;
/** Domain lookup end */
domainLookupEnd: number;
/** Connect start */
connectStart: number;
/** Secure connection start */
secureConnectionStart: number;
/** Connect end */
connectEnd: number;
/** Request start */
requestStart: number;
/** Response start */
responseStart: number;
/** Response end */
responseEnd: number;
}
interface RequestSizes {
/** Request header bytes */
requestHeadersSize: number;
/** Request body bytes */
requestBodySize: number;
/** Response header bytes */
responseHeadersSize: number;
/** Response body bytes */
responseBodySize: number;
}
interface ResponseSizes {
/** Response header bytes */
responseHeadersSize: number;
/** Response body bytes */
responseBodySize: number;
}
interface SecurityDetails {
/** TLS protocol version */
protocol: string;
/** Certificate issuer */
issuer: string;
/** Certificate subject name */
subjectName: string;
/** Certificate valid from */
validFrom: number;
/** Certificate valid to */
validTo: number;
}
interface ServerAddr {
/** Server IP address */
ipAddress: string;
/** Server port */
port: number;
}type NetworkErrorCode =
| 'aborted'
| 'accessdenied'
| 'addressunreachable'
| 'blockedbyclient'
| 'blockedbyresponse'
| 'connectionaborted'
| 'connectionclosed'
| 'connectionfailed'
| 'connectionrefused'
| 'connectionreset'
| 'internetdisconnected'
| 'namenotresolved'
| 'timedout'
| 'failed';Usage Examples:
// Abort with specific error
await page.route('**/slow-api/**', route => {
route.abort('timedout');
});
// Handle different error types
page.on('requestfailed', request => {
const failure = request.failure();
switch (failure?.errorText) {
case 'net::ERR_INTERNET_DISCONNECTED':
console.log('No internet connection');
break;
case 'net::ERR_CONNECTION_TIMED_OUT':
console.log('Request timed out');
break;
default:
console.log('Request failed:', failure?.errorText);
}
});Install with Tessl CLI
npx tessl i tessl/npm-playwright-chromium