Live viewers & iframes
Show only the browser. No dashboard chrome, no viewer sign-in.
Choose a viewer experience
The dashboard viewer is for signed-in workspace users. A standalone URL at https://view.tabfleet.com/s/SESSION_ID?token=SIGNED_TOKEN grants temporary access to one browser without signing in.
Standalone links default to view-only. Interactive links require an explicit mode: "control" request made with a Browser control key. Up to eight viewers may connect at once across the dashboard and standalone view. Interactive viewers control the same page, so their actions are visible to everyone.
1. Allow your embedding origin
Embedding is disabled by default. Add your application’s exact HTTPS origin before issuing a link. Changing the allowlist revokes every existing signed viewer link for the workspace and disconnects its signed viewers.
Use exact origins such as https://your-app.example, without paths, trailing slashes, or wildcards. Every ancestor frame must be allowed. The allowlist restricts framing; it does not prevent someone from opening a copied link directly.
curl --fail-with-body -sS -X POST \
https://api.tabfleet.com/v1/viewer-settings \
-H "Authorization: Bearer $TABFLEET_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"origins":["https://your-app.example"]}'2. Mint the link on your backend
After creating a browser, request a signed link from your backend. Default TTL is 300 seconds, maximum 900 seconds, and the link can never outlive the browser lease. Pass only the resulting URL to the frontend.
const response = await fetch(
`https://api.tabfleet.com/v1/sessions/${sessionId}/share`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TABFLEET_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ mode: "view", ttlSeconds: 300 })
}
);
if (!response.ok) throw new Error("Could not create viewer link");
const { url, expiresAt } = await response.json();
// Return url and expiresAt only to an authorized user of your app.3. Embed it
Set the iframe source to the returned URL. Match the height to your product’s layout. Fullscreen is optional. Your application should refresh its displayed link by requesting another one from your backend when needed.
<iframe
src="SIGNED_VIEWER_URL"
title="Live browser"
width="100%"
height="720"
allow="fullscreen"
referrerpolicy="no-referrer"
></iframe>Revoke access
DELETE /v1/sessions/:id/share or call revoke_live_views to invalidate all signed links for that browser and disconnect the signed viewer immediately. This leaves the browser and agent running. Mint a new link to restore access.
Expiration also disconnects an open stream, including an idle one. Closing the session ends browser access. Revoking an issuing API key blocks new use immediately, while existing signed streams are checked on the normal cleanup cycle.
Do the same through MCP
An agent can manage the policy and viewer links with these tools. Change a workspace’s embedding policy only when the workspace owner intends to replace it.
viewer_embedding_settings({"origins":["https://your-app.example"]})
get_live_view({"sessionId":"SESSION_ID","mode":"view","ttlSeconds":300})
revoke_live_views({"sessionId":"SESSION_ID"})Treat links as temporary credentials
Anyone holding a signed URL can use its granted permission until expiry or revocation. Do not put workspace keys in the iframe, and exclude signed URLs from analytics, request logs, public source, and permanent public pages.
The standalone viewer uses no-store responses, no-referrer headers, restricted content security policy, and no third-party assets. Tabfleet does not record the stream. A viewer can still take their own screenshot.