Browser Agents
Watch the live browser
Get an authenticated WebSocket URL for available browser frames in a run you own.
Request the live-view URL using your API key and an existing run ID:
curl --fail-with-body "https://api.pre.dev/browser-agent/$BATCH_ID/ws" \
-H "Authorization: Bearer $PREDEV_API_KEY"The response is { "url": "wss://…" }. Connect to that URL exactly as returned; it includes the authorization needed for the live view. Treat it as a credential-bearing URL and keep it out of public logs.
Frames
Where live capture is available, JSON messages with type: "frame" contain:
| Field | Meaning |
|---|---|
taskIndex | Zero-based index within the run |
b64 | Base64-encoded JPEG image |
w, h | Capture metadata dimensions, when available |
ts | Unix timestamp in milliseconds |
Filter for type: "frame" before reading those fields. For a preview image, use data:image/jpeg;base64, followed by b64 as the image source.
Frames are a live visual feed, not a durable recording, task-control channel, or completion signal. Some execution paths do not produce live frames. Use SSE or polling for authoritative task state and includeEvents=true for available screenshot history.
A returned URL does not guarantee that a frame will arrive. Current SDKs and MCP tools do not have a wrapper for this endpoint.
Errors
| Status | When |
|---|---|
400 | id is not a valid run ID |
401 | Missing or invalid key |
404 | No run with this ID in your account, or no live stream for it |
Each status has an example body in the response examples. See errors and retries.
curl -X GET "https://api.pre.dev/browser-agent/string/ws"fetch("https://api.pre.dev/browser-agent/string/ws", { method: "GET"})package mainimport ( "fmt" "net/http" "io/ioutil")func main() { url := "https://api.pre.dev/browser-agent/string/ws" req, _ := http.NewRequest("GET", url, nil) res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := ioutil.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body))}import requestsurl = "https://api.pre.dev/browser-agent/string/ws"response = requests.request("GET", url)print(response.text)import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.net.http.HttpResponse.BodyHandlers;import java.time.Duration;HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build();HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() .uri(URI.create("https://api.pre.dev/browser-agent/string/ws")) .GET() .build();try { HttpResponse<String> response = client.send(requestBuilder.build(), BodyHandlers.ofString()); System.out.println("Status code: " + response.statusCode()); System.out.println("Response body: " + response.body());} catch (Exception e) { e.printStackTrace();}using System;using System.Net.Http;using System.Text;var client = new HttpClient();var response = await client.GetAsync("https://api.pre.dev/browser-agent/string/ws");var responseBody = await response.Content.ReadAsStringAsync();use reqwest::{Result, Client};async fn main() -> Result<()> { let client = Client::new(); let url = "https://api.pre.dev/browser-agent/string/ws"; let res = client .get(url) .send() .await? .text() .await?; println!("{}", res); Ok(())}{ "url": "wss://browser-worker.example/ws/507f1f77bcf86cd799439011?token=3f1c0b9e2d4a7c58"}Your pre.dev workspace API key (pdk_...) from Integrations, Built-in tab: https://pre.dev/projects/integrations?tab=built-in
In: header
Path Parameters
24-character record ID.
^[a-fA-F0-9]{24}$Response Body
application/json
Connect to the returned WebSocket URL.
TypeScript Definitions
Use the response body type in TypeScript.
application/json
Invalid request.
TypeScript Definitions
Use the response body type in TypeScript.
application/json
Missing, invalid, or ineligible authentication.
TypeScript Definitions
Use the response body type in TypeScript.
application/json
Record unavailable.
TypeScript Definitions
Use the response body type in TypeScript.