Control the live browser
The browser API provides plain REST endpoints for querying the live in-session browser’s status and navigating it to URLs — useful for programmatic browser control without an SDK or a WebSocket connection.
Authentication
Section titled “Authentication”Every request needs a Jarvis API key. Send it as
Authorization: Bearer <key> or X-Jarvis-Api-Key: <key>. A request
without a valid key is rejected with 401:
{ "success": false, "error": "A Jarvis API key is required (Authorization: Bearer <key> or X-Jarvis-Api-Key)", "code": "unauthorized"}A 502 with "code": "auth_unavailable" means key validation itself
could not be reached — retry rather than treating the key as bad.
Call these endpoints server-to-server. Cross-origin browser calls are limited to an allow-list of first-party origins, because a browser integration would have to ship your API key to end users.
Endpoints
Section titled “Endpoints”GET /api/sessions/:sessionId/browser
Section titled “GET /api/sessions/:sessionId/browser”Returns the current browser status.
Response:
{ "status": "idle", "sessionId": null, "liveViewUrl": null, "desiredUrl": null, "lastNavigatedUrl": null, "lastError": null}status is one of idle, creating, ready, expired, or error.
Once it is ready, liveViewUrl contains the URL for the live browser
view.
desiredUrl is the page the session is currently targeting and
lastNavigatedUrl the last one the browser actually reached, so the two
together tell you whether a requested navigation has landed yet.
lastError carries the reason a navigation was refused; it clears as
soon as the browser reaches a page.
POST /api/sessions/:sessionId/browser
Section titled “POST /api/sessions/:sessionId/browser”Retarget the live browser to a URL. If no browser is running yet, one is provisioned automatically and comes up on that URL.
The URL is added to the session’s known target pages and becomes the selected one, so it also survives the browser being reaped and recreated.
Request:
{ "url": "https://example.com" }Response (202):
{ "accepted": true, "url": "https://example.com", "statusUrl": "/api/sessions/:sessionId/browser"}The navigation outlives the request, so 202 means accepted, not
landed. Poll statusUrl until lastNavigatedUrl equals the URL you
asked for:
curl -s -X POST \ -H "Authorization: Bearer $JARVIS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com"}' \ "$EDITOR_WEB/api/sessions/$SESSION_ID/browser"
for _ in $(seq 30); do status=$(curl -s -H "Authorization: Bearer $JARVIS_API_KEY" \ "$EDITOR_WEB/api/sessions/$SESSION_ID/browser") echo "$status" | grep -q '"lastNavigatedUrl":"https://example.com"' && break echo "$status" | grep -q '"lastError":"' && break sleep 1doneecho "$status"A navigation the browser refuses leaves lastNavigatedUrl unchanged and
reports the reason in lastError, which is why the loop above watches
for both and gives up rather than waiting forever. A cold session pays
for the browser to start first, so allow ~30s.
Error (400):
{ "error": "url is required" }Session ID format
Section titled “Session ID format”Session IDs must match [a-z0-9][a-z0-9_-]{0,63} — lowercase
alphanumeric, 1–64 characters, may contain hyphens and underscores
(but not as the first character). Uppercase IDs are rejected and fall
through to the SPA router.
Live demo
Section titled “Live demo”Try the browser API endpoints against a real Coframe Agent backend.
Paste a Jarvis API key to get past the 401; the demo keeps it in the
page only, so a reload clears it.