CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-puppeteer-core

A high-level API to control headless Chrome and Firefox browsers over the DevTools Protocol and WebDriver BiDi

94

1.02x
Overview
Eval results
Files

network-management.mddocs/

Network Management

Request interception, response mocking, and comprehensive network monitoring for testing and debugging.

Capabilities

HTTPRequest Interface

Represents an HTTP request that can be intercepted, modified, or monitored.

interface HTTPRequest {
  /** Get request URL */
  url(): string;
  /** Get resource type */
  resourceType(): ResourceType;
  /** Get HTTP method */
  method(): string;
  /** Get request headers */
  headers(): Record<string, string>;
  /** Get POST data */
  postData(): string | undefined;
  /** Get POST data as buffer */
  postDataBuffer(): Buffer | undefined;
  /** Check if request is navigation request */
  isNavigationRequest(): boolean;
  /** Check if request is intercepted */
  isInterceptResolutionHandled(): boolean;
  /** Get response */
  response(): HTTPResponse | null;
  /** Get frame that initiated request */
  frame(): Frame | null;
  /** Get redirect chain */
  redirectChain(): HTTPRequest[];
  /** Get failure details if request failed */
  failure(): { errorText: string } | null;
  /** Abort request */
  abort(errorCode?: ErrorCode): Promise<void>;
  /** Continue request with optional overrides */
  continue(overrides?: ContinueRequestOverrides): Promise<void>;
  /** Respond to request with mock response */
  respond(response: ResponseForRequest): Promise<void>;
  /** Get request initiator */
  initiator(): Initiator;
  /** Check if request has POST data */
  hasPostData(): boolean;
}

type ResourceType = 
  | "document" 
  | "stylesheet" 
  | "image" 
  | "media" 
  | "font" 
  | "script" 
  | "texttrack" 
  | "xhr" 
  | "fetch" 
  | "prefetch" 
  | "eventsource" 
  | "websocket" 
  | "manifest" 
  | "signedexchange" 
  | "ping" 
  | "cspviolationreport" 
  | "preflight" 
  | "other";

type ErrorCode = 
  | "aborted" 
  | "accessdenied" 
  | "addressunreachable" 
  | "blockedbyclient" 
  | "blockedbyresponse" 
  | "connectionaborted" 
  | "connectionclosed" 
  | "connectionfailed" 
  | "connectionrefused" 
  | "connectionreset" 
  | "internetdisconnected" 
  | "namenotresolved" 
  | "timedout" 
  | "failed";

interface ContinueRequestOverrides {
  /** Override URL */
  url?: string;
  /** Override method */
  method?: string;
  /** Override POST data */
  postData?: string;
  /** Override headers */
  headers?: Record<string, string>;
}

interface ResponseForRequest {
  /** Response status code */
  status?: number;
  /** Response headers */
  headers?: Record<string, string>;
  /** Response body */
  body?: string | Buffer;
  /** Content type header */
  contentType?: string;
}

interface Initiator {
  /** Type of initiator */
  type: "parser" | "script" | "preload" | "SignedExchange" | "preflight" | "other";
  /** Stack trace if initiated by script */
  stack?: CallFrame[];
  /** URL if initiated by parser */
  url?: string;
  /** Line number */
  lineNumber?: number;
  /** Column number */
  columnNumber?: number;
}

interface CallFrame {
  functionName: string;
  scriptId: string;
  url: string;
  lineNumber: number;
  columnNumber: number;
}

Usage Examples:

import puppeteer from "puppeteer-core";

const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });
const page = await browser.newPage();

// Enable request interception
await page.setRequestInterception(true);

// Basic request monitoring
page.on("request", (request) => {
  console.log("Request:", request.method(), request.url());
  console.log("Resource type:", request.resourceType());
  console.log("Headers:", request.headers());
  
  // Continue all requests normally
  request.continue();
});

// Block specific resource types
page.on("request", (request) => {
  if (request.resourceType() === "image") {
    request.abort("blockedbyclient");
  } else {
    request.continue();
  }
});

// Modify requests
page.on("request", (request) => {
  const overrides: ContinueRequestOverrides = {};
  
  // Add custom header
  overrides.headers = {
    ...request.headers(),
    "X-Custom-Header": "custom-value"
  };
  
  // Modify user agent
  if (request.headers()["user-agent"]) {
    overrides.headers["user-agent"] = "Custom-User-Agent/1.0";
  }
  
  request.continue(overrides);
});

