BLOG
Agent Browser Record: How to Log and Replay AI Browser Sessions
Agent browser record: capture, replay, and debug AI browser sessions with hosted Chromium. Learn the CDP and Playwright setup for production.
# Agent Browser Record: How to Log and Replay AI Browser Sessions
When you run an AI agent that browses the web, you need more than a screenshot at the end. You need a full agent browser record—a replayable trace of every navigation, click, input, and network request. This is the difference between debugging a flaky agent in minutes versus hours.
In this guide, we'll cover what an agent browser record actually is, why it matters for production AI workloads, and how to implement it using hosted Chromium, CDP, and Playwright. We'll also compare the recording approaches and show you a concrete TypeScript example.
What Is an Agent Browser Record?
An agent browser record is a structured log of everything that happens inside a browser session driven by an AI agent. Unlike a simple video capture, a record includes:
- DOM snapshots at each step
- Network requests and responses (URLs, status codes, payloads)
- Console logs and errors
- Mouse and keyboard events (or their CDP equivalents)
- Screenshots at configurable intervals
- Agent decisions (the prompt, the tool call, the result)
The record is not just for post-mortem debugging. It's the foundation for:
- Replaying a session to reproduce a bug
- Evaluating agent performance against a benchmark
- Auditing what an agent did (compliance, safety)
- Training better agents with real interaction data
The term "agent browser record" is often conflated with "session recording" or "video replay." But for AI agents, the record must be machine-readable, not just human-viewable. You need to query it, diff it, and feed it back into your evaluation pipeline.
Why a Local Browser Record Isn't Enough
You can record a browser session locally with Playwright's built-in tracing or Chrome DevTools Protocol (CDP) methods. For a single script, that works. But in production, AI agents run across multiple cloud workers, often in ephemeral environments. Here's where local recording breaks down:
| Concern | Local Browser | Hosted Chromium (Remote Browser) |
|---|---|---|
| Session persistence | Lost when the worker dies | Survives across workers via persistent profiles |
| Record storage | On the local disk, hard to share | Centralized, accessible via API |
| Live debugging | Requires port forwarding or VNC | Live viewer built into the runtime |
| Network visibility | Limited to local devtools | Full request/response logging at the proxy level |
| Scaling | One browser per machine | Many isolated sessions on demand |
| Replay fidelity | Depends on local environment | Deterministic in a controlled runtime |
If you're running browser automations with Selenium or Playwright across a fleet of workers, you need the record to be a first-class artifact, not an afterthought.
How to Record an Agent Browser Session with CDP
The Chrome DevTools Protocol is the lowest-level interface for recording browser activity. Every Chromium-based browser exposes it. When you connect to a hosted browser via CDP, you can subscribe to events and build your own record.
Here's a minimal TypeScript example that connects to a Remote Browser session and captures network and console events:
import CDP from 'chrome-remote-interface';
import { RemoteBrowser } from '@remote-browser/sdk';
async function recordAgentSession() {
// 1. Create a hosted browser session
const browser = await RemoteBrowser.create({
apiKey: process.env.REMOTE_BROWSER_API_KEY,
// Persistent profile keeps cookies and state across sessions
profileId: 'my-agent-profile',
});
// 2. Get the CDP websocket endpoint
const cdpUrl = await browser.getCdpUrl();
const client = await CDP({ target: cdpUrl });
const { Network, Page, Runtime, Log } = client;
// 3. Enable the domains we want to record
await Network.enable();
await Page.enable();
await Runtime.enable();
await Log.enable();
// 4. Collect events into a structured record
const record: any[] = [];
Network.requestWillBeSent((params) => {
record.push({
type: 'network',
timestamp: Date.now(),
url: params.request.url,
method: params.request.method,
status: params.response?.status,
});
});
Log.entryAdded((params) => {
record.push({
type: 'console',
timestamp: Date.now(),
level: params.entry.level,
text: params.entry.text,
});
});
Runtime.consoleAPICalled((params) => {
record.push({
type: 'console-api',
timestamp: Date.now(),
type: params.type,
args: params.args.map((arg) => arg.value),
});
});
// 5. Navigate and let the agent work
await Page.navigate({ url: 'https://example.com' });
await Page.loadEventFired();
// 6. Save the record for later replay
await browser.saveRecord(record, { format: 'jsonl' });
// 7. Close the session or keep it alive for the next task
await browser.close();
}This gives you a raw event stream. For most production use cases, you'll want to enrich it with DOM snapshots and screenshots at key decision points.
Using Playwright Tracing for a Higher-Level Record
If you're already using Playwright, you don't need to hand-roll CDP event capture. Playwright's built-in tracing is a solid agent browser record format. It captures screenshots, DOM snapshots, network, and console in a single .zip file that you can open in the Playwright Trace Viewer.
Here's how to enable it on a hosted browser:
import { chromium } from 'playwright-core';
import { RemoteBrowser } from '@remote-browser/sdk';
async function recordWithPlaywright() {
const browser = await RemoteBrowser.connect({
apiKey: process.env.REMOTE_BROWSER_API_KEY,
// Use the CDP endpoint to attach Playwright
cdpUrl: await RemoteBrowser.getCdpUrl(),
});
const context = await browser.newContext({
recordVideo: { dir: 'videos/' },
trace: 'on', // Capture trace for every action
});
const page = await context.newPage();
// Your agent loop here
await page.goto('https://example.com');
await page.click('text=Get Started');
// Save the trace
await context.tracing.stop({ path: 'agent-trace.zip' });
// The trace file contains the full agent browser record
await browser.uploadArtifact('agent-trace.zip');
await browser.close();
}The Playwright trace is excellent for debugging. But it's not ideal for feeding back into an LLM evaluation loop because it's a binary format. For that, you'll want a JSONL record of decisions and outcomes.
What to Record for AI Agent Evaluation
A raw event log is not an evaluation dataset. To actually measure agent performance, your record should include the agent's reasoning and tool calls alongside the browser events.
Here's a practical schema for an agent browser record:
{
"session_id": "abc-123",
"timestamp": "2026-08-27T10:00:00Z",
"steps": [
{
"step": 1,
"agent_prompt": "Find the pricing page and extract the monthly cost",
"tool_call": "browser_navigate",
"tool_input": { "url": "https://remote-browser.dev/pricing" },
"tool_output": { "status": 200, "title": "Pricing - Remote Browser" },
"dom_snapshot": "<html>...</html>",
"screenshot_path": "s3://records/abc-123/step1.png",
"network_requests": [
{ "url": "https://remote-browser.dev/pricing", "status": 200 }
],
"latency_ms": 1200
}
]
}This structure lets you:
- Replay the exact sequence of tool calls
- Diff two runs to see where behavior diverged
- Score whether the agent achieved the goal
- Filter for failure patterns (e.g., repeated 404s, timeouts)
Keeping Sessions Alive Across Cloud Workers
One of the hardest problems in production browser automation is session persistence. If your agent runs on a serverless worker, the browser context dies when the function ends. The next invocation starts from scratch—losing cookies, local storage, and the navigation history.
The solution is a persistent browser profile. With Remote Browser, you create a profile once and attach it to any new session. The profile stores cookies, localStorage, and other state. This means your agent can pick up where it left off, even across different cloud workers.
Here's the pattern:
// Worker 1: Start the task
const session1 = await RemoteBrowser.create({
profileId: 'user-42-profile',
});
// ... agent works, session ends
// Worker 2: Continue the task
const session2 = await RemoteBrowser.create({
profileId: 'user-42-profile', // Same profile, new session
});
// session2 has the same cookies and state as session1This is critical for long-running tasks like form submissions, multi-page checkouts, or any workflow that requires authentication.
Live Debugging: The Missing Piece
A record is useful after the fact, but you also need to see what the agent is doing *right now*. That's where a live viewer comes in. Remote Browser provides a live viewer that streams the browser viewport in real time. You can watch the agent navigate, click, and type—and intervene if it goes off track.
For debugging, combine the live viewer with the record:
- Watch live to see the current state.
- Pause the agent if it's stuck.
- Inspect the record to see the exact sequence of events that led to the failure.
- Replay the record in a fresh session to test a fix.
This workflow is far more efficient than reading logs or watching a video after the fact.
Comparison: Recording Approaches
| Approach | Granularity | Replay | LLM-Friendly | Setup Effort |
|---|---|---|---|---|
| CDP raw events | High (network, console, DOM) | Manual | Yes (JSONL) | High |
| Playwright Trace | Medium (screenshots, DOM, network) | Built-in viewer | No (binary) | Low |
| Custom agent record | High (agent + browser) | Custom | Yes (JSON) | Medium |
| Video only | Low (visual) | Manual | No | Low |
For production AI agents, we recommend a hybrid: use Playwright tracing for debugging, and a custom JSONL record for evaluation and replay.
Production Criteria for Agent Browser Recording
Before you adopt any recording approach, verify these criteria:
- Storage: Where does the record live? Can you query it? S3-compatible object storage is a good default.
- Retention: How long do you keep records? Define a policy based on compliance needs.
- Privacy: If the agent handles PII, the record contains it. Encrypt at rest and in transit.
- Cost: Recording every network request can be expensive. Sample or filter based on importance.
- Determinism: Can you replay the record in a clean environment and get the same result? If not, your record is incomplete.
Getting Started with Remote Browser
Remote Browser is a hosted Chromium runtime designed for AI agents and browser automation. It gives you:
- CDP access for low-level control
- Playwright and Puppeteer compatibility via the standard APIs
- Persistent profiles for session continuity
- Live viewer for real-time debugging
- Configurable browser settings for proxy and stealth-related needs
To start recording agent browser sessions in production, see the documentation for API details, or check the pricing page for current limits and rates.
If you're new to hosted browsers, read our guide on remote browsers for AI agents to understand the runtime layer. For a deeper dive into the practical setup, see remote web browser and remote control browser.
Conclusion
An agent browser record is not a nice-to-have; it's a requirement for any serious AI web automation workload. It enables debugging, evaluation, and compliance. The best approach combines CDP-level event capture with a structured agent log, stored centrally and replayable on demand.
Hosted Chromium makes this practical. You get persistent sessions, centralized records, and live debugging without managing browser infrastructure yourself. Start with Playwright tracing for quick wins, then build a custom JSONL record for evaluation. Your future self—and your agents—will thank you.
For the technical details on connecting via CDP, refer to the Chrome DevTools Protocol documentation. For Playwright-specific tracing, see the Playwright trace viewer docs.