BLOG
Browser-Use Watch: What to Track Before Production
A browser-use watch guide: what to monitor in hosted Chromium sessions, how Browserbase plans and concurrency compare, and when to move to a metered runtime.
# Browser-Use Watch: What to Track Before Production
A browser-use watch is the practice of monitoring the things that actually break browser agents in production: session lifetime, CDP connection health, concurrency headroom, and cost per browser-hour. If you run browser-use against a hosted runtime, "watch" is not a dashboard you glance at. It is the set of signals that tell you whether an agent is making progress or quietly burning hours on a stuck page. This guide covers what to instrument, how Browserbase plans and concurrency limits shape your watch strategy, and how a metered runtime like Remote Browser changes the math. Current pricing and limits live on /pricing.
The short version: watch sessions, not just tasks. A browser-use agent that fails fast is cheap. One that hangs on a CAPTCHA for 40 minutes is expensive and invisible unless you are watching the session itself.
What "Browser-Use Watch" Actually Means
Browser-use is an agent framework that drives a real browser to complete tasks. It works locally, but production deployments usually point it at a hosted Chromium instance over CDP. The "watch" layer sits between the agent loop and the browser runtime. It answers four questions continuously:
- Is the session alive and responsive over CDP?
- Is the agent making forward progress, or looping?
- Are we near a concurrency ceiling?
- What is this session costing per minute?
Most teams instrument the agent (LLM calls, token spend, step counts) and forget the browser. That is backwards. The browser is where time is consumed and where failures become expensive. A browser-use watch should treat the session as the primary unit of observability.
Why Browser-Use Needs Its Own Watch Layer
Browser-use agents are non-deterministic. The same task can take 8 steps or 80 depending on page state, model output, and whether a modal appears. That variability is fine for a demo and dangerous for a budget. Three failure modes dominate:
Silent stalls. The agent waits on a selector that never appears. The session stays open, the browser-hour meter keeps running, and nothing in the agent logs looks like an error.
Concurrency cliffs. You launch 30 tasks against a plan that allows 10 concurrent browsers. Twenty sessions queue or fail, and your retry logic doubles the load. This is where Browserbase plan tiers and concurrency limits matter most.
Connection drift. The CDP WebSocket drops mid-task. The agent throws, your orchestrator retries, and you now have an orphaned session still billing until it times out.
A watch layer catches all three. Without one, you find out from the invoice.
The Signals Worth Watching
You do not need fifty metrics. You need the ones that map to cost and correctness.
Session-level signals
- Session age vs. expected duration. Set a per-task budget. If a session exceeds it, kill it and log the last screenshot.
- CDP round-trip latency. A healthy hosted Chromium responds to
Runtime.evaluatein milliseconds. Rising latency usually means the page is overloaded or the session is degrading. - Page count and target churn. Agents that open tabs and never close them leak memory and confuse the next step.
- Last successful action timestamp. This is the single best stall detector. If no successful action has landed in N seconds, the agent is stuck.
Fleet-level signals
- Active sessions vs. concurrency limit. Track this as a ratio. Above 80% sustained, you are one burst away from queueing.
- Browser-hours consumed per task. This is your unit economics. It should be stable across similar tasks; drift means something changed on the target site.
- Failure rate by error class. Separate CDP errors, selector timeouts, CAPTCHA blocks, and agent logic errors. They have different fixes.
Cost signals
- Cost per completed task, not cost per hour. A cheap runtime that fails 30% of tasks is more expensive than a pricier one that finishes.
- Idle session time. Sessions held open between tasks are pure waste unless you are deliberately reusing a persistent profile.
Browserbase Plans, Concurrency, and the October Snapshot
Browserbase is the most common comparison point for browser-use deployments, so it is worth being concrete about how its plan structure affects a watch strategy. As of the October 2026 snapshot published on browser-use.com, Browserbase tiers look roughly like this:
| Tier | Price | Concurrent browsers | Included hours | Overage |
|---|---|---|---|---|
| Free | Free | 3 | 1 browser-hour | — |
| Developer | Monthly subscription | 25 | 100 hours | Metered per hour |
| Startup | Higher monthly subscription | 100 | 500 hours | Metered per hour |
| Scale | Sales | Custom | Custom | Custom |
Treat those numbers as a snapshot, not a contract. The structural point matters more than the digits: Browserbase bundles concurrency and hours into subscription tiers. That means your watch layer has to track two ceilings at once — the concurrency cap and the included-hours cap — because you hit them at different times. A team running short, parallel tasks hits concurrency first. A team running long research sessions hits hours first.
For comparison, Remote Browser meters usage per browser-hour with no subscription tier gating concurrency. Check /pricing for current rates and limits rather than assuming any figure. The practical difference for a browser-use watch is that you monitor one axis (hours consumed) instead of two (hours plus tier concurrency), and you scale concurrency by paying for what you use rather than by upgrading a plan.
Browser-Use Integration: Where to Attach the Watch
Browser-use connects to a remote browser over CDP. The integration point is a WebSocket endpoint. Everything you want to watch flows through that connection, which means the cleanest place to instrument is the client that owns it.
If you use browser-use's built-in cloud support, you get some session visibility for free. If you connect your own agent to a hosted runtime, you own the instrumentation. Either way, the pattern is the same: wrap the CDP connection, log every command and response, and emit session-level events to your observability stack.
A few integration details that matter:
- Persistent profiles let you reuse logins across sessions. Watch for profile corruption — a bad cookie jar will fail every subsequent task silently.
- Session isolation means each task gets a clean browser. Do not disable it to save time unless you have a specific reason; cross-task contamination is hard to debug.
- Live viewer access is useful for humans debugging a stuck session, but it is not a substitute for automated stall detection.
A Concrete Watch Implementation
The following TypeScript example connects Playwright to a hosted Chromium session over CDP and wraps the connection with basic health checks. It is deliberately minimal — the point is the shape, not a full observability stack.
import { chromium, Browser, Page } from "playwright";
interface SessionConfig {
cdpEndpoint: string; // wss://... from your runtime provider
taskBudgetMs: number; // hard ceiling per task
stallThresholdMs: number; // no progress = stuck
}
async function runWatchedTask(
cfg: SessionConfig,
task: (page: Page) => Promise<void>
) {
const started = Date.now();
let lastProgress = Date.now();
const browser: Browser = await chromium.connectOverCDP(cfg.cdpEndpoint);
const context = browser.contexts()[0] ?? (await browser.newContext());
const page = await context.newPage();
// Emit progress on every navigation and network settle.
page.on("framenavigated", () => { lastProgress = Date.now(); });
page.on("load", () => { lastProgress = Date.now(); });
const watchdog = setInterval(async () => {
const stalled = Date.now() - lastProgress > cfg.stallThresholdMs;
const overBudget = Date.now() - started > cfg.taskBudgetMs;
if (stalled || overBudget) {
console.warn("session_watch_abort", {
reason: stalled ? "stall" : "budget",
elapsedMs: Date.now() - started,
url: page.url(),
});
clearInterval(watchdog);
await browser.close(); // stops the browser-hour meter
}
}, 5_000);
try {
await task(page);
} finally {
clearInterval(watchdog);
await browser.close();
}
}Three things to note. First, browser.close() is the cost-control primitive — an open session bills whether or not the agent is doing anything. Second, the watchdog runs on a timer independent of the agent loop, so it catches stalls the agent itself cannot see. Third, logging the URL at abort time is what makes post-mortems possible.
For the underlying protocol details, the Chrome DevTools Protocol documentation is the authoritative reference for the commands your watch layer will see.
Production Criteria: What to Check Before You Commit
Before you pick a runtime for browser-use workloads, run these checks against your own task mix.
1. Can you kill a session programmatically and immediately? If session teardown lags, your cost ceiling is fiction.
2. Does the runtime expose session metadata via API? You want session ID, start time, current URL, and status without scraping a dashboard.
3. What happens at the concurrency limit? Queue, reject, or silently degrade? Each requires different orchestrator logic.
4. Are persistent profiles scoped per task or per account? Shared profiles across concurrent tasks cause login races.
5. Is the CDP endpoint stable across reconnects? Some runtimes rotate endpoints, which breaks long-lived watch connections.
6. How is usage metered — wall-clock or active time? This changes your stall-detection thresholds significantly.
If you are still choosing a runtime, the remote browser for AI agents guide covers the architectural trade-offs, and remote browser online walks through running real Chromium without local setup.
Where Remote Browser Fits
Remote Browser is a hosted Chromium runtime built for exactly this pattern. It gives you CDP endpoints that Playwright, Puppeteer, Selenium, and browser-use can connect to directly, plus a live viewer for debugging, persistent profiles for login reuse, session isolation, configurable browser settings for proxy and stealth-related needs, and usage controls that make per-session cost visible.
The relevant design choice for a browser-use watch is that sessions are the billing unit and they are easy to terminate. You do not manage a tier's concurrency ceiling; you manage how many sessions you open and how long you keep them. That makes the watch layer simpler: track session age, track stalls, close aggressively.
What Remote Browser does not do is replace your observability stack. You still need to emit the events. The runtime gives you the primitives — session lifecycle, CDP access, viewer, usage data — and you wire them into whatever you already run.
Putting the Watch Together
A browser-use watch is not a product feature you buy. It is a small amount of instrumentation applied at the right layer: the CDP connection and the session lifecycle. The teams that get this right treat browser-hours like compute spend — bounded, attributed, and alerted on. The teams that get it wrong find out at the end of the month.
Start with four signals: session age, last-progress timestamp, active-vs-limit ratio, and cost per completed task. Add more only when one of them fails to explain an incident. Then pick a runtime whose session model makes those signals easy to collect and easy to act on. For the connection mechanics, see the documentation; for current rates and limits, see /pricing.