// Mock API responses
page.on("request", (request) => {
  if (request.url().includes("/api/users")) {
    request.respond({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([
        { id: 1, name: "John Doe" },
        { id: 2, name: "Jane Smith" }
      ])
    });
  } else {
    request.continue();
  }
});

await page.goto("https://example.com");
await browser.close();

HTTPResponse Interface

Represents an HTTP response received from the server.

interface HTTPResponse {
  /** Get response URL */
  url(): string;
  /** Check if response is successful (200-299) */
  ok(): boolean;
  /** Get status code */
  status(): number;
  /** Get status text */
  statusText(): string;
  /** Get response headers */
  headers(): Record<string, string>;
  /** Get security details for HTTPS */
  securityDetails(): SecurityDetails | null;
  /** Get request that produced this response */
  request(): HTTPRequest;
  /** Check if response was served from cache */
  fromCache(): boolean;
  /** Check if response was served from service worker */
  fromServiceWorker(): boolean;
  /** Get frame that received this response */
  frame(): Frame | null;
  /** Get response body as text */
  text(): Promise<string>;
  /** Get response body as JSON */
  json(): Promise<any>;
  /** Get response body as buffer */
  buffer(): Promise<Buffer>;
  /** Get timing information */
  timing(): ResponseTiming | null;
  /** Get remote address */
  remoteAddress(): RemoteAddress;
}

interface SecurityDetails {
  /** Subject name */
  subjectName(): string;
  /** Issuer name */
  issuer(): string;
  /** Valid from timestamp */
  validFrom(): number;
  /** Valid to timestamp */
  validTo(): number;
  /** Protocol version */
  protocol(): string;
  /** Subject alternative names */
  subjectAlternativeNames(): string[];
}

interface ResponseTiming {
  /** Request start time */
  requestTime: number;
  /** Proxy start time */
  proxyStart: number;
  /** Proxy end time */
  proxyEnd: number;
  /** DNS start time */
  dnsStart: number;
  /** DNS end time */
  dnsEnd: number;
  /** Connect start time */
  connectStart: number;
  /** Connect end time */
  connectEnd: number;
  /** SSL start time */
  sslStart: number;
  /** SSL end time */
  sslEnd: number;
  /** Worker start time */
  workerStart: number;
  /** Worker ready time */
  workerReady: number;
  /** Send start time */
  sendStart: number;
  /** Send end time */
  sendEnd: number;
  /** Push start time */
  pushStart: number;
  /** Push end time */
  pushEnd: number;
  /** Receive headers end time */
  receiveHeadersEnd: number;
}

interface RemoteAddress {
  /** IP address */
  ip: string;
  /** Port number */
  port: number;
}

Usage Examples:

// Response monitoring
page.on("response", async (response) => {
  console.log("Response:", response.status(), response.url());
  console.log("Headers:", response.headers());
  console.log("From cache:", response.fromCache());
  console.log("From service worker:", response.fromServiceWorker());
  
  if (!response.ok()) {
    console.log("Failed response:", response.statusText());
  }
  
  // Get response body for specific URLs
  if (response.url().includes("/api/")) {
    const body = await response.text();
    console.log("API Response body:", body);
  }
});

// Security information for HTTPS
page.on("response", (response) => {
  const security = response.securityDetails();
  if (security) {
    console.log("Certificate subject:", security.subjectName());
    console.log("Certificate issuer:", security.issuer());
    console.log("Protocol:", security.protocol());
  }
});

// Performance monitoring
page.on("response", (response) => {
  const timing = response.timing();
  if (timing) {
    const totalTime = timing.receiveHeadersEnd - timing.requestTime;
    console.log(`Request to ${response.url()} took ${totalTime}ms`);
  }
});

Request Interception Patterns

Common patterns for request interception and modification:

interface RequestInterceptionPatterns {
  /** Block resources by type or URL pattern */
  blockResources(patterns: ResourceBlockPattern[]): void;
  /** Mock API endpoints */
  mockAPIs(mocks: APIMock[]): void;
  /** Add authentication headers */
  addAuth(token: string): void;
  /** Modify user agent */
  setUserAgent(userAgent: string): void;
  /** Add CORS headers to responses */
  enableCORS(): void;
  /** Log all network activity */
  logAllRequests(): void;
}

interface ResourceBlockPattern {
  resourceType?: ResourceType;
  urlPattern?: string | RegExp;
  errorCode?: ErrorCode;
}

