Related UI example
Use the Next.js UI as a reference. Its current URL-parameter transport differs
from the safer session-state pattern below.
- Home — the user types a task, the app creates a session and sends the task.
- Session — live browser preview, task messages, follow-ups, and recording download.
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.1. Create a session
actions.ts
keepAlive: truekeeps the session open after each task so the user can send follow-ups (default isfalse).enableRecording: trueproduces an MP4 video of the browser session.maxCostUsdbounds total spend across the keep-alive session, including follow-up turns. Set the environment value to the session cap your application accepts.liveUrlis checked before the server action returns, so the client receives a string rather than the SDK’s nullable response field.
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
Consumeclient.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
session-context.tsx
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
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
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