"Session" and "state" get used interchangeably in browser automation, but they describe two different things with two different lifetimes. A session is the live browser process doing work right now. State is what's supposed to survive after that process is gone. Conflating them is where a lot of automation bugs come from—work that vanishes when it shouldn't, or an assumption that saving something once means it's saved forever.
A Session Is a Process, Not a Place
When you start a browser session, you're allocating a running Chromium instance with a lifecycle: it's created, it does work, and then it ends—either because your automation closed it, because it hit a maximum duration, or because it sat idle too long. None of that is about what's stored inside the browser. It's about how long the process itself is allowed to exist.
Anchor's session config exposes both ends of that lifecycle directly, so a session doesn't outlive its usefulness (or get killed mid-task):
const session = await anchorClient.sessions.create({
session: {
timeout: {
idle_timeout: 5, // end the session after 5 minutes with no connection
max_duration: 60, // hard cap regardless of activity
},
},
});
idle_timeout restarts every time a new connection attaches, so a long-running agent that reconnects periodically won't get cut off just for going quiet between actions. max_duration doesn't care about activity at all—it's a ceiling for cases like a scraping job that should never run unbounded. Whichever limit is hit first ends the session.
State Is What's Supposed to Outlive the Session
Everything inside that running browser—open tabs, in-memory JavaScript variables, WebSocket connections—disappears the moment the session ends. That's expected; none of it was meant to persist. What is meant to persist is a narrower slice: cookies, local storage, and cache, the things that let a browser skip a login flow instead of repeating it. In Anchor, that slice lives in a Profile, which is explicitly separate from the session it was captured in:
// Save state once, during a session
const session = await anchorClient.sessions.create({
browser: {
profile: { name: 'acme-portal', persist: true },
},
});
// Log in, then end the session — ending it is what writes the profile.
// Reuse the state in a completely new session later
const laterSession = await anchorClient.sessions.create({
browser: {
profile: { name: 'acme-portal' },
},
});
// This session starts already authenticated.
Notice these are two separate sessions, each with its own lifecycle and its own timeout settings. The profile is what bridges them. A common mistake is treating a long idle_timeout as a substitute for a profile—keeping a session alive to avoid re-logging in, instead of just saving the state once and starting a fresh, cheap session each time it's needed.
Why the Distinction Matters in Practice
Once sessions and state are separate concepts, a few design decisions get easier:
Size timeouts around the task, not the login. If authentication is handled by a profile, there's no reason to keep a session alive just to preserve a signed-in state. Set idle_timeout and max_duration based on how long the actual work takes.
Don't expect a profile to resurrect a dead session. Reattaching a profile gives you a new session that starts with the old cookies—it doesn't resume whatever the previous session was doing. Any in-progress navigation or unsaved in-memory state from the old session is gone.
Expect state to expire independently of any session. If the target site invalidates a cookie server-side, a session built on that profile starts unauthenticated even though the profile itself is intact. Handle that as a distinct failure mode from a session timing out.
The two concepts fail differently, so they're worth debugging differently: a session problem shows up as a task getting cut off mid-run, while a state problem shows up as a task starting from the wrong point entirely.
If you're designing automations that need predictable lifecycles on both fronts, Anchor gives you session timeouts and profiles as separate, composable controls instead of one blunt setting. Get an API key and try tuning both independently against a workflow you're already running.