interface APIMock {
  urlPattern: string | RegExp;
  method?: string;
  response: ResponseForRequest;
}

Usage Examples:

// Block images and stylesheets for faster loading
await page.setRequestInterception(true);

page.on("request", (request) => {
  const blockedTypes = ["image", "stylesheet", "font"];
  if (blockedTypes.includes(request.resourceType())) {
    request.abort("blockedbyclient");
  } else {
    request.continue();
  }
});

// Mock multiple API endpoints
const apiMocks = [
  {
    url: "/api/users",
    response: {
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([{ id: 1, name: "Test User" }])
    }
  },
  {
    url: "/api/config",
    response: {
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({ theme: "dark", version: "1.0.0" })
    }
  }
];

page.on("request", (request) => {
  const mock = apiMocks.find(m => request.url().includes(m.url));
  if (mock) {
    request.respond(mock.response);
  } else {
    request.continue();
  }
});

// Add authentication to all API requests
page.on("request", (request) => {
  if (request.url().includes("/api/")) {
    const headers = {
      ...request.headers(),
      "Authorization": "Bearer your-token-here"
    };
    request.continue({ headers });
  } else {
    request.continue();
  }
});

// Comprehensive request logging
page.on("request", (request) => {
  console.log(`→ ${request.method()} ${request.url()}`);
  console.log(`  Type: ${request.resourceType()}`);
  console.log(`  Headers:`, request.headers());
  
  if (request.postData()) {
    console.log(`  POST data:`, request.postData());
  }
  
  request.continue();
});

page.on("response", async (response) => {
  console.log(`← ${response.status()} ${response.url()}`);
  console.log(`  Headers:`, response.headers());
  
  if (response.url().includes("/api/")) {
    const body = await response.text();
    console.log(`  Body:`, body);
  }
});

page.on("requestfailed", (request) => {
  const failure = request.failure();
  console.log(`✗ ${request.url()} failed: ${failure?.errorText}`);
});

Network Events

Page-level network events for monitoring and debugging:

interface NetworkEvents {
  /** Emitted when request starts */
  "request": (request: HTTPRequest) => void;
  /** Emitted when response received */
  "response": (response: HTTPResponse) => void;
  /** Emitted when request completes successfully */
  "requestfinished": (request: HTTPRequest) => void;
  /** Emitted when request fails */
  "requestfailed": (request: HTTPRequest) => void;
}

Usage Examples:

// Network event monitoring
const networkEvents = [];

page.on("request", (request) => {
  networkEvents.push({
    type: "request",
    url: request.url(),
    method: request.method(),
    timestamp: Date.now()
  });
});

page.on("response", (response) => {
  networkEvents.push({
    type: "response",
    url: response.url(),
    status: response.status(),
    timestamp: Date.now()
  });
});

page.on("requestfailed", (request) => {
  const failure = request.failure();
  networkEvents.push({
    type: "requestfailed",
    url: request.url(),
    error: failure?.errorText,
    timestamp: Date.now()
  });
});

// Analyze network activity after page load
await page.goto("https://example.com");
await page.waitForLoadState("networkidle");

console.log("Network activity summary:");
console.log(`Total requests: ${networkEvents.filter(e => e.type === "request").length}`);
console.log(`Successful responses: ${networkEvents.filter(e => e.type === "response").length}`);
console.log(`Failed requests: ${networkEvents.filter(e => e.type === "requestfailed").length}`);

Advanced Network Features

Advanced networking capabilities and utilities:

interface AdvancedNetworkFeatures {
  /** Wait for specific request/response */
  waitForRequest(urlOrPredicate: string | ((req: HTTPRequest) => boolean), options?: WaitForOptions): Promise<HTTPRequest>;
  waitForResponse(urlOrPredicate: string | ((res: HTTPResponse) => boolean), options?: WaitForOptions): Promise<HTTPResponse>;
  /** Capture network traffic */
  captureNetworkTraffic(): NetworkCapture;
  /** Simulate network conditions */
  setNetworkConditions(conditions: NetworkConditions): Promise<void>;
  /** Set offline mode */
  setOfflineMode(enabled: boolean): Promise<void>;
  /** Set user agent */
  setUserAgent(userAgent: string, userAgentMetadata?: UserAgentMetadata): Promise<void>;
  /** Set extra HTTP headers */
  setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;
  /** Authenticate with HTTP credentials */
  authenticate(credentials: Credentials | null): Promise<void>;
}

