# How camofox-browser Proxy Integration with GeoIP Automatic Locale Detection Works

> Discover how camofox-browser integrates with GeoIP to automatically detect locale and timezone from proxy IP addresses, enhancing your Playwright sessions.

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

---

**camofox-browser automatically detects a client’s locale, timezone, and geolocation from the IP address of the configured proxy, then passes these values to Playwright’s browser context to ensure the automated session geographically matches the proxy server.**

The camofox-browser project synchronizes browser fingerprinting with proxy infrastructure by wiring proxy Pools into Playwright’s launch sequence. This integration eliminates manual locale configuration by leveraging the proxy’s exit IP to drive automatic geographic detection. Below is the complete technical flow as implemented in the `jo-inc/camofox-browser` repository.

## Proxy Pool Initialization and Session Support

When the server starts, it reads the `CONFIG.proxy` object populated from [`lib/config.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/config.js) and initializes a connection manager using `createProxyPool()` (see [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) lines [409-418](https://github.com/jo-inc/camofox-browser/blob/master/server.js#L409-L418)).

The proxy pool exposes a `canRotateSessions` boolean that indicates whether the provider supports **per-context session rotation**. For back-connect providers such as Decodo or BrightData, the pool can embed a unique session ID into the proxy username, enabling each browser tab to acquire a distinct IP address and independent geographic fingerprint.

## Launch-Time Proxy Selection and the GeoIP Flag

When a client request triggers a new browser tab, the server requests a launch proxy from the pool:

```js
const launchProxy = proxyPool
  ? proxyPool.getLaunchProxy(
      proxyPool.canRotateSessions
        ? `browser-${crypto.randomUUID().replace(/-/g, '').slice(0, 12)}`
        : undefined
    )
  : undefined;

```

(See [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) lines [564-574](https://github.com/jo-inc/camofox-browser/blob/master/server.js#L564-L574).)

If a proxy is returned, the server sets `geoip: !!launchProxy` in the launch payload (lines [592-607](https://github.com/jo-inc/camofox-browser/blob/master/server.js#L592-L607)). This boolean flag signals downstream logic to apply GeoIP-based locale configuration.

## Automatic Locale and Timezone Configuration

Before invoking `browser.newContext()`, the server assembles `contextOptions`. When the `geoip` flag is true, the options object is automatically populated with default locale and timezone values that align with the proxy’s expected IP range:

```js
const contextOptions = {
  // Additional permissions and viewport settings...
};

if (geoip) {
  contextOptions.locale = 'en-US';
  contextOptions.timezoneId = 'America/Los_Angeles';
  contextOptions.geolocation = { latitude: 37.7749, longitude: -122.4194 };
}

contextOptions.proxy = normalizePlaywrightProxy(sessionProxy);
const context = await browser.newContext(contextOptions);

```

(See [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) lines [723-744](https://github.com/jo-inc/camofox-browser/blob/master/server.js#L723-L744).)

These initial values act as placeholders; Playwright subsequently overrides them based on the actual geographic data associated with the proxy’s public IP.

## Playwright’s Native Geo-IP Handling

Playwright’s engine detects the `proxy` field in the context options and routes all TCP connections through the specified proxy server. By observing the exit IP of the proxy hop, Playwright **automatically infers the client’s public IP** and adjusts the browser’s internal `navigator.language`, `Intl.DateTimeFormat().resolvedOptions().timeZone`, and `navigator.geolocation` values to match the IP’s geographic location. No additional instrumentation is required; the mere presence of a working proxy triggers Playwright’s Geo-IP resolution path.

## Per-Context Session Rotation for Isolated IPs

For providers that return `canRotateSessions: true`, camofox-browser enables per-tab geographic isolation. The system generates a unique session identifier for each tab and embeds it into the proxy credentials via `buildSessionUsername()` in [`lib/proxy.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/proxy.js) (lines [72-94](https://github.com/jo-inc/camofox-browser/blob/master/lib/proxy.js#L72-L94)):

```js
export const decodoProvider = {
  name: 'decodo',
  canRotateSessions: true,
  buildSessionUsername(baseUsername, { country, sessionId }) {
    const parts = [`user-${sanitizeBackconnectValue(baseUsername)}`];
    if (country) parts.push(`country-${sanitizeBackconnectValue(country)}`);
    if (sessionId) parts.push(`session-${sanitizeBackconnectValue(sessionId)}`);
    return parts.join('-');
  },
};

```

Each tab therefore connects through a **different back-connect session**, yielding independent IP addresses and unique Geo-IP detection results per browser context.

## Implementation Examples

### Basic Server Start with Auto Geo-IP

Configure environment variables for a back-connect provider:

```bash

# .env

PROXY_STRATEGY=back_connect
PROXY_BACKCONNECT_HOST=gate.proxy.com
PROXY_BACKCONNECT_PORT=7000
PROXY_USERNAME=myuser
PROXY_PASSWORD=mypass
PROXY_COUNTRY=US

```

Initialize the pool in [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js):

```js
import { createProxyPool } from './lib/proxy.js';
import CONFIG from './lib/config.js';

const proxyPool = createProxyPool(CONFIG.proxy);
if (proxyPool) {
  console.log('Proxy pool created', {
    mode: proxyPool.mode,
    canRotate: proxyPool.canRotateSessions,
  });
}

```

When handling a new tab request:

```js
const launchProxy = proxyPool
  ? proxyPool.getLaunchProxy(`browser-${crypto.randomUUID().slice(0, 12)}`)
  : undefined;

const contextOptions = {
  permissions: ['geolocation'],
  locale: launchProxy ? 'en-US' : undefined,
  timezoneId: launchProxy ? 'America/Los_Angeles' : undefined,
  geolocation: launchProxy
    ? { latitude: 37.7749, longitude: -122.4194 }
    : undefined,
  proxy: launchProxy ? normalizePlaywrightProxy(launchProxy) : undefined,
};

const context = await browser.newContext(contextOptions);

```

Playwright exposes the correct `navigator.language`, timezone, and geolocation values corresponding to the proxy’s public IP.

### Per-Tab Session Isolation

Request a fresh session for each tab to ensure independent Geo-IP data:

```js
const sessionId = `ctx-${userId}-${Date.now()}`;
const launchProxy = proxyPool
  ? proxyPool.getLaunchProxy(sessionId)
  : undefined;

// Each tab now uses a distinct IP address from the provider’s pool
const context = await browser.newContext({
  proxy: normalizePlaywrightProxy(launchProxy),
});

```

## Summary

- **Proxy Pool Creation**: `createProxyPool()` in [`lib/proxy.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/proxy.js) initializes the connection manager and detects session rotation support via `canRotateSessions`.
- **GeoIP Flag**: In [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js), the `geoip` boolean is set to true whenever a launch proxy is retrieved, triggering automatic locale configuration.
- **Context Options**: Default `locale`, `timezoneId`, and `geolocation` values are injected into `contextOptions` before `browser.newContext()` is called.
- **Playwright Automation**: Playwright automatically translates the proxy’s exit IP into browser-exposed locale, timezone, and geolocation values.
- **Session Rotation**: Back-connect providers use `buildSessionUsername()` to embed unique session IDs, enabling per-tab IP isolation and independent geographic detection.

## Frequently Asked Questions

### How does camofox-browser detect the correct locale without manual configuration?

The system relies on Playwright’s built-in Geo-IP capabilities. When a proxy is configured in the browser context, Playwright routes traffic through that proxy, detects the public IP address of the exit node, and automatically sets the browser’s `navigator.language`, timezone, and geolocation to match the IP’s geographic region.

### What is the purpose of the `canRotateSessions` flag in the proxy pool?

The `canRotateSessions` boolean indicates whether the proxy provider supports back-connect rotation. When true, camofox-browser generates a unique session ID for each browser tab and embeds it into the proxy username via `buildSessionUsername()`, ensuring each tab receives a different IP address from the provider’s pool.

### Which source files handle the proxy and GeoIP logic?

The main implementation spans three files: [`lib/proxy.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/proxy.js) contains the pool factory and provider-specific logic including `createProxyPool()` and `buildSessionUsername()`; [`lib/config.js`](https://github.com/jo-inc/camofox-browser/blob/main/lib/config.js) provides the `CONFIG.proxy` object; and [`server.js`](https://github.com/jo-inc/camofox-browser/blob/main/server.js) orchestrates the launch flow, sets the `geoip` flag, and builds the `contextOptions` passed to Playwright.

### Does camofox-browser support static proxy configurations?

Yes. While the system optimizes for back-connect providers with session rotation, it also supports static proxies. If `canRotateSessions` is false, the `getLaunchProxy()` method returns the same proxy configuration for every context, and Playwright still performs automatic Geo-IP detection based on that single exit IP.