0
# Browser Contexts
1
2
Isolated browser contexts for managing sessions, cookies, permissions, and parallel test execution.
3
4
## Capabilities
5
6
### BrowserContext Interface
7
8
Provides isolated browser sessions with independent cookies, storage, and permissions.
9
10
```typescript { .api }
11
interface BrowserContext extends EventEmitter {
12
/** Create new page in this context */
13
newPage(): Promise<Page>;
14
/** Get all pages in this context */
15
pages(): Page[];
16
/** Get browser instance */
17
browser(): Browser;
18
/** Close context and all pages */
19
close(): Promise<void>;
20
/** Check if context is closed */
21
isIncognito(): boolean;
22
/** Get/set cookies */
23
cookies(...urls: string[]): Promise<Cookie[]>;
24
setCookie(...cookies: CookieParam[]): Promise<void>;
25
addCookies(cookies: CookieParam[]): Promise<void>;
26
clearCookies(): Promise<void>;
27
/** Permissions management */
28
grantPermissions(permissions: Permission[], options?: { origin?: string }): Promise<void>;
29
clearPermissionOverrides(): Promise<void>;
30
overridePermissions(origin: string, permissions: Permission[]): Promise<void>;
31
/** Geolocation */
32
setGeolocation(geolocation: GeolocationOptions): Promise<void>;
33
/** HTTP credentials */
34
setHTTPCredentials(httpCredentials: HTTPCredentials | null): Promise<void>;
35
/** User agent */
36
setUserAgent(userAgent: string): Promise<void>;
37
/** Viewport */
38
setViewportSize(viewportSize: ViewportSize): Promise<void>;
39
/** Offline mode */
40
setOffline(offline: boolean): Promise<void>;
41
/** Extra HTTP headers */
42
setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;
43
/** Request interception */
44
setRequestInterception(value: boolean): Promise<void>;
45
/** Default timeout */
46
setDefaultTimeout(timeout: number): void;
47
setDefaultNavigationTimeout(timeout: number): void;
48
/** Wait for events */
49
waitForEvent(event: string, optionsOrPredicate?: Function | { timeout?: number; predicate?: Function }): Promise<any>;
50
/** Tracing */
51
tracing(): Tracing;
52
/** Route handling */
53
route(url: string | RegExp | ((url: URL) => boolean), handler: RouteHandler): Promise<void>;
54
unroute(url: string | RegExp | ((url: URL) => boolean), handler?: RouteHandler): Promise<void>;
55
/** Storage state */
56
storageState(options?: { path?: string }): Promise<StorageState>;
57
addInitScript(script: Function | string | { path?: string; content?: string }): Promise<void>;
58
/** Expose function to all pages */
59
exposeFunction(name: string, callback: Function): Promise<void>;
60
exposeBinding(name: string, callback: Function, options?: { handle?: boolean }): Promise<void>;
61
/** Service workers */
62
serviceWorkers(): Worker[];
63
/** Background pages */
64
backgroundPages(): Page[];
65
/** CDPSession */
66
newCDPSession(page: Page): Promise<CDPSession>;
67
}
68
69
interface Cookie {
70
name: string;
71
value: string;
72
domain?: string;
73
path?: string;
74
expires?: number;
75
httpOnly?: boolean;
76
secure?: boolean;
77
sameSite?: "Strict" | "Lax" | "None";
78
priority?: "Low" | "Medium" | "High";
79
sameParty?: boolean;
80
sourceScheme?: "Unset" | "NonSecure" | "Secure";
81
partitionKey?: string;
82
}
83
84
interface CookieParam {
85
name: string;
86
value: string;
87
url?: string;
88
domain?: string;
89
path?: string;
90
secure?: boolean;
91
httpOnly?: boolean;
92
sameSite?: "Strict" | "Lax" | "None";
93
expires?: number;
94
priority?: "Low" | "Medium" | "High";
95
sameParty?: boolean;
96
sourceScheme?: "Unset" | "NonSecure" | "Secure";
97
partitionKey?: string;
98
}
99
100
type Permission =
101
| "geolocation"
102
| "midi"
103
| "notifications"
104
| "camera"
105
| "microphone"
106
| "background-sync"
107
| "ambient-light-sensor"
108
| "accelerometer"
109
| "gyroscope"
110
| "magnetometer"
111
| "accessibility-events"
112
| "clipboard-read"
113
| "clipboard-write"
114
| "payment-handler"
115
| "persistent-storage"
116
| "idle-detection"
117
| "midi-sysex";
118
119
interface GeolocationOptions {
120
latitude: number;
121
longitude: number;
122
accuracy?: number;
123
}
124
125
interface HTTPCredentials {
126
username: string;
127
password: string;
128
origin?: string;
129
}
130
131
interface ViewportSize {
132
width: number;
133
height: number;
134
}
135
136
interface RouteHandler {
137
(route: Route, request: Request): Promise<void> | void;
138
}
139
140
interface StorageState {
141
cookies: Cookie[];
142
origins: OriginState[];
143
}
144
145
interface OriginState {
146
origin: string;
147
localStorage: NameValuePair[];
148
sessionStorage: NameValuePair[];
149
}
150
151
interface NameValuePair {
152
name: string;
153
value: string;
154
}
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import puppeteer from "puppeteer-core";
161
162
const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });
163
164
// Create isolated contexts
165
const context1 = await browser.createBrowserContext();
166
const context2 = await browser.createBrowserContext();
167
168
// Each context has its own session
169
const page1 = await context1.newPage();
170
const page2 = await context2.newPage();
171
172
// Set different cookies for each context
173
await context1.setCookie({
174
name: "user",
175
value: "alice",
176
domain: "example.com"
177
});
178
179
await context2.setCookie({
180
name: "user",
181
value: "bob",
182
domain: "example.com"
183
});
184
185
// Navigate to same site - each will have different cookies
186
await page1.goto("https://example.com");
187
await page2.goto("https://example.com");
188
189
// Set different permissions
190
await context1.grantPermissions(["geolocation"], { origin: "https://example.com" });
191
await context2.overridePermissions("https://example.com", []); // No permissions
192
193
// Close contexts
194
await context1.close();
195
await context2.close();
196
await browser.close();
197
```
198
199
### Context Creation and Configuration
200
201
Create browser contexts with specific configurations:
202
203
```typescript { .api }
204
interface BrowserContextOptions {
205
/** Accept downloads */
206
acceptDownloads?: boolean;
207
/** Bypass CSP */
208
bypassCSP?: boolean;
209
/** Color scheme */
210
colorScheme?: "light" | "dark" | "no-preference";
211
/** Device scale factor */
212
deviceScaleFactor?: number;
213
/** Extra HTTP headers */
214
extraHTTPHeaders?: Record<string, string>;
215
/** Geolocation */
216
geolocation?: GeolocationOptions;
217
/** Has touch */
218
hasTouch?: boolean;
219
/** HTTP credentials */
220
httpCredentials?: HTTPCredentials;
221
/** Ignore HTTPS errors */
222
ignoreHTTPSErrors?: boolean;
223
/** Is mobile */
224
isMobile?: boolean;
225
/** Java Script enabled */
226
javaScriptEnabled?: boolean;
227
/** Locale */
228
locale?: string;
229
/** Offline */
230
offline?: boolean;
231
/** Permissions */
232
permissions?: Permission[];
233
/** Proxy */
234
proxy?: ProxySettings;
235
/** Record HAR */
236
recordHar?: HarOptions;
237
/** Record video */
238
recordVideo?: VideoOptions;
239
/** Reduced motion */
240
reducedMotion?: "reduce" | "no-preference";
241
/** Screen */
242
screen?: ScreenSize;
243
/** Service workers */
244
serviceWorkers?: "allow" | "block";
245
/** Storage state */
246
storageState?: string | StorageState;
247
/** Timezone */
248
timezoneId?: string;
249
/** User agent */
250
userAgent?: string;
251
/** Viewport */
252
viewport?: ViewportSize | null;
253
}
254
255
interface ProxySettings {
256
server: string;
257
bypass?: string;
258
username?: string;
259
password?: string;
260
}
261
262
interface HarOptions {
263
omitContent?: boolean;
264
path?: string;
265
}
266
267
interface VideoOptions {
268
dir: string;
269
size?: ViewportSize;
270
}
271
272
interface ScreenSize {
273
width: number;
274
height: number;
275
}
276
```
277
278
**Usage Examples:**
279
280
```typescript
281
// Create context with mobile emulation
282
const mobileContext = await browser.createBrowserContext({
283
viewport: { width: 375, height: 667 },
284
userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15",
285
isMobile: true,
286
hasTouch: true,
287
deviceScaleFactor: 2
288
});
289
290
// Create context with specific locale and timezone
291
const localizedContext = await browser.createBrowserContext({
292
locale: "de-DE",
293
timezoneId: "Europe/Berlin",
294
colorScheme: "dark"
295
});
296
297
// Create context with geolocation and permissions
298
const locationContext = await browser.createBrowserContext({
299
geolocation: { latitude: 37.7749, longitude: -122.4194 },
300
permissions: ["geolocation", "notifications"]
301
});
302
303
// Create context with proxy
304
const proxyContext = await browser.createBrowserContext({
305
proxy: {
306
server: "http://proxy.example.com:8080",
307
username: "proxyuser",
308
password: "proxypass"
309
}
310
});
311
312
// Create context with custom storage state
313
const contextWithStorage = await browser.createBrowserContext({
314
storageState: {
315
cookies: [
316
{
317
name: "session_id",
318
value: "abc123",
319
domain: "example.com",
320
path: "/",
321
secure: true,
322
httpOnly: true
323
}
324
],
325
origins: [
326
{
327
origin: "https://example.com",
328
localStorage: [
329
{ name: "theme", value: "dark" },
330
{ name: "language", value: "en" }
331
],
332
sessionStorage: []
333
}
334
]
335
}
336
});
337
```
338
339
### Cookie Management
340
341
Comprehensive cookie management within contexts:
342
343
```typescript { .api }
344
interface CookieManagement {
345
/** Add single cookie */
346
addCookie(cookie: CookieParam): Promise<void>;
347
/** Add multiple cookies */
348
addCookies(cookies: CookieParam[]): Promise<void>;
349
/** Get cookies for URLs */
350
getCookies(urls?: string[]): Promise<Cookie[]>;
351
/** Set cookies (replaces existing) */
352
setCookies(cookies: CookieParam[]): Promise<void>;
353
/** Delete specific cookies */
354
deleteCookies(cookies: DeleteCookieParam[]): Promise<void>;
355
/** Clear all cookies */
356
clearAllCookies(): Promise<void>;
357
/** Get cookie by name */
358
getCookie(name: string, url?: string): Promise<Cookie | null>;
359
}
360
361
interface DeleteCookieParam {
362
name: string;
363
url?: string;
364
domain?: string;
365
path?: string;
366
}
367
```
368
369
**Usage Examples:**
370
371
```typescript
372
const context = await browser.createBrowserContext();
373
374
// Add authentication cookies
375
await context.addCookies([
376
{
377
name: "auth_token",
378
value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
379
domain: "api.example.com",
380
path: "/",
381
secure: true,
382
httpOnly: true,
383
sameSite: "Strict"
384
},
385
{
386
name: "session_id",
387
value: "sess_abc123",
388
domain: "example.com",
389
path: "/",
390
expires: Date.now() + 86400000 // 24 hours
391
}
392
]);
393
394
// Get cookies for specific domains
395
const allCookies = await context.cookies();
396
const exampleCookies = await context.cookies("https://example.com");
397
const apiCookies = await context.cookies("https://api.example.com");
398
399
// Update cookie value
400
await context.setCookie({
401
name: "theme",
402
value: "dark",
403
domain: "example.com"
404
});
405
406
// Delete specific cookies
407
await context.clearCookies();
408
409
// Cookie-based session management
410
class SessionManager {
411
constructor(private context: BrowserContext) {}
412
413
async login(username: string, password: string) {
414
const page = await this.context.newPage();
415
await page.goto("https://example.com/login");
416
417
await page.type("#username", username);
418
await page.type("#password", password);
419
await page.click("#login-button");
420
421
// Wait for redirect and session cookie
422
await page.waitForNavigation();
423
await page.close();
424
}
425
426
async isLoggedIn(): Promise<boolean> {
427
const cookies = await this.context.cookies("https://example.com");
428
return cookies.some(cookie => cookie.name === "session_id");
429
}
430
431
async logout() {
432
await this.context.clearCookies();
433
}
434
}
435
436
const sessionManager = new SessionManager(context);
437
await sessionManager.login("user@example.com", "password123");
438
```
439
440
### Permission Management
441
442
Control browser permissions within contexts:
443
444
```typescript { .api }
445
interface PermissionManagement {
446
/** Grant permissions for origin */
447
grantPermissions(permissions: Permission[], origin?: string): Promise<void>;
448
/** Override permissions for origin */
449
overridePermissions(origin: string, permissions: Permission[]): Promise<void>;
450
/** Clear permission overrides */
451
clearPermissionOverrides(): Promise<void>;
452
/** Check permission state */
453
getPermissionState(permission: Permission, origin?: string): Promise<PermissionState>;
454
}
455
456
type PermissionState = "granted" | "denied" | "prompt";
457
```
458
459
**Usage Examples:**
460
461
```typescript
462
const context = await browser.createBrowserContext();
463
464
// Grant geolocation permission
465
await context.grantPermissions(["geolocation"], {
466
origin: "https://maps.example.com"
467
});
468
469
// Block notifications globally
470
await context.overridePermissions("https://example.com", []);
471
472
// Grant multiple permissions
473
await context.grantPermissions([
474
"camera",
475
"microphone",
476
"notifications"
477
], { origin: "https://video-chat.example.com" });
478
479
// Permission-based testing
480
async function testLocationFeature(context: BrowserContext) {
481
// Test with permission granted
482
await context.grantPermissions(["geolocation"]);
483
const page = await context.newPage();
484
await page.goto("https://example.com/location");
485
486
const locationButton = await page.$("#get-location");
487
await locationButton.click();
488
489
// Verify location was obtained
490
const locationText = await page.$("#current-location").textContent();
491
console.log("Location with permission:", locationText);
492
493
await page.close();
494
495
// Test with permission denied
496
await context.overridePermissions("https://example.com", []);
497
const page2 = await context.newPage();
498
await page2.goto("https://example.com/location");
499
500
await page2.click("#get-location");
501
502
// Verify error message
503
const errorText = await page2.$("#location-error").textContent();
504
console.log("Location without permission:", errorText);
505
506
await page2.close();
507
}
508
509
await testLocationFeature(context);
510
```
511
512
### Context Events
513
514
Browser context events for monitoring and automation:
515
516
```typescript { .api }
517
interface BrowserContextEvents {
518
/** Emitted when page is created */
519
"page": (page: Page) => void;
520
/** Emitted when page is closed */
521
"close": () => void;
522
/** Emitted when background page is created */
523
"backgroundpage": (page: Page) => void;
524
/** Emitted when service worker is created */
525
"serviceworker": (worker: Worker) => void;
526
/** Emitted when request starts */
527
"request": (request: HTTPRequest) => void;
528
/** Emitted when response is received */
529
"response": (response: HTTPResponse) => void;
530
/** Emitted when request fails */
531
"requestfailed": (request: HTTPRequest) => void;
532
/** Emitted when request finishes */
533
"requestfinished": (request: HTTPRequest) => void;
534
}
535
```
536
537
**Usage Examples:**
538
539
```typescript
540
const context = await browser.createBrowserContext();
541
542
// Monitor page creation
543
context.on("page", (page) => {
544
console.log("New page created:", page.url());
545
546
// Set up page-level monitoring
547
page.on("console", (msg) => {
548
console.log(`Page console: ${msg.text()}`);
549
});
550
551
page.on("pageerror", (error) => {
552
console.error("Page error:", error.message);
553
});
554
});
555
556
// Monitor network activity across all pages
557
context.on("request", (request) => {
558
console.log(`Request: ${request.method()} ${request.url()}`);
559
});
560
561
context.on("response", (response) => {
562
if (!response.ok()) {
563
console.log(`Failed response: ${response.status()} ${response.url()}`);
564
}
565
});
566
567
// Handle context closure
568
context.on("close", () => {
569
console.log("Browser context closed");
570
});
571
572
// Create pages and trigger events
573
const page1 = await context.newPage();
574
const page2 = await context.newPage();
575
576
await page1.goto("https://example.com");
577
await page2.goto("https://another-example.com");
578
579
await context.close();
580
```
581
582
### Storage State Management
583
584
Save and restore browser state across sessions:
585
586
```typescript { .api }
587
interface StorageStateManagement {
588
/** Get current storage state */
589
getStorageState(): Promise<StorageState>;
590
/** Save storage state to file */
591
saveStorageState(path: string): Promise<void>;
592
/** Load storage state from file */
593
loadStorageState(path: string): Promise<StorageState>;
594
/** Create context with saved state */
595
createContextWithState(statePath: string): Promise<BrowserContext>;
596
}
597
```
598
599
**Usage Examples:**
600
601
```typescript
602
// Save authenticated session
603
const context = await browser.createBrowserContext();
604
const page = await context.newPage();
605
606
// Perform login
607
await page.goto("https://example.com/login");
608
await page.type("#username", "user@example.com");
609
await page.type("#password", "password123");
610
await page.click("#login-button");
611
await page.waitForNavigation();
612
613
// Save storage state
614
const storageState = await context.storageState();
615
await context.storageState({ path: "auth-state.json" });
616
617
await context.close();
618
619
// Restore session later
620
const restoredContext = await browser.createBrowserContext({
621
storageState: "auth-state.json"
622
});
623
624
const restoredPage = await restoredContext.newPage();
625
await restoredPage.goto("https://example.com/dashboard");
626
627
// User should already be logged in
628
const welcomeText = await restoredPage.$("#welcome-message").textContent();
629
console.log(welcomeText); // Should show logged-in state
630
631
// Session state management utility
632
class SessionStateManager {
633
private stateFile: string;
634
635
constructor(stateFile: string) {
636
this.stateFile = stateFile;
637
}
638
639
async createAuthenticatedContext(browser: Browser): Promise<BrowserContext> {
640
try {
641
return await browser.createBrowserContext({
642
storageState: this.stateFile
643
});
644
} catch (error) {
645
console.log("No saved state found, creating fresh context");
646
return await browser.createBrowserContext();
647
}
648
}
649
650
async saveState(context: BrowserContext): Promise<void> {
651
await context.storageState({ path: this.stateFile });
652
}
653
654
async clearState(): Promise<void> {
655
try {
656
await import("fs").then(fs => fs.unlinkSync(this.stateFile));
657
} catch (error) {
658
// File doesn't exist, nothing to do
659
}
660
}
661
}
662
663
const stateManager = new SessionStateManager("user-session.json");
664
const authContext = await stateManager.createAuthenticatedContext(browser);
665
666
// Use context...
667
await stateManager.saveState(authContext);
668
```
669
670
### Parallel Execution with Contexts
671
672
Use contexts for parallel test execution and isolation:
673
674
```typescript { .api }
675
interface ParallelExecution {
676
/** Run tests in parallel contexts */
677
runParallel<T>(tests: (() => Promise<T>)[], maxConcurrency?: number): Promise<T[]>;
678
/** Create context pool */
679
createContextPool(browser: Browser, poolSize: number): ContextPool;
680
/** Execute with context isolation */
681
withIsolatedContext<T>(browser: Browser, operation: (context: BrowserContext) => Promise<T>): Promise<T>;
682
}
683
684
interface ContextPool {
685
acquire(): Promise<BrowserContext>;
686
release(context: BrowserContext): void;
687
close(): Promise<void>;
688
}
689
```
690
691
**Usage Examples:**
692
693
```typescript
694
// Parallel test execution
695
async function runParallelTests(browser: Browser) {
696
const tests = [
697
async () => {
698
const context = await browser.createBrowserContext();
699
const page = await context.newPage();
700
await page.goto("https://example.com/test1");
701
const result = await page.$("#result").textContent();
702
await context.close();
703
return { test: "test1", result };
704
},
705
async () => {
706
const context = await browser.createBrowserContext();
707
const page = await context.newPage();
708
await page.goto("https://example.com/test2");
709
const result = await page.$("#result").textContent();
710
await context.close();
711
return { test: "test2", result };
712
},
713
async () => {
714
const context = await browser.createBrowserContext();
715
const page = await context.newPage();
716
await page.goto("https://example.com/test3");
717
const result = await page.$("#result").textContent();
718
await context.close();
719
return { test: "test3", result };
720
}
721
];
722
723
const results = await Promise.all(tests.map(test => test()));
724
return results;
725
}
726
727
const testResults = await runParallelTests(browser);
728
console.log("Test results:", testResults);
729
730
// Context pool for resource management
731
class BrowserContextPool {
732
private contexts: BrowserContext[] = [];
733
private inUse: Set<BrowserContext> = new Set();
734
735
constructor(private browser: Browser, private maxSize: number) {}
736
737
async acquire(): Promise<BrowserContext> {
738
// Try to find available context
739
const available = this.contexts.find(ctx => !this.inUse.has(ctx));
740
if (available) {
741
this.inUse.add(available);
742
return available;
743
}
744
745
// Create new context if under limit
746
if (this.contexts.length < this.maxSize) {
747
const context = await this.browser.createBrowserContext();
748
this.contexts.push(context);
749
this.inUse.add(context);
750
return context;
751
}
752
753
// Wait for context to become available
754
return new Promise((resolve) => {
755
const checkAvailable = () => {
756
const available = this.contexts.find(ctx => !this.inUse.has(ctx));
757
if (available) {
758
this.inUse.add(available);
759
resolve(available);
760
} else {
761
setTimeout(checkAvailable, 100);
762
}
763
};
764
checkAvailable();
765
});
766
}
767
768
release(context: BrowserContext): void {
769
this.inUse.delete(context);
770
}
771
772
async close(): Promise<void> {
773
await Promise.all(this.contexts.map(ctx => ctx.close()));
774
this.contexts = [];
775
this.inUse.clear();
776
}
777
}
778
779
// Usage
780
const contextPool = new BrowserContextPool(browser, 5);
781
782
async function runWithPool(operation: (page: Page) => Promise<any>) {
783
const context = await contextPool.acquire();
784
try {
785
const page = await context.newPage();
786
const result = await operation(page);
787
await page.close();
788
return result;
789
} finally {
790
contextPool.release(context);
791
}
792
}
793
794
// Run multiple operations
795
const operations = Array(10).fill(0).map((_, i) =>
796
runWithPool(async (page) => {
797
await page.goto(`https://example.com/item/${i}`);
798
return await page.$("#title").textContent();
799
})
800
);
801
802
const results = await Promise.all(operations);
803
await contextPool.close();
804
```