The live view shows a browser's screen in Studio (KasmVNC), proxied by the engine so the container is never exposed.
Getting a link
POST /browser/<id>/live
Authorization: Bearer <user token or ENGINE_SECRET>
Content-Type: application/json
{ "access": "control", "ttlMs": 3600000 }
{
"url": "https://engine.example.com/browser/6ae0…/live/eyJicm93c2VySWQiOi….r3mcLc…/?path=browser/6ae0…/live/eyJicm93…/websockify#resize=scale&enable_webp=false",
"expiresAt": 1793167566319
}
-
A user may only get links for their own browsers.
-
access:view(watch only) orcontrol(mouse and keyboard). Defaultview. -
ttlMs: default 10 minutes; Studio asks for 1 hour. -
The token is
base64url(JSON) . HMAC-SHA256withENGINE_SECRET:{ "browserId": "6ae0…", "access": "control", "version": 0, "expiresAt": 1793167566319 }
Why the token is in the path
The link is opened inside an iframe on mooflair's origin; third-party cookies are blocked there. With the token in the path, KasmVNC's relative assets and its websocket (?path=…/websockify) carry it automatically.
The proxy
/browser/:id/live/:token/* serves the KasmVNC web client from browser-<id>:6901 on the browser's internal network and pipes the websocket both ways (messages sent before KasmVNC answers wait in a queue). It logs in as KasmVNC's control (read-write) or view (read-only) user, so view-only is enforced by KasmVNC itself. The engine sends its own Origin (KasmVNC refuses a websocket without one) and publishes live open/close events.
Before handing out a link, POST /browser/:id/live waits (up to 60 s) until KasmVNC answers, signed in as view. KasmVNC blacklists an address after 5 failed logins (for 10 s, growing), and every viewer reaches it from the engine's one address, so nothing the engine sends may be unauthenticated: an unsigned readiness ping used to lock every live view out (blank, 401).
URL options
| Hash option | Why |
|---|---|
resize=scale | Fits the remote screen to the viewer's size. |
enable_webp=false | Chrome failed to decode KasmVNC's first WebP frame, leaving view-only screens black. |
Revoke
DELETE /browser/<id>/live
Bumps the browser's live.version (every earlier link stops working) and closes open live sockets with code 4001 revoked.
FAQ
Is the stream encrypted?
Use HTTPS for the engine (a reverse proxy in front of it in production). The proxy keeps everything on the engine's origin.
Can I give someone a watch-only link?
Yes: ask for access: "view" with a short ttlMs. Revoke when done.