# How camofox-browser Handles Rotating Sticky Sessions with Backconnect Proxies

> Discover how camofox-browser manages rotating sticky sessions using its backconnect proxy strategy. Learn how unique session identifiers ensure isolated browser contexts without restarts.

- Repository: [jo/camofox-browser](https://github.com/jo-inc/camofox-browser)
- Tags: how-to-guide
- Published: 2026-04-15

---

**camofox-browser rotates sticky sessions by embedding unique session identifiers directly into the proxy username, allowing a single backconnect endpoint to maintain isolated sessions per browser context without restarting the browser.**

The camofox-browser open-source project implements a sophisticated proxy abstraction layer that supports residential backconnect proxies with session persistence. Unlike round-robin strategies that cycle through static ports, the backconnect approach generates per-context session IDs that are baked into proxy authentication credentials. This design enables granular traffic isolation while maintaining a single physical proxy endpoint.

## Backconnect vs Round-Robin Proxy Strategies

camofox-browser supports two distinct proxy strategies defined in [`lib/proxy.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/proxy.js). The **round-robin** strategy rotates through a pool of static proxy ports, while the **backconnect** strategy uses a single residential proxy endpoint that maintains sticky sessions based on the username format.

When `CONFIG.proxy.strategy` is set to `"backconnect"`, the library creates a pool with `canRotateSessions: true`. This flag signals that the pool can generate unique sessions per context rather than cycling through different physical endpoints.

## Creating the Backconnect Proxy Pool

The proxy initialization occurs in [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) where the system reads the configuration and instantiates the pool using `createProxyPool`.

```js
const proxyPool = createProxyPool(CONFIG.proxy);
// source: server.js lines 408-416

```

For backconnect configurations, this factory returns a pool object sized at exactly one endpoint, but with methods capable of accepting unique session identifiers. The pool recognizes it should rotate sessions rather than rotate servers.

## How Session Rotation Works in lib/proxy.js

### Pool Architecture with Single Endpoint

In [`lib/proxy.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/proxy.js), the backconnect pool implementation provides two key methods: `getLaunchProxy(sessionId?)` for browser initialization and `getNext(sessionId?)` for context switching. Both methods invoke `buildBackconnectProxy` but accept different session ID formats.

```js
// source: lib/proxy.js lines 87-106
if (strategy === 'backconnect') {
  // ...
  return {
    // ...
    getLaunchProxy(sessionId = makeSessionId('browser')) {
      return buildBackconnectProxy(config, provider, sessionId);
    },
    getNext(sessionId = makeSessionId('ctx')) {
      return buildBackconnectProxy(config, provider, sessionId);
    },
  };
}

```

The `makeSessionId` function generates opaque identifiers prefixed with either `browser-` or `ctx-` depending on the calling context. These identifiers ensure that each logical session receives distinct treatment from the remote proxy service.

### Building Sticky Session Proxies

The `buildBackconnectProxy` function composes the final proxy object by constructing a specialized username that includes the session identifier. This is the core mechanism that enables sticky sessions on a shared endpoint.

```js
// source: lib/proxy.js lines 52-68
function buildBackconnectProxy(config, provider, sessionId) {
  const username = provider.buildSessionUsername(config.username, {
    // ...
    sessionId,
  });
  return {
    server: `http://${config.backconnectHost}:${config.backconnectPort}`,
    username,
    password: config.password,
    sessionId,
  };
}

```

The function returns an object containing the shared `server` endpoint, a `username` with embedded session data, the static `password`, and the opaque `sessionId` for logging purposes.

## Provider-Specific Username DSL

camofox-browser uses provider plugins to format usernames according to each proxy service's requirements. The default `decodoProvider` constructs a domain-specific language (DSL) that embeds geography, session duration, and the critical **sessionId** into the username string.

```js
// source: lib/proxy.js lines 72-93 (Decodo provider)
buildSessionUsername(baseUsername, options = {}) {
  // ...
  if (sessionId) parts.push(`session-${sessionId}`);
  // ...
  return parts.join('-');
}

