# How to Create Persistent Browser Profiles Using `launch_persistent_context` in CloakBrowser

> Learn to create persistent browser profiles in CloakBrowser using launch_persistent_context. Store cookies and session state across launches by specifying a userDataDir.

- Repository: [CloakHQ/CloakBrowser](https://github.com/CloakHQ/CloakBrowser)
- Tags: how-to-guide
- Published: 2026-05-09

---

**Use the `launchPersistentContext` function exported from [`js/src/playwright.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/src/playwright.ts) and provide a `userDataDir` path to store cookies, localStorage, and session state across browser launches.**

CloakBrowser is a stealth-focused wrapper around Playwright that enables persistent browser sessions through its `launchPersistentContext` implementation. Unlike ephemeral incognito contexts, this function creates real Chrome profiles on disk, allowing you to maintain authentication state and avoid anti-bot detection systems that flag fresh browser instances. The core implementation handles timezone normalization, proxy configuration, and WebRTC spoofing before delegating to Playwright's underlying Chromium launcher.

## What Is `launchPersistentContext` and Why Use It?

The `launchPersistentContext` function in CloakBrowser wraps Playwright's native `chromium.launchPersistentContext()` to provide a **stealth-enabled browser context** that persists data between runs. When you use standard `launch()` or incognito contexts, every session starts completely fresh, which sophisticated anti-bot services can detect. By specifying a `userDataDir`, CloakBrowser stores the full browser profile—including cookies, localStorage, IndexedDB, and extension data—allowing you to resume exactly where you left off.

According to the CloakBrowser source code in [`js/src/playwright.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/src/playwright.ts), this approach applies all stealth arguments (such as `--fingerprint-webrtc-ip` and locale spoofing) while avoiding the "incognito penalty" that automation detection systems look for.

## Inside the `launchPersistentContext` Implementation

Understanding how CloakBrowser assembles your persistent context helps you configure it correctly. The implementation at lines 186-214 of [`js/src/playwright.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/src/playwright.ts) performs several preparation steps before calling Playwright.

### Timezone and Locale Normalization

Before launch, the wrapper calls `resolveTimezone` to normalize `timezone` and `timezoneId` fields from your options. This ensures the browser reports consistent locale information that matches your proxy location, a critical factor for evading geographic fingerprinting.

### Binary Path Resolution

The function uses `ensureBinary()` to locate the bundled Chromium binary, or respects the `CLOAKBROWSER_BINARY_PATH` environment variable if you need to override the executable. This happens at lines 84-88 of the source file.

### Stealth Argument Construction

CloakBrowser builds the final argument list through several stages:

- **`maybeResolveGeoip`** and **`resolveWebrtcArgs`** add flags like `--fingerprint-webrtc-ip` to prevent IP leakage
- **`buildArgs`** merges user-provided arguments with stealth defaults
- **`filterStealthCtxOptions`** removes detectable Chrome DevTools Protocol (CDP) emulation patterns that anti-bot scripts scan for

### The Launch Call

Ultimately, the function invokes Playwright's underlying launcher with your persistent directory:

```typescript
const context = await chromium.launchPersistentContext(options.userDataDir, {
  executablePath: binaryPath,
  headless: options.headless ?? true,
  args,
  ignoreDefaultArgs: IGNORE_DEFAULT_ARGS,
  ...(proxyOption ? { proxy: proxyOption } : {}),
  ...filterStealthCtxOptions(options.contextOptions),
  viewport: options.viewport === undefined ? DEFAULT_VIEWPORT : options.viewport,
});

```

### Human Behavior Patching

If you set `humanize: true` in your options, CloakBrowser patches the returned context with realistic mouse movements and keyboard timing patterns after launch, making automation behavior indistinguishable from genuine user interaction.

## Creating Your First Persistent Browser Profile

To create a persistent profile, you need only specify a directory path for `userDataDir`. Below is a complete example from the repository at [`js/examples/persistent-context.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/examples/persistent-context.ts) that demonstrates writing data in one session and retrieving it in another:

```typescript
import { launchPersistentContext } from "../src/index.js";

const PROFILE_DIR = "./my-profile";

/* Session 1 – set persistent state */
let ctx = await launchPersistentContext({
  userDataDir: PROFILE_DIR,
  headless: false,
});
let page = ctx.pages()[0] || (await ctx.newPage());
await page.goto("https://example.com");
await page.evaluate(() => {
  document.cookie = "session=abc123; path=/; max-age=3600";
  localStorage.setItem("user", "returning");
});
console.log("Session 1 cookie:", await page.evaluate(() => document.cookie));
await ctx.close();

/* Session 2 – verify persistence */
ctx = await launchPersistentContext({
  userDataDir: PROFILE_DIR,
  headless: false,
});
page = ctx.pages()[0] || (await ctx.newPage());
await page.goto("https://example.com");
console.log("Session 2 cookie:", await page.evaluate(() => document.cookie));
console.log("Session 2 localStorage:", await page.evaluate(() => localStorage.getItem("user")));
await ctx.close();

```

Running this script twice demonstrates that both the cookie and localStorage values survive browser restarts.

## Configuring Proxies and Stealth Options

Persistent contexts support the same stealth configuration as ephemeral ones. Pass a `proxy` string and enable geo-IP spoofing to match your proxy location:

```typescript
const ctx = await launchPersistentContext({
  userDataDir: "./profile",
  headless: false,
  proxy: "http://user:pass@proxy.example:3128",
  geoip: true,
  userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
});

```

The `geoip: true` flag triggers `maybeResolveGeoip` to automatically configure timezone and locale settings based on the proxy's egress IP, while the persistent directory stores any authentication cookies set during the session.

## Summary

- **`launchPersistentContext`** in [`js/src/playwright.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/src/playwright.ts) creates durable browser profiles that persist between script runs
- Provide a `userDataDir` path to store cookies, localStorage, and extension data on disk
- The function automatically applies stealth arguments, WebRTC spoofing, and timezone normalization before launching Chromium
- Persistent profiles avoid the "incognito penalty" that triggers bot detection on many websites
- Use `humanize: true` to add realistic mouse and keyboard behavior to persistent contexts

## Frequently Asked Questions

### Where is the `launchPersistentContext` function defined in CloakBrowser?

The function is defined in [`js/src/playwright.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/src/playwright.ts) at lines 186-214. It exports an async function that accepts `LaunchPersistentContextOptions` and returns a Playwright `BrowserContext` instance with stealth modifications applied.

### What data persists between sessions when using `userDataDir`?

The `userDataDir` directory stores cookies, localStorage, IndexedDB, cache, browser history, and extension data. This includes HTTP-only cookies and HTML5 storage mechanisms that standard ephemeral contexts discard upon closing.

### Can I use headless mode with persistent browser profiles?

Yes. While the examples often use `headless: false` for visibility, you can set `headless: true` (the default) and the profile will still persist to disk. However, some anti-bot services detect headless mode, so CloakBrowser's stealth arguments remain essential regardless of visibility settings.

### How does CloakBrowser handle proxy authentication in persistent contexts?

Proxy credentials passed in the `proxy` option are resolved through [`js/src/proxy.ts`](https://github.com/CloakHQ/CloakBrowser/blob/main/js/src/proxy.ts) before launch. These settings persist for the context lifetime, and any authentication cookies received through the proxy are stored in the `userDataDir`, allowing subsequent sessions to maintain logged-in states without re-authenticating.