> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sente.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Sessions

> Get a browser already logged into an account — as a CDP URL for your own automation, a portable Playwright storageState, or an interactive live view for a human.

Once an account exists — [registered](/guides/register) or [connected](/guides/connect) — Sente
keeps its login alive. You don't change your automation stack to use it: ask for a session and
drive it with the Playwright/Puppeteer/browser-use code you already have.

Three ways to use a session:

* **CDP URL** — attach your own automation to a remote browser that is already logged in.
* **Exported `storageState`** — take the cookies + localStorage into your own infrastructure and
  run your own browser.
* **Live view URL** — an interactive browser page for a human (takeover, inspection).

## Open a live session (CDP)

`POST /v1/registrations/:id/session` opens a remote browser logged into the account and returns a
CDP URL. Works for connected accounts too — use the connection id.

<CodeGroup>
  ```bash CLI theme={null}
  sente session open <registrationId>
  # prints JUST the CDP url on stdout (pipeable); live view + expiry go to stderr
  sente session close <registrationId>
  ```

  ```ts TypeScript theme={null}
  const s = await sente.registrations.getSession(registration.id);
  // { sessionId, cdpUrl, liveViewUrl, expiresAt, verified, healed }

  const browser = await chromium.connectOverCDP(s.cdpUrl); // or puppeteer.connect({ browserWSEndpoint: s.cdpUrl })
  // ...drive the app...
  await sente.registrations.closeSession(registration.id);
  ```

  ```python Python theme={null}
  s = sente.registrations.get_session(registration_id)
  # { "sessionId", "cdpUrl", "liveViewUrl", "expiresAt", "verified", "healed" }

  browser = chromium.connect_over_cdp(s["cdpUrl"])
  # ...drive the app...
  sente.registrations.close_session(registration_id)
  ```
</CodeGroup>

**One live session per identity.** Close it when done (`DELETE /v1/registrations/:id/session`,
idempotent) — open sessions count against your plan's browser-minute allowance.

## Freshness and auto re-login

Sessions go stale: cookies expire, apps log you out. `getSession` verifies freshness before handing
you the browser. If the login is older than the freshness window, Sente re-logs-in first — from the
vaulted credentials, completing email verification from the identity's own inbox (created accounts)
or injecting a server-computed TOTP code (connected accounts with a seed) — and returns
`healed: true`. A recent account returns in seconds; a heal can take a minute.

At the raw API level, a stale or busy account answers `409` with a `runId` you can poll:

| 409 code          | Meaning                                                                                |
| ----------------- | -------------------------------------------------------------------------------------- |
| `SESSION_STALE`   | The login was stale; a re-login run was queued. Wait for `runId`, then retry the open. |
| `SESSION_PENDING` | A run is already in flight for this account. Wait for `runId`, then retry.             |

The SDKs' `getSession` / `get_session` handle both loops for you; the CLI does too. If the heal
run itself ends `blocked` (email/SMS MFA on a connected account, a wall), you get the run with its
`liveViewUrl` — human takeover, then resume. `openSession` / `open_session` (CLI
`sente session open --no-verify`) is the raw escape hatch: hand back the session with no freshness
check.

## Export the session — keep your Playwright stack

`POST /v1/registrations/:id/session/export` returns the logged-in browser state (cookies +
localStorage) as a standard Playwright `storageState`. Load it into your own browser, on your own
infrastructure — no CDP connection to Sente, no changes to your existing automation:

<CodeGroup>
  ```bash CLI theme={null}
  sente session export <registrationId> ./state.json
  # writes the storageState JSON (mode 0600)
  ```

  ```ts TypeScript theme={null}
  const { storageState } = await sente.registrations.exportSession(registration.id);
  const context = await browser.newContext({ storageState });
  ```

  ```python Python theme={null}
  storage_state = sente.registrations.export_session(registration_id)
  context = browser.new_context(storage_state=storage_state)
  ```
</CodeGroup>

Export runs the same verify-then-heal logic as `getSession` (same `409 SESSION_STALE` /
`SESSION_PENDING` behavior), so the state you get was just confirmed logged in. It works for
created and connected accounts.

<Warning>
  An exported `storageState` is a bearer credential for a logged-in account. Anyone holding the file
  can act as that account until the cookies expire. Store it like a secret: keep it out of version
  control, restrict file permissions, and delete it when done. The exported copy does not stay fresh
  — when it expires, export again.
</Warning>

## The live view (for humans)

Every session — and every [blocked run](/concepts/runs-and-human-takeover) — carries a
`liveViewUrl`: an interactive browser page a person can open to watch or take over. That is how a
human enters an MFA code, completes a CAPTCHA, or clicks a confirm-before-submit final submit.
Treat the URL as sensitive: anyone with it controls the logged-in browser while the session is
open. Blocked runs hold about 10 minutes; after the hold lapses the session is torn down and the
live-view URL stops working.

## Which shape to use

| You want                                                                     | Use                                                       |
| ---------------------------------------------------------------------------- | --------------------------------------------------------- |
| Drive the app now with your Playwright/Puppeteer code, no session management | `getSession` → CDP URL                                    |
| Run the browser on your own infra, keep Sente out of the hot path            | `exportSession` → `storageState`                          |
| A human to look at or act in the browser                                     | `liveViewUrl`                                             |
| Re-authenticate without opening a browser session                            | [`login`](/api-reference/registrations) (`sente relogin`) |
