# How ego-browser Handles Chrome Data Migration and Login Inheritance

> Discover how ego-browser manages Chrome data migration and login inheritance. Learn how ego-lite ensures cookies and logins persist across automation tasks for a seamless experience.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: internals
- Published: 2026-07-24

---

**ego-browser delegates Chrome data migration to the closed-source ego-lite binary, which initializes a persisted user-data directory, runs Chromium's built-in profile migration on version upgrades, and exposes the session via CDP so that cookies and logins remain available across automation tasks.**

The open-source automation layer in citrolabs/ego-lite provides the JavaScript harness for browser control, but the heavy lifting of Chrome data migration happens inside the embedded Chromium engine. Understanding how ego-browser manages user profiles and inherits existing logins is essential for building automation workflows that persist authentication state across sessions.

## How the Chrome User-Data Directory Is Initialized

The ego-lite binary derives the profile path from the `EGO_BROWSER_DATA_PATH` environment variable, falling back to a default folder within the repository if the variable is unset. When the binary starts, it checks for an existing profile at that location and **re-uses** it rather than creating a fresh instance. This mechanism preserves all cookies, local storage entries, and saved passwords from previous sessions.

Because the profile is persisted to disk, agents can restart the harness without losing authenticated sessions on sites like Gmail or GitHub.

## Automatic Profile Migration on First-Run

When ego-lite detects a version mismatch between the stored profile schema and the current Chromium version, it triggers a transparent migration step. The binary invokes Chromium's internal `chrome::ProfileMigration` routine, which copies legacy data—including `Bookmarks`, `Login Data`, and `Cookies`—into the new format compatible with the updated engine.

This process is opaque to the automation layer; once completed, the CDP session simply sees the same logged-in state as a standard Chrome instance.

## CDP Session Attachment to Persisted Profiles

After the profile is ready, [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) establishes a Chrome DevTools Protocol (CDP) session through the `ensureSession()` function. This session attaches specifically to the **first tab** of the persisted Chrome profile, ensuring that navigation helpers operate within the context of the migrated data.

Helper functions such as `goto()` and `pageInfo()` execute against this tab, meaning previously authenticated sites remain accessible without additional login steps. Additionally, [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) exposes `state.sleep()` and other utilities that provide settling time after navigation, ensuring the session fully synchronizes with the migrated profile state.

## Blocking Internal Chrome URLs

To prevent accidental navigation to privileged browser pages, [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) defines a constant `INTERNAL_URL_PREFIXES` that filters requests to `chrome://`, `chrome-extension://`, and `devtools://` schemes. The navigation layer blocks these URLs unless explicitly allowed, protecting the user's profile integrity while maintaining normal browsing capabilities.

## Practical Implementation Examples

```javascript
// Create a task space that automatically inherits the existing Chrome profile
import { newTaskSpace, goto, pageInfo } from 'ego-browser';

await newTaskSpace('my-workspace');

// Navigate to a site where you are already logged in
await goto('https://mail.google.com');

// Retrieve page info—the logged-in inbox is immediately accessible
const info = await pageInfo();
console.log(info.title); // "Inbox – user@example.com"

```

```javascript
// Internal URL restrictions prevent navigation to chrome:// pages
import { INTERNAL_URL_PREFIXES } from 'ego-browser/src/driver/nav.js';

// This navigation would throw an error due to INTERNAL_URL_PREFIXES filtering
// await goto('chrome://settings'); // ❌ Blocked by security checks

```

## Summary

- **ego-browser** offloads data migration to the closed-source ego-lite binary that embeds the Chromium engine.
- Profile persistence relies on the `EGO_BROWSER_DATA_PATH` environment variable, falling back to a default directory.
- On version upgrades, the binary automatically runs `chrome::ProfileMigration` to convert `Login Data`, `Cookies`, and `Bookmarks` to the new schema.
- The CDP session created in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) attaches to the first tab of the persisted profile, inheriting all cookies and authentication state.
- Navigation safeguards in [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) block access to `chrome://` and `devtools://` URLs to protect profile integrity.

## Frequently Asked Questions

### Where does ego-browser store Chrome profile data?

The binary checks the `EGO_BROWSER_DATA_PATH` environment variable first, then falls back to a default folder inside the repository. This directory contains the full Chrome user-data profile including cookies, local storage, and saved passwords.

### Does ego-browser support migrating data from a standard Chrome installation?

While ego-lite runs its own embedded Chromium engine, it can reuse an existing profile directory if pointed to one via `EGO_BROWSER_DATA_PATH`. When a version mismatch occurs between the stored profile and the current Chromium version, the binary automatically invokes `chrome::ProfileMigration` to update the schema.

### Why do my logins persist across ego-browser sessions?

Because [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) creates a CDP session attached to the first tab of a **re-used** profile rather than a temporary incognito session, all authentication tokens and cookies remain intact. Helper functions like `goto()` operate on this persisted profile, giving immediate access to previously logged-in sites.

### How does ego-browser prevent navigation to sensitive Chrome internal pages?

The navigation layer in [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) maintains an `INTERNAL_URL_PREFIXES` list that blocks requests to `chrome://`, `chrome-extension://`, and `devtools://` schemes. This prevents automation scripts from accidentally accessing browser settings or extension internals while allowing normal web navigation.