Session replay for AI agents: sessions as text, over an API

Session replay records what visitors do on a website so you can see where they get stuck. AgentFirstStack Replay is open-source session replay built for AI agents: the agent sets it up through an API, text and inputs are masked in the browser by default, and each session comes back as a readable transcript instead of a video.

Updated

Prompt for your agent

Paste this into Claude Code, Cursor or Codex. The agent asks you first, then sets up replay and reports what it finds.

Paste this into Claude Code, Cursor or Codex

Ask me first whether to record sessions on this site; it's a privacy decision. If I agree, set up session replay with AgentFirstStack Replay and tell me what's slowing visitors down. 1. Read the manual: https://replay.agentfirststack.com/llms.txt 2. If this project's .env already has AGENTFIRSTSTACK_API_KEY, use it. Otherwise get a key with: curl -X POST https://agentfirststack.com/v1/signup Save api_key in .env as AGENTFIRSTSTACK_API_KEY. 3. Create a replay site for the production domain. If the site runs AgentFirstStack analytics, pass its analytics_site_id (nothing to paste). Otherwise add the returned script tag to <head>. 4. Keep mask_mode strict. Unmask only non-personal UI text with unmask_selectors: nav, buttons, links, headings and labels. 5. Deploy, open https://<domain>/?afsr=1, click through the main pages, then run verify until it passes. 6. Once real sessions arrive, use search_sessions, get_session_transcript and summarize_sessions, and report the top problems with example session ids. 7. Write the replay site id in AGENTFIRSTSTACK.md (never the key), and create a claim link for me with POST https://agentfirststack.com/v1/claim-link.

What gets recorded

The recorder captures changes to the page (with rrweb), not video. A 2 KB loader decides whether a tab is recorded and loads the recorder, about 29 KB gzipped, after the page's load event. From the events, the server derives signals for each session:

  • Rage click: three or more clicks within a second on one element.
  • Dead click: nothing changes within a second of a click.
  • Error click: a JavaScript error within a second of a click.
  • Quick back: back to the previous page within 7 seconds.
  • Excessive scroll: scrolling up and down well past the page's height.
  • JS error: uncaught errors, grouped by fingerprint.

A frustration score from 0 to 100 weights those signals, so the worst sessions sort first.

Install and verify

R=https://replay.agentfirststack.com
H="Authorization: Bearer $AGENTFIRSTSTACK_API_KEY"

# With AgentFirstStack analytics on the site: link it, nothing to paste
curl -s -X POST $R/v1/sites -H "$H" -H 'content-type: application/json' \
  -d '{"domain":"example.com","analytics_site_id":"site_..."}'
# -> { "site": { "id": "rsite_...", "loads_with_analytics": true, ... }, ... }

# Without it: create the site and add the returned tag to <head>
#   <script defer src="https://replay.agentfirststack.com/r/rsite_....js"></script>

# Let transcripts name what was clicked; everything else stays masked
curl -s -X PATCH $R/v1/sites/$RSITE -H "$H" -H 'content-type: application/json' \
  -d '{"unmask_selectors":["nav","button","a","h1","h2","label"]}'

# Deploy, open https://example.com/?afsr=1 and click around, then:
curl -s -X POST $R/v1/sites/$RSITE/verify -H "$H"
# -> { "ok": true, "installed": true, "receiving_sessions": true, "domain_verified": true, "checks": [ ... ] }

?afsr=1 forces a recording of that tab, even in a headless browser, so the agent can test the install itself. Until the domain is verified, a site records a small trial (20 sessions a day, 10 until a person claims the project) with strict masking, no share links and no unmasking. verify proves the domain from the script tag on the homepage, or from a DNS TXT record at _afs-verify.<domain>.

Read sessions as text

curl -s "$R/v1/sites/$RSITE/sessions?sort=frustration&page=/checkout*&period=7d" -H "$H"
curl -s "$R/v1/sites/$RSITE/sessions/$SESSION/transcript" -H "$H"
curl -s "$R/v1/sites/$RSITE/summary?page=/checkout*&period=7d" -H "$H"

