Session replay for / Developers
Session replay for developers debugging production
You ship changes fast, your test suite is decent, and something still breaks for a slice of production users that neither caught. You need to see what they actually did, not a metric that shows something dipped.
What to watch for
- Console errors that correlate with one integration A third-party script — analytics, chat, a payments SDK — throwing on load takes down handlers that were supposed to bind after it, but the error reads as belonging to a library you don’t own, so it’s easy to dismiss instead of tracing to the actual broken dependency.
- Dead clicks during a slow third-party script load A button rendered before the script that makes it interactive has finished loading looks identical to a broken button. This is a different mechanism from a slow first paint — the DOM is ready, the JavaScript behind the control is not — and it needs a different fix.
- API responses that succeed with an unexpected shape A 200 with a field renamed, removed, or now nullable doesn’t throw anywhere near the failure — it throws three components downstream, if it throws at all, and the transcript is often the only place the original response and the eventual dead UI appear in the same view.
- Sessions where a feature flag changed behavior mid-session A flag flip during a long-lived tab means two users on “the same” version of your app are running different code, and a bug report that “sometimes” reproduces is often just this, invisible without knowing which cohort a specific session was in.
- Long idle stretches before an unexplained client-side redirect A redirect fired by a stale timeout, an expired token check, or a retry loop that finally gives up looks like the user did something to cause it. The stall beforehand, with no interaction, is the tell that it was the code, not the click.
What a session looks like
- 0:00 session start · /dashboard/reports · viewport 1920×1080 · Chrome 128 - 0:02 console error: "Cannot read properties of undefined (reading 'id')" - 0:02 click button "Export CSV" - ⚠ 0:03 dead click button "Export CSV" — nothing on the page responded - 0:04 click button "Export CSV" - ⚠ 0:05 dead click button "Export CSV" — nothing on the page responded - 0:19 navigated to /dashboard - 0:44 session end · total 0:44
Most session replay tools are built for marketers and demoed with heatmaps, which is a reasonable reason for an engineer to be skeptical the first time someone suggests installing one. The tool is still useful for you specifically — it just answers a different question than the one it’s usually sold on.
The gap between your existing tools
Logs tell you what the server did. Error monitoring tells you where the code threw, with a stack. Analytics tells you how many people did a thing. None of the three tell you what a user was doing in the moment something silently failed — a caught exception with an empty handler, a 200 response with a shape nobody expected, a button whose handler never bound because a script loaded out of order. That’s the specific gap a recording fills, and it’s a narrower, more useful claim than “see everything users do.”
Read the transcript, don’t watch the video
The single decision that determines whether this stays useful past week two:
filter to the sessions with a signal — an error, a rage cluster, a specific
route — and read the derived transcript before you ever open the player.
Reading is faster than the recording is to load, and a transcript line like
⚠ 0:03 dead click button "Export CSV" sitting two lines under a console
error is often the entire diagnosis. The player is still there for the moment
you actually want to see, with the timestamp already pointing at it.
Where this beats a stack trace
The recurring pattern worth watching for is the one in the transcript above: a console error that reads as belonging to a library or a helper function, followed immediately by a dead click on the control the user was trying to use. The stack trace alone tells you a property read failed somewhere. The transcript tells you it failed for every session hitting a specific report type, added in a specific release, because a field the code assumed always existed doesn’t for that one case. That correlation — one console error, one dead button, nine sessions, one shared property — is not something a stack trace surfaces on its own.
Wiring it into how you already work
The version of this that actually pays for itself connects a coding agent to your sessions over MCP, so “find the sessions with this error and tell me what’s shared between them” is a query the agent runs itself, in the same conversation where it then opens the file responsible and proposes the fix. Full setup and the tool list are in MCP agent access; the broader developer case for replay — including the performance and privacy trade-offs worth checking before you adopt anything — is in session replay for developers.
Asking your agent
$ claude "Export CSV is dead for some users, not others — find the split"
▸ usertapes list_tapes(url_contains: "/dashboard/reports", has_errors: true)
← 9 tapes this week · same console error on all 9
▸ usertapes read_transcript(a1c48e02)
← 0:02 console error: Cannot read properties of undefined (reading 'id')
0:03 ⚠ dead click "Export CSV"
▸ all 9 sessions have report.owner as null — a report type added last week
ships without an owner field; export.js assumes it always exists
Over MCP, in Claude Code or Cursor — see session replay over MCP.
Installing it here
One script tag, same as everywhere:
<script src="https://usertapes.com/tapes.js"
data-token="YOUR_SITE_TOKEN" async></script>
For a developer specifically, the workflow choice that matters more than
installation: don’t watch video to find the interesting session. Filter by
has_errors or has_rage_clicks, read the transcript, and only open the
player once you know which second to look at. See
Replay & transcripts for how the two formats
stay in sync, and connect MCP so an agent can do the
filtering and reading for you, in the same pass it edits the file.
When this is the wrong tool
- Bugs your error monitoring already catches with a full stack trace. If it throws uncaught, you already have what you need — replay adds the most value on failures that don’t throw anywhere near where they matter.
- Apps whose primary surface is canvas, WebGL, or a native embed. DOM-based replay reconstructs the DOM; it has nothing to show for a canvas frame that was never expressed as DOM nodes.
- Teams with no privacy owner. Masking is on by default and not configurable per field, which is the right default, but someone still needs to own the retention policy and answer “how long do we keep this.”