---
site: steel.dev
collection: blog
canonical_url: https://steel.dev/blog/profiles
markdown_url: https://steel.dev/blog/profiles.md
content_signal: ai-input=yes, ai-train=yes, search=yes
related:
  - https://steel.dev/blog/more-browsers.md
  - https://steel.dev/blog/dedicated-ips.md
  - https://steel.dev/blog/mobile-mode.md
title: "Profiles: Your Agent's Persistent Identity"
description: Persistent browser identities to keep auth, cookies, cache across sessions.
date: 2025-10-13
authors:
  - Hussien Hussien
category: Product
launch_week: v2
minutes: 3
tldr: Steel Profiles store browser state (cookies, extensions, credentials, localStorage, auth tokens, fingerprints) so a session started with a profileId resumes still logged in. persistProfile controls whether changes write back. The Profiles API is live in Steel Cloud and the Python (v0.11.0+) and Node (v0.12.0+) SDKs.
topics:
  - Persistent browser profiles
  - Session state persistence
  - Authentication reuse
  - Human-in-the-loop authentication
  - Multi-tenant agent workflows
  - Anti-bot detection
entities:
  - Steel
  - Steel Profiles
  - Profiles API
  - Steel Cloud
answers_questions:
  - How do I keep a browser agent logged in across Steel sessions?
  - What browser state does a Steel profile store?
  - What is the difference between persistProfile true and false?
  - How do I set up a profile manually to handle 2FA or CAPTCHAs once?
  - Which Steel SDK versions support the Profiles API?
---

# Profiles: Your Agent's Persistent Identity

Think Chrome profiles. You have one for work, one for personal browsing, maybe one for testing. Each remembers its own logins, cookies, and settings. Steel Profiles work the same way, but you can spin them up programmatically for your agents.

Before today, every Steel session started fresh. Your agent would log in, complete a task, and when the session ended, everything was forgotten. Cookies cleared. Auth tokens gone. Next run? Log in again.

Now your agents can maintain persistent browser identities across sessions.

[Video on YouTube](https://www.youtube.com/watch?v=D2vG6K4skHg)

## How It Works

A Profile stores browser state: cookies, extensions, credentials, localStorage, auth tokens, and fingerprints. When you start a session with a `profileId`, the browser loads that state. The agent picks up effectively where it left off, still logged in, still authenticated.

Here's the simplest case, an agent that needs to stay logged in across multiple runs:

```ts
// Day 1: Agent logs in and completes a task
const session = await client.sessions.create({ 
  persistProfile: true 
});

const browser = await chromium.connectOverCDP(
  `wss://connect.steel.dev?apiKey=${apiKey}&sessionId=${session.id}`
);
const page = await browser.contexts()[0].pages()[0];

await page.goto('https://app.example.com/login');
await page.fill('#email', 'agent@company.com');
await page.fill('#password', process.env.PASSWORD);
await page.click('#login-button');

// Session ends, state is saved
await client.sessions.release(session.id);
console.log(`Profile ID: ${session.profileId}`);

// Day 2: Resume where you left off
const resumedSession = await client.sessions.create({ 
  profileId: session.profileId  // Still logged in
});
```

## Persist or Read-Only

When using an existing profile, you control whether changes write back:

```ts
// Read from profile, build on its history
const session = await client.sessions.create({ 
  profileId: 'bc252fdd-0c22-43ae-9e53-c2ffaba1108a',
  persistProfile: true  // Appends new cookies, state changes
});

// Read from profile, keep it unchanged  
const session = await client.sessions.create({ 
  profileId: 'bc252fdd-0c22-43ae-9e53-c2ffaba1108a',
  persistProfile: false  // Default: no state mutation
});
```

Set `persistProfile: true` when you want to update the profile with new authentication state or app data. Keep it `false` for read-only operations or when running parallel sessions that shouldn't interfere with each other.

## Human-in-the-Loop Setup

For complex auth flows, you can set up profiles manually. Create a session, open the debug URL, and handle the tricky parts yourself:

```ts
const session = await client.sessions.create({ 
  persistProfile: true 
});

console.log(`Complete auth here: ${session.sessionViewerUrl}`);
// Open the URL, handle 2FA, solve CAPTCHAs, accept terms, etc.

// Wait for manual completion...
await new Promise(resolve => setTimeout(resolve, 60000));

// Release the session - your auth state is saved
await client.sessions.release(session.id);

// Now your agent uses your authenticated state
const agentSession = await client.sessions.create({ 
  profileId: session.profileId 
});
```

Handle 2FA, CAPTCHAs, or SSO flows once, then let your agent reuse that authenticated state for all future runs.

## Why This Matters

**No repeated authentication**: Your agent logs in once. Every subsequent session picks up with valid auth tokens and cookies already in place.

**Better stealth**: Profiles build browsing history and reputation. Sites see a returning user, not a fresh bot on every request. Fewer CAPTCHAs, less anti-bot friction.

**Multi-tenant workflows**: Each customer gets their own profile. One authentication per tenant, reused across all their agent operations.

**Parallel testing**: Fork a baseline profile to test different agent strategies without sessions interfering with each other's state.

**Simpler infrastructure**: No more managing cookie jars in Redis or session blobs in S3. Steel handles state persistence, encryption, and retrieval.

## Available Now

The Profiles API is live today in Steel Cloud, plus Python(v0.11.0+) and Node SDKs (v0.12.0+).

**Get started:**

- [Profiles API Documentation](https://docs.steel.dev/overview/profiles-api/overview)
- [Cookbook Example](https://github.com/steel-dev/steel-cookbook/)

Questions or want to share what you build? Join us in [Discord](https://discord.gg/steel-dev) or tag us on Twitter [@steeldotdev](https://twitter.com/steeldotdev).

*This is part of Steel's launch week. More features dropping daily at* [*steel.dev/launch-week*](https://steel.dev/blog/launch-week-v2-recap)*.*