A transcript turns one session into lines an agent can read and quote. Each click carries the element's label as recorded and a stable CSS selector:

[00:00.0] page "/pricing" · load · from "google.com" · stayed 15s · saw 64% of the page
[00:03.2] scrolled to 50% of "/pricing"
[00:05.1] click button "Start trial" {"#plans > div:nth-of-type(2) > button.cta"}
[00:09.3] click x4 in 0.8s button "Pay" {"#checkout button.pay"}  [RAGE DEAD ERROR-CLICK]
[00:09.5] JS error "TypeError: Cannot read properties of undefined (reading 'id')" after click on {"#checkout button.pay"}  [ERROR-CLICK]
[00:15.0] page "/signup" · push · from "/pricing" · stayed 2s · saw 30% of the page  [QUICK-BACK]

The summary groups patterns across up to 1,000 sessions, such as top rage-click targets, JS errors, elements clicked that aren't clickable and exit pages, each with example session ids. No model is involved.

Over MCP the tools are search_sessions, get_session_transcript, summarize_sessions, get_heatmap, list_errors and get_funnel_dropoffs. When a person wants to watch one, create_replay_link returns an expiring player URL.

Privacy defaults

  • All text is masked in the visitor's browser before anything is sent. Each character becomes *, so the layout survives and the content doesn't.
  • Typed values are masked in every mode. Password, payment-card and one-time-code fields can never be unmasked.
  • Query strings and fragments are removed from every URL, and id-like path segments (emails, long numbers, tokens) become :id.
  • Browsers that send Global Privacy Control or Do Not Track aren't recorded. With require_consent, nothing is recorded until your consent banner calls afsr('consent', true).
  • No cookies: a per-tab session lives in sessionStorage.
  • block_selectors leave elements out entirely, and delete_visitor_data removes one person's sessions.

Compared with Microsoft Clarity

Microsoft ClarityAgentFirstStack Replay
SetupA person creates a project and adds the tracking codeThe agent, through the API, with verify to check it
Reading sessionsIn the Clarity app; the MCP server lists recordings, and the Data Export API allows 10 requests a dayTranscripts, summaries, heatmaps, errors and funnels over REST and MCP
Default maskingBalanced: numbers and email addresses (masking)Strict: all text and inputs
Retention30 days; favorites and a sample up to 9 months (FAQ)Up to 14 days hosted, longer when you self-host
VolumeNo traffic limits, no sampling200 sessions per site a day hosted

For the Clarity MCP server's limits, and where Hotjar stands now, see Microsoft Clarity MCP.

Microsoft Clarity and Hotjar belong to their owners. AgentFirstStack isn't affiliated with Microsoft or Hotjar. Clarity details come from Microsoft's docs, checked on 4 November 2026.

Limits on the hosted service

  • 5 replay sites per account (2 until a person claims the project), with one unverified site at a time.
  • 200 recorded sessions per site a day (100 until claimed), each up to 30 minutes and 2 MB.
  • Recordings kept up to 14 days; daily heatmap aggregates longer.
  • 5 active share links per site.

Need different limits? Self-host it: every service is an MIT-licensed Cloudflare Worker.

Questions

Is AgentFirstStack Replay open source?

Yes. The whole service is MIT licensed and runs on Cloudflare Workers, and the recorder is built on rrweb. The hosted version at replay.agentfirststack.com is free with fair-use limits.

What is a session replay API?

An API that returns recorded sessions as data instead of only as video. Here, one call lists sessions by signal or frustration score, and another returns a session as a text transcript of pages, clicks, inputs, scrolling and errors.

Does it record passwords or what visitors type?

No. Typed values are masked in every mode, and password, payment-card and one-time-code fields can never be unmasked. All other text is masked too unless you unmask specific UI elements.

Can a person watch a recording?

Yes. create_replay_link returns a player URL for one session that expires after 7 days by default. Share links need a verified domain.