0
# Network Management
1
2
Request interception, response mocking, and comprehensive network monitoring for testing and debugging.
3
4
## Capabilities
5
6
### HTTPRequest Interface
7
8
Represents an HTTP request that can be intercepted, modified, or monitored.
9
10
```typescript { .api }
11
interface HTTPRequest {
12
/** Get request URL */
13
url(): string;
14
/** Get resource type */
15
resourceType(): ResourceType;
16
/** Get HTTP method */
17
method(): string;
18
/** Get request headers */
19
headers(): Record<string, string>;
20
/** Get POST data */
21
postData(): string | undefined;
22
/** Get POST data as buffer */
23
postDataBuffer(): Buffer | undefined;
24
/** Check if request is navigation request */
25
isNavigationRequest(): boolean;
26
/** Check if request is intercepted */
27
isInterceptResolutionHandled(): boolean;
28
/** Get response */
29
response(): HTTPResponse | null;
30
/** Get frame that initiated request */
31
frame(): Frame | null;
32
/** Get redirect chain */
33
redirectChain(): HTTPRequest[];
34
/** Get failure details if request failed */
35
failure(): { errorText: string } | null;
36
/** Abort request */
37
abort(errorCode?: ErrorCode): Promise<void>;
38
/** Continue request with optional overrides */
39
continue(overrides?: ContinueRequestOverrides): Promise<void>;
40
/** Respond to request with mock response */
41
respond(response: ResponseForRequest): Promise<void>;
42
/** Get request initiator */
43
initiator(): Initiator;
44
/** Check if request has POST data */
45
hasPostData(): boolean;
46
}
47
48
type ResourceType =
49
| "document"
50
| "stylesheet"
51
| "image"
52
| "media"
53
| "font"
54
| "script"
55
| "texttrack"
56
| "xhr"
57
| "fetch"
58
| "prefetch"
59
| "eventsource"
60
| "websocket"
61
| "manifest"
62
| "signedexchange"
63
| "ping"
64
| "cspviolationreport"
65
| "preflight"
66
| "other";
67
68
type ErrorCode =
69
| "aborted"
70
| "accessdenied"
71
| "addressunreachable"
72
| "blockedbyclient"
73
| "blockedbyresponse"
74
| "connectionaborted"
75
| "connectionclosed"
76
| "connectionfailed"
77
| "connectionrefused"
78
| "connectionreset"
79
| "internetdisconnected"
80
| "namenotresolved"
81
| "timedout"
82
| "failed";
83
84
interface ContinueRequestOverrides {
85
/** Override URL */
86
url?: string;
87
/** Override method */
88
method?: string;
89
/** Override POST data */
90
postData?: string;
91
/** Override headers */
92
headers?: Record<string, string>;
93
}
94
95
interface ResponseForRequest {
96
/** Response status code */
97
status?: number;
98
/** Response headers */
99
headers?: Record<string, string>;
100
/** Response body */
101
body?: string | Buffer;
102
/** Content type header */
103
contentType?: string;
104
}
105
106
interface Initiator {
107
/** Type of initiator */
108
type: "parser" | "script" | "preload" | "SignedExchange" | "preflight" | "other";
109
/** Stack trace if initiated by script */
110
stack?: CallFrame[];
111
/** URL if initiated by parser */
112
url?: string;
113
/** Line number */
114
lineNumber?: number;
115
/** Column number */
116
columnNumber?: number;
117
}
118
119
interface CallFrame {
120
functionName: string;
121
scriptId: string;
122
url: string;
123
lineNumber: number;
124
columnNumber: number;
125
}
126
```
127
128
**Usage Examples:**
129
130
```typescript
131
import puppeteer from "puppeteer-core";
132
133
const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });
134
const page = await browser.newPage();
135
136
// Enable request interception
137
await page.setRequestInterception(true);
138
139
// Basic request monitoring
140
page.on("request", (request) => {
141
console.log("Request:", request.method(), request.url());
142
console.log("Resource type:", request.resourceType());
143
console.log("Headers:", request.headers());
144
145
// Continue all requests normally
146
request.continue();
147
});
148
149
// Block specific resource types
150
page.on("request", (request) => {
151
if (request.resourceType() === "image") {
152
request.abort("blockedbyclient");
153
} else {
154
request.continue();
155
}
156
});
157
158
// Modify requests
159
page.on("request", (request) => {
160
const overrides: ContinueRequestOverrides = {};
161
162
// Add custom header
163
overrides.headers = {
164
...request.headers(),
165
"X-Custom-Header": "custom-value"
166
};
167
168
// Modify user agent
169
if (request.headers()["user-agent"]) {
170
overrides.headers["user-agent"] = "Custom-User-Agent/1.0";
171
}
172
173
request.continue(overrides);
174
});
175
176
// Mock API responses
177
page.on("request", (request) => {
178
if (request.url().includes("/api/users")) {
179
request.respond({
180
status: 200,
181
contentType: "application/json",
182
body: JSON.stringify([
183
{ id: 1, name: "John Doe" },
184
{ id: 2, name: "Jane Smith" }
185
])
186
});
187
} else {
188
request.continue();
189
}
190
});
191
192
await page.goto("https://example.com");
193
await browser.close();
194
```
195
196
### HTTPResponse Interface
197
198
Represents an HTTP response received from the server.
199
200
```typescript { .api }
201
interface HTTPResponse {
202
/** Get response URL */
203
url(): string;
204
/** Check if response is successful (200-299) */
205
ok(): boolean;
206
/** Get status code */
207
status(): number;
208
/** Get status text */
209
statusText(): string;
210
/** Get response headers */
211
headers(): Record<string, string>;
212
/** Get security details for HTTPS */
213
securityDetails(): SecurityDetails | null;
214
/** Get request that produced this response */
215
request(): HTTPRequest;
216
/** Check if response was served from cache */
217
fromCache(): boolean;
218
/** Check if response was served from service worker */
219
fromServiceWorker(): boolean;
220
/** Get frame that received this response */
221
frame(): Frame | null;
222
/** Get response body as text */
223
text(): Promise<string>;
224
/** Get response body as JSON */
225
json(): Promise<any>;
226
/** Get response body as buffer */
227
buffer(): Promise<Buffer>;
228
/** Get timing information */
229
timing(): ResponseTiming | null;
230
/** Get remote address */
231
remoteAddress(): RemoteAddress;
232
}
233
234
interface SecurityDetails {
235
/** Subject name */
236
subjectName(): string;
237
/** Issuer name */
238
issuer(): string;
239
/** Valid from timestamp */
240
validFrom(): number;
241
/** Valid to timestamp */
242
validTo(): number;
243
/** Protocol version */
244
protocol(): string;
245
/** Subject alternative names */
246
subjectAlternativeNames(): string[];
247
}
248
249
interface ResponseTiming {
250
/** Request start time */
251
requestTime: number;
252
/** Proxy start time */
253
proxyStart: number;
254
/** Proxy end time */
255
proxyEnd: number;
256
/** DNS start time */
257
dnsStart: number;
258
/** DNS end time */
259
dnsEnd: number;
260
/** Connect start time */
261
connectStart: number;
262
/** Connect end time */
263
connectEnd: number;
264
/** SSL start time */
265
sslStart: number;
266
/** SSL end time */
267
sslEnd: number;
268
/** Worker start time */
269
workerStart: number;
270
/** Worker ready time */
271
workerReady: number;
272
/** Send start time */
273
sendStart: number;
274
/** Send end time */
275
sendEnd: number;
276
/** Push start time */
277
pushStart: number;
278
/** Push end time */
279
pushEnd: number;
280
/** Receive headers end time */
281
receiveHeadersEnd: number;
282
}
283
284
interface RemoteAddress {
285
/** IP address */
286
ip: string;
287
/** Port number */
288
port: number;
289
}
290
```
291
292
**Usage Examples:**
293
294
```typescript
295
// Response monitoring
296
page.on("response", async (response) => {
297
console.log("Response:", response.status(), response.url());
298
console.log("Headers:", response.headers());
299
console.log("From cache:", response.fromCache());
300
console.log("From service worker:", response.fromServiceWorker());
301
302
if (!response.ok()) {
303
console.log("Failed response:", response.statusText());
304
}
305
306
// Get response body for specific URLs
307
if (response.url().includes("/api/")) {
308
const body = await response.text();
309
console.log("API Response body:", body);
310
}
311
});
312
313
// Security information for HTTPS
314
page.on("response", (response) => {
315
const security = response.securityDetails();
316
if (security) {
317
console.log("Certificate subject:", security.subjectName());
318
console.log("Certificate issuer:", security.issuer());
319
console.log("Protocol:", security.protocol());
320
}
321
});
322
323
// Performance monitoring
324
page.on("response", (response) => {
325
const timing = response.timing();
326
if (timing) {
327
const totalTime = timing.receiveHeadersEnd - timing.requestTime;
328
console.log(`Request to ${response.url()} took ${totalTime}ms`);
329
}
330
});
331
```
332
333
### Request Interception Patterns
334
335
Common patterns for request interception and modification:
336
337
```typescript { .api }
338
interface RequestInterceptionPatterns {
339
/** Block resources by type or URL pattern */
340
blockResources(patterns: ResourceBlockPattern[]): void;
341
/** Mock API endpoints */
342
mockAPIs(mocks: APIMock[]): void;
343
/** Add authentication headers */
344
addAuth(token: string): void;
345
/** Modify user agent */
346
setUserAgent(userAgent: string): void;
347
/** Add CORS headers to responses */
348
enableCORS(): void;
349
/** Log all network activity */
350
logAllRequests(): void;
351
}
352
353
interface ResourceBlockPattern {
354
resourceType?: ResourceType;
355
urlPattern?: string | RegExp;
356
errorCode?: ErrorCode;
357
}
358
359
interface APIMock {
360
urlPattern: string | RegExp;
361
method?: string;
362
response: ResponseForRequest;
363
}
364
```
365
366
**Usage Examples:**
367
368
```typescript
369
// Block images and stylesheets for faster loading
370
await page.setRequestInterception(true);
371
372
page.on("request", (request) => {
373
const blockedTypes = ["image", "stylesheet", "font"];
374
if (blockedTypes.includes(request.resourceType())) {
375
request.abort("blockedbyclient");
376
} else {
377
request.continue();
378
}
379
});
380
381
// Mock multiple API endpoints
382
const apiMocks = [
383
{
384
url: "/api/users",
385
response: {
386
status: 200,
387
contentType: "application/json",
388
body: JSON.stringify([{ id: 1, name: "Test User" }])
389
}
390
},
391
{
392
url: "/api/config",
393
response: {
394
status: 200,
395
contentType: "application/json",
396
body: JSON.stringify({ theme: "dark", version: "1.0.0" })
397
}
398
}
399
];
400
401
page.on("request", (request) => {
402
const mock = apiMocks.find(m => request.url().includes(m.url));
403
if (mock) {
404
request.respond(mock.response);
405
} else {
406
request.continue();
407
}
408
});
409
410
// Add authentication to all API requests
411
page.on("request", (request) => {
412
if (request.url().includes("/api/")) {
413
const headers = {
414
...request.headers(),
415
"Authorization": "Bearer your-token-here"
416
};
417
request.continue({ headers });
418
} else {
419
request.continue();
420
}
421
});
422
423
// Comprehensive request logging
424
page.on("request", (request) => {
425
console.log(`→ ${request.method()} ${request.url()}`);
426
console.log(` Type: ${request.resourceType()}`);
427
console.log(` Headers:`, request.headers());
428
429
if (request.postData()) {
430
console.log(` POST data:`, request.postData());
431
}
432
433
request.continue();
434
});
435
436
page.on("response", async (response) => {
437
console.log(`← ${response.status()} ${response.url()}`);
438
console.log(` Headers:`, response.headers());
439
440
if (response.url().includes("/api/")) {
441
const body = await response.text();
442
console.log(` Body:`, body);
443
}
444
});
445
446
page.on("requestfailed", (request) => {
447
const failure = request.failure();
448
console.log(`✗ ${request.url()} failed: ${failure?.errorText}`);
449
});
450
```
451
452
### Network Events
453
454
Page-level network events for monitoring and debugging:
455
456
```typescript { .api }
457
interface NetworkEvents {
458
/** Emitted when request starts */
459
"request": (request: HTTPRequest) => void;
460
/** Emitted when response received */
461
"response": (response: HTTPResponse) => void;
462
/** Emitted when request completes successfully */
463
"requestfinished": (request: HTTPRequest) => void;
464
/** Emitted when request fails */
465
"requestfailed": (request: HTTPRequest) => void;
466
}
467
```
468
469
**Usage Examples:**
470
471
```typescript
472
// Network event monitoring
473
const networkEvents = [];
474
475
page.on("request", (request) => {
476
networkEvents.push({
477
type: "request",
478
url: request.url(),
479
method: request.method(),
480
timestamp: Date.now()
481
});
482
});
483
484
page.on("response", (response) => {
485
networkEvents.push({
486
type: "response",
487
url: response.url(),
488
status: response.status(),
489
timestamp: Date.now()
490
});
491
});
492
493
page.on("requestfailed", (request) => {
494
const failure = request.failure();
495
networkEvents.push({
496
type: "requestfailed",
497
url: request.url(),
498
error: failure?.errorText,
499
timestamp: Date.now()
500
});
501
});
502
503
// Analyze network activity after page load
504
await page.goto("https://example.com");
505
await page.waitForLoadState("networkidle");
506
507
console.log("Network activity summary:");
508
console.log(`Total requests: ${networkEvents.filter(e => e.type === "request").length}`);
509
console.log(`Successful responses: ${networkEvents.filter(e => e.type === "response").length}`);
510
console.log(`Failed requests: ${networkEvents.filter(e => e.type === "requestfailed").length}`);
511
```
512
513
### Advanced Network Features
514
515
Advanced networking capabilities and utilities:
516
517
```typescript { .api }
518
interface AdvancedNetworkFeatures {
519
/** Wait for specific request/response */
520
waitForRequest(urlOrPredicate: string | ((req: HTTPRequest) => boolean), options?: WaitForOptions): Promise<HTTPRequest>;
521
waitForResponse(urlOrPredicate: string | ((res: HTTPResponse) => boolean), options?: WaitForOptions): Promise<HTTPResponse>;
522
/** Capture network traffic */
523
captureNetworkTraffic(): NetworkCapture;
524
/** Simulate network conditions */
525
setNetworkConditions(conditions: NetworkConditions): Promise<void>;
526
/** Set offline mode */
527
setOfflineMode(enabled: boolean): Promise<void>;
528
/** Set user agent */
529
setUserAgent(userAgent: string, userAgentMetadata?: UserAgentMetadata): Promise<void>;
530
/** Set extra HTTP headers */
531
setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;
532
/** Authenticate with HTTP credentials */
533
authenticate(credentials: Credentials | null): Promise<void>;
534
}
535
536
interface NetworkCapture {
537
/** Start capturing */
538
start(): Promise<void>;
539
/** Stop capturing and return data */
540
stop(): Promise<NetworkTrafficEntry[]>;
541
}
542
543
interface NetworkTrafficEntry {
544
request: {
545
url: string;
546
method: string;
547
headers: Record<string, string>;
548
postData?: string;
549
timestamp: number;
550
};
551
response?: {
552
status: number;
553
headers: Record<string, string>;
554
body: string;
555
timestamp: number;
556
};
557
timing: ResponseTiming;
558
}
559
560
interface NetworkConditions {
561
/** Download speed in bytes/sec */
562
downloadThroughput: number;
563
/** Upload speed in bytes/sec */
564
uploadThroughput: number;
565
/** Latency in milliseconds */
566
latency: number;
567
/** Offline mode */
568
offline?: boolean;
569
}
570
571
interface WaitForOptions {
572
/** Maximum wait time */
573
timeout?: number;
574
/** Wait for navigation to complete */
575
waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
576
}
577
```
578
579
**Usage Examples:**
580
581
```typescript
582
// Wait for specific requests/responses
583
const apiRequest = page.waitForRequest(req =>
584
req.url().includes("/api/data") && req.method() === "POST"
585
);
586
587
const apiResponse = page.waitForResponse(res =>
588
res.url().includes("/api/data") && res.status() === 200
589
);
590
591
// Trigger the requests
592
await page.click("#load-data-button");
593
594
// Wait for completion
595
const [request, response] = await Promise.all([apiRequest, apiResponse]);
596
console.log("API call completed:", response.status());
597
598
// Simulate slow network
599
await page.emulateNetworkConditions({
600
downloadThroughput: 50 * 1024, // 50KB/s
601
uploadThroughput: 20 * 1024, // 20KB/s
602
latency: 200 // 200ms
603
});
604
605
// Test offline functionality
606
await page.setOfflineMode(true);
607
try {
608
await page.goto("https://example.com");
609
} catch (error) {
610
console.log("Page failed to load offline:", error.message);
611
}
612
await page.setOfflineMode(false);
613
614
// Set custom headers for all requests
615
await page.setExtraHTTPHeaders({
616
"X-API-Key": "your-api-key",
617
"X-Client-Version": "1.0.0"
618
});
619
620
// HTTP authentication
621
await page.authenticate({
622
username: "testuser",
623
password: "testpass"
624
});
625
```
626
627
### Error Handling
628
629
Network-related error handling and debugging:
630
631
```typescript { .api }
632
class NetworkError extends Error {
633
constructor(message: string);
634
}
635
636
class RequestInterceptionError extends NetworkError {
637
constructor(message: string);
638
}
639
640
class ResponseError extends NetworkError {
641
constructor(message: string, response: HTTPResponse);
642
response: HTTPResponse;
643
}
644
```
645
646
**Usage Examples:**
647
648
```typescript
649
// Robust request interception with error handling
650
page.on("request", async (request) => {
651
try {
652
if (request.url().includes("/api/")) {
653
// Validate request before continuing
654
const headers = request.headers();
655
if (!headers["authorization"]) {
656
await request.respond({
657
status: 401,
658
body: JSON.stringify({ error: "Unauthorized" })
659
});
660
return;
661
}
662
}
663
664
await request.continue();
665
} catch (error) {
666
console.log("Request interception error:", error.message);
667
// Fallback: continue the request
668
try {
669
await request.continue();
670
} catch (fallbackError) {
671
console.log("Fallback failed:", fallbackError.message);
672
}
673
}
674
});
675
676
// Handle response errors gracefully
677
page.on("response", async (response) => {
678
if (!response.ok()) {
679
console.log(`HTTP ${response.status()} for ${response.url()}`);
680
681
try {
682
const body = await response.text();
683
console.log("Error response body:", body);
684
} catch (error) {
685
console.log("Could not read error response body:", error.message);
686
}
687
}
688
});
689
690
// Retry failed requests
691
async function waitForResponseWithRetry(
692
page: Page,
693
urlPattern: string,
694
maxRetries = 3
695
): Promise<HTTPResponse> {
696
for (let i = 0; i < maxRetries; i++) {
697
try {
698
const response = await page.waitForResponse(
699
res => res.url().includes(urlPattern),
700
{ timeout: 10000 }
701
);
702
703
if (response.ok()) {
704
return response;
705
}
706
707
console.log(`Attempt ${i + 1}: Response ${response.status()}`);
708
} catch (error) {
709
console.log(`Attempt ${i + 1} failed:`, error.message);
710
}
711
712
if (i < maxRetries - 1) {
713
await page.waitForTimeout(1000 * (i + 1)); // Exponential backoff
714
}
715
}
716
717
throw new NetworkError(`Failed to get successful response after ${maxRetries} attempts`);
718
}
719
```