Skip to main content

Related UI example

Use the Next.js UI as a reference. Its current URL-parameter transport differs from the safer session-state pattern below.
This tutorial adapts the chat-ui-example architecture for a Next.js app that lets users chat with a Browser Use agent. Follow the integration on this page rather than copying the example repository’s query-parameter transport. The app has two pages:
  1. Home — the user types a task, the app creates a session and sends the task.
  2. Session — live browser preview, task messages, follow-ups, and recording download.
In this pattern, the SDK client lives in one server-only file, src/lib/api.ts. Short calls use Server Actions. The long-running task and its stop control use separate Route Handlers so the stop request can run while the task request is still pending.

Setup

api.ts
The API key uses BROWSER_USE_API_KEY (no NEXT_PUBLIC_ prefix) so it stays server-side. All SDK calls go through server-only Server Actions or Route Handlers — never call the SDK directly from client components.
This is a trusted-user prototype. Before exposing it publicly, authenticate every server entry point, verify that each session ID belongs to the caller, and enforce rate limits and spend quotas. A server-only API key prevents key disclosure; it does not prevent an unauthenticated visitor from spending against that key.

1. Create a session

actions.ts
  • keepAlive: true keeps the session open after each task so the user can send follow-ups (default is false).
  • enableRecording: true produces an MP4 video of the browser session.
  • maxCostUsd bounds total spend across the keep-alive session, including follow-up turns. Set the environment value to the session cap your application accepts.
  • liveUrl is checked before the server action returns, so the client receives a string rather than the SDK’s nullable response field.
The home page creates the session and navigates with only the opaque session ID. Keep the signed liveUrl and task out of query parameters, which can be copied into browser history, analytics, and request logs. This prototype uses sessionStorage; a production app should keep this state server-side under the authenticated user’s ownership:
page.tsx

2. Run a task through a Route Handler

Consume client.run() inside a Route Handler so the API key and SDK client never enter the browser bundle. A long-running Server Action would block a second Server Action from the same client, preventing the Stop button from interrupting the task. The handler collects task messages and returns them with the final session state:
app/api/browser-use/run/route.ts
Call the handler from the client component and update local UI state after it returns:
session-context.tsx
When the for await loop ends on the server, run.result contains the final session state. This pattern returns the collected messages after completion. For token-by-token or message-by-message browser updates, expose a server Route Handler that encodes the iterator as a ReadableStream; do not import the SDK client into a client component. client.run() otherwise waits for up to four hours. This example gives the Route Handler five minutes and the SDK four, leaving time to stop the task on a timeout. Set both values to limits supported by your deployment platform. For tasks longer than one request, persist messages and task state server-side and resume polling from a queue or worker rather than depending on one HTTP request. Read and delete the prototype’s initial task from sessionStorage, then run it:
session-context.tsx

3. Follow-up tasks

Follow-ups call the same Route Handler with the existing session ID:
session-context.tsx
The SDK auto-sets keepAlive: true when targeting an existing session, so follow-up tasks work without extra config.

4. Finish the session and get the recording

After a task completes, its recording URLs become available on the session. When the conversation is finished, wait for the recording and then stop the keep-alive session so its sandbox is released:
app/api/browser-use/finish/route.ts
session-context.tsx
waitForRecording polls for up to 15 seconds and returns presigned MP4 download URLs. It returns an empty array if the agent never opened a browser. Stopping the session after the poll destroys its sandbox, so call this route only when the user is finished with follow-ups.

5. Stop a task

app/api/browser-use/stop/route.ts
session-context.tsx
Because the task and stop controls are independent Route Handler requests, the stop request can reach the server while the task request is still pending. Using strategy: "task" stops only the current task, keeping the session alive for follow-ups.

6. Session page

The session page consumes everything through a context provider:
session/[id]/page.tsx

Summary