```

This username format (e.g., `user-test-country-us-session-ctx-42-test`) signals the remote proxy service to isolate traffic for that specific session, effectively creating a sticky session without changing the physical endpoint.

## Per-Context Session Isolation

When a Google-blocked tab requires rotation, the server requests a new proxy from the pool using a context-specific session identifier. The test suite in [`tests/unit/proxyRotation.test.js`](https://github.com/jo-inc/camofox-browser/blob/main/tests/unit/proxyRotation.test.js) demonstrates this pattern through the `assignContextProxy` function.

```js
// source: tests/unit/proxyRotation.test.js lines 24-30
function assignContextProxy(proxyPool, userId) {
  if (proxyPool?.canRotateSessions) {
    const key = normalizeUserId(userId);
    return proxyPool.getNext(`ctx-${key}-test`);
  } else if (proxyPool) {
    return proxyPool.getNext();
  }
  return null;
}

```

Each distinct user receives a unique session ID (e.g., `ctx-alice-test`), ensuring that backconnect endpoints treat them as separate sticky sessions. This prevents one user's blocked session from affecting another's traffic.

## Integrating with Playwright

The server injects the proxy configuration into Playwright's launch options after normalizing it through `normalizePlaywrightProxy`. For backconnect configurations, this includes the sticky-session username constructed earlier.

```js
const launchProxy = proxyPool
  ? proxyPool.getLaunchProxy(proxyPool.canRotateSessions
      ? `browser-${crypto.randomUUID().replace(/-/g, '').slice(0,12)}`
      : undefined)
  : null;
options.proxy = normalizePlaywrightProxy(launchProxy);
// source: server.js lines 568-614

```

When `canRotateSessions` is true, the code generates a browser-scoped session ID (e.g., `browser-abcd1234`) that persists for the browser instance lifetime, while individual contexts within that browser can still rotate via `getNext()`.

## Summary

- **camofox-browser** uses a single backconnect endpoint with rotating session IDs embedded in usernames to create virtual sticky sessions.
- The `createProxyPool` factory sets `canRotateSessions: true` for backconnect strategies, enabling per-context session generation.
- Session identifiers follow formats like `ctx-{userId}` for context isolation or `browser-{uuid}` for launch-time sessions.
- Provider plugins like **Decodo** construct DSL usernames that remote proxy services recognize as sticky session keys.
- Per-context rotation occurs via `getNext(sessionId)` without requiring browser restarts, maintaining efficiency while ensuring isolation.

## Frequently Asked Questions

### What is the difference between backconnect and round-robin in camofox-browser?

Round-robin cycles through multiple static proxy ports, changing the physical endpoint for each request. Backconnect uses a single residential endpoint but rotates **sticky sessions** by changing the username format, embedding unique session IDs that tell the remote service to maintain IP persistence for that specific session identifier.

### How does camofox-browser ensure session persistence across browser contexts?

The system generates unique session identifiers (e.g., `ctx-user123-test`) in `assignContextProxy` and passes them to `buildBackconnectProxy`. These IDs are embedded in the proxy username using the provider's `buildSessionUsername` method. The remote proxy service recognizes this username pattern and routes all traffic from that session through the same residential IP address.

### Can I use custom proxy providers with camofox-browser's sticky session system?

Yes. The [`lib/proxy.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/proxy.js) module exports `registerProvider(name, provider)`, allowing you to implement custom `buildSessionUsername` logic. Your provider can format session IDs according to specific proxy service requirements (such as BrightData or Oxylabs) while maintaining the same `canRotateSessions` architecture.

### Where does the session ID get injected when launching a browser instance?

In [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) lines 568-614, the code checks `proxyPool.canRotateSessions` and generates a browser-scoped session ID using `crypto.randomUUID()`. This ID is passed to `getLaunchProxy()`, which returns a proxy object containing the session-embedded username. The `normalizePlaywrightProxy` function then formats this for Playwright's `proxy` launch option.