interface NetworkCapture {
  /** Start capturing */
  start(): Promise<void>;
  /** Stop capturing and return data */
  stop(): Promise<NetworkTrafficEntry[]>;
}

interface NetworkTrafficEntry {
  request: {
    url: string;
    method: string;
    headers: Record<string, string>;
    postData?: string;
    timestamp: number;
  };
  response?: {
    status: number;
    headers: Record<string, string>;
    body: string;
    timestamp: number;
  };
  timing: ResponseTiming;
}

interface NetworkConditions {
  /** Download speed in bytes/sec */
  downloadThroughput: number;
  /** Upload speed in bytes/sec */
  uploadThroughput: number;
  /** Latency in milliseconds */
  latency: number;
  /** Offline mode */
  offline?: boolean;
}

interface WaitForOptions {
  /** Maximum wait time */
  timeout?: number;
  /** Wait for navigation to complete */
  waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
}

Usage Examples:

// Wait for specific requests/responses
const apiRequest = page.waitForRequest(req => 
  req.url().includes("/api/data") && req.method() === "POST"
);

const apiResponse = page.waitForResponse(res => 
  res.url().includes("/api/data") && res.status() === 200
);

// Trigger the requests
await page.click("#load-data-button");

// Wait for completion
const [request, response] = await Promise.all([apiRequest, apiResponse]);
console.log("API call completed:", response.status());

// Simulate slow network
await page.emulateNetworkConditions({
  downloadThroughput: 50 * 1024, // 50KB/s
  uploadThroughput: 20 * 1024,   // 20KB/s
  latency: 200                   // 200ms
});

// Test offline functionality
await page.setOfflineMode(true);
try {
  await page.goto("https://example.com");
} catch (error) {
  console.log("Page failed to load offline:", error.message);
}
await page.setOfflineMode(false);

// Set custom headers for all requests
await page.setExtraHTTPHeaders({
  "X-API-Key": "your-api-key",
  "X-Client-Version": "1.0.0"
});

// HTTP authentication
await page.authenticate({
  username: "testuser",
  password: "testpass"
});

Error Handling

Network-related error handling and debugging:

class NetworkError extends Error {
  constructor(message: string);
}

class RequestInterceptionError extends NetworkError {
  constructor(message: string);
}

class ResponseError extends NetworkError {
  constructor(message: string, response: HTTPResponse);
  response: HTTPResponse;
}

Usage Examples:

// Robust request interception with error handling
page.on("request", async (request) => {
  try {
    if (request.url().includes("/api/")) {
      // Validate request before continuing
      const headers = request.headers();
      if (!headers["authorization"]) {
        await request.respond({
          status: 401,
          body: JSON.stringify({ error: "Unauthorized" })
        });
        return;
      }
    }
    
    await request.continue();
  } catch (error) {
    console.log("Request interception error:", error.message);
    // Fallback: continue the request
    try {
      await request.continue();
    } catch (fallbackError) {
      console.log("Fallback failed:", fallbackError.message);
    }
  }
});

// Handle response errors gracefully
page.on("response", async (response) => {
  if (!response.ok()) {
    console.log(`HTTP ${response.status()} for ${response.url()}`);
    
    try {
      const body = await response.text();
      console.log("Error response body:", body);
    } catch (error) {
      console.log("Could not read error response body:", error.message);
    }
  }
});

// Retry failed requests
async function waitForResponseWithRetry(
  page: Page, 
  urlPattern: string, 
  maxRetries = 3
): Promise<HTTPResponse> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await page.waitForResponse(
        res => res.url().includes(urlPattern),
        { timeout: 10000 }
      );
      
      if (response.ok()) {
        return response;
      }
      
      console.log(`Attempt ${i + 1}: Response ${response.status()}`);
    } catch (error) {
      console.log(`Attempt ${i + 1} failed:`, error.message);
    }
    
    if (i < maxRetries - 1) {
      await page.waitForTimeout(1000 * (i + 1)); // Exponential backoff
    }
  }
  
  throw new NetworkError(`Failed to get successful response after ${maxRetries} attempts`);
}

Install with Tessl CLI

npx tessl i tessl/npm-puppeteer-core

docs

browser-contexts.md

browser-management.md

element-handling.md

index.md

input-simulation.md

locators-selectors.md

network-management.md

page-interaction.md

tile.json