TabSailTabSail

Sessions & connections

Create, connect, and release an isolated browser.

With SDK imports from the Quickstart:

const client = new TabSail();

await client.withSession({ timeoutSeconds: 300 }, async (session) => {
  const grant = await client.sessions.connections.create(session.id, { type: "cdp" });
  // Connect your browser client using grant.url.
});

The owned scope creates, waits for readiness, then closes and confirms release.

Create parameters

ParameterTypeRequiredDefaultDescription
timeoutSecondsintegerNoInstance defaultRunning lifetime, 60–3,600 seconds
idleTimeoutSecondsinteger or nullNonullIdle expiry, 60–3,600 seconds; null disables
browserobjectNo{}Browser configuration
profileobjectNoNoneSaved browser state
regionstringNoautoauto, west, or asia
viewportobjectNoInstance defaultWidth and height, each 320–4,096
metadataobjectNo{}Up to 10 string entries; keys ≤64, values ≤256 characters

Python uses timeout_seconds. Unknown creation fields are rejected.

Lifecycle

starting → ready → closing → closed
    └─────────────→ failed
State / fieldMeaning
startingAccepted; startup is in progress
readyAvailable; inspect controller before control
closingStop requested; still occupies capacity
closed / failedManagement outcome; release may still be pending
releasedAtNon-null confirms resource release

Running lifetime begins at readiness. Startup and grant deadlines are separate. Disconnecting a client does not stop the remote browser.

Explicit ownership

With an initialized client:

const session = await client.sessions.create({ timeoutSeconds: 300 });
try {
  await client.sessions.waitUntilReady(session.id);
  // Connect and run your workflow.
} finally {
  await client.sessions.close(session.id);
  await client.sessions.waitUntilReleased(session.id);
}

Persist the session ID and creation key when work spans processes.

Connections

ParameterTypeRequiredDescription
typestringYescdp or live
modestringFor Liveview or control
handoffIdstringFor controlActive handoff ID

CDP requires automation control; Live control requires a handoff. Treat the URL as a credential. expiresAt limits new handshakes.

Reconnect

If the session is ready and automation controls it, request a fresh grant and reconnect to its existing context and pages. A new session does not inherit the old browser's memory.

Extend or keep alive

await client.sessions.update(sessionId, {
  timeoutSeconds: 600,       // New total lifetime from startedAt.
  idleTimeoutSeconds: 120,
});
await client.sessions.touch(sessionId); // Explicit idle keepalive.
await client.sessions.update(sessionId, { idleTimeoutSeconds: null });

Python: sessions.update(id, timeout_seconds=600, idle_timeout_seconds=120) and sessions.touch(id). HTTP: PATCH /v1/browser-sessions/{id} and POST /v1/browser-sessions/{id}/touch with an empty body.

The total lifetime cannot decrease or exceed 3,600 seconds. An extension reserves only the additional credit budget; insufficient credits leave the old lifetime unchanged. Repeating the same total lifetime adds no second reservation. An ended session cannot be revived.

Idle activity includes explicit touch, browser actions, page evaluation, and Live control input. GET, SSE, CDP setup, and read-only Live viewing do not renew it. Idle timeout also applies during human handoff. The paid lifetime remains the upper bound. Inspect lastActivityAt and closeReason (timeout or idle_timeout).

See configuration, capacity waiting, and resource fields.

On this page