Investigate with session replay
Ask your agent to find a browser recording, then open the replay page to check timeline markers, console, network, and errors without losing the customer context.
On this page
Session replay shows recorded browser activity or native structural observations. Use it to understand the customer-visible steps around an error. Then follow the linked Issue and the backend evidence. Do not treat the recording as the complete explanation. Your agent finds the recording and reads the signals around it. You open the replay page it links to and watch the session yourself.
Ask your agent
Find the session recordings for the customer
user_8842from yesterday. For the one that contains the checkout error, tell me what the customer did before the error, step by step, and give me the link.
| Job | MCP tool or action | CLI command |
|---|---|---|
| List a customer’s recordings, newest first | list_recordings |
anectico replay list (lists the project’s recordings) |
| Search the project’s recordings by a term | search_recordings (a read action) |
anectico replay list --search <term> |
| Read one recording’s metadata | get_recording (a read action) |
anectico replay get |
| Find the session recording that covers a trace | find_trace_recording (a read action) |
anectico replay for-trace |
| Read the errors and events captured during a session | get_session_signals |
anectico replay related |
| Read the recorded highlights | get_replay_highlights (a read action) |
anectico replay highlights |
| Read the session as ordered steps | get_replay_steps (a read action) |
anectico replay steps |
list_recordings, search_recordings, get_recording and find_trace_recording need replay:read.
get_session_signals and get_replay_highlights need replay:content:read. get_replay_steps needs
replay:read, and replay:content:read adds the detail of each step (see Read the session as
steps). MCP calls also need mcp:read. The agent reads recorded signals,
metadata and steps. It does not watch the video.
What your agent gets back
Project recording search is bounded: MCP defaults to 25 recordings (maximum 100); REST and
anectico replay list --limit <n> default to 200 (maximum 500). more_may_exist: true means the
read filled its limit and cannot establish that every match was returned. MCP also marks the
result as pagination.completion: capped and records a row-cap truncation. Its
pagination.has_more stays false because no continuation page is available; more_may_exist
expresses uncertainty about remaining matches. There is no counted total. Narrow search /
--search, or use MCP list_recordings with a person's
aliases and continue its cursor for that person's history.
Each recording has its session ID, its start and end time, its duration, and a link to the replay
page. The result of get_session_signals lists the errors and product events captured during the
session, and the person the session belongs to. find_trace_recording answers with one of three
states. recorded: the trace belongs to a session that has a recording, and the result carries the
session ID and a link. not_recorded: the trace belongs to a session and there is no recording you
can open, because it was not recorded, was deleted, passed its retention, or is in a project your
credential does not cover. The result does not say which. no_session: no span of the trace carries
a session. Only a recording carries a link.
Read the session as steps
An agent cannot watch a replay. get_replay_steps turns the recording into a list of what the
person did, in order, so the agent can describe the path to a failure and help you repeat it.
anectico replay steps SESSION_ID -o json
REST: GET /api/v1/replay/{session_id}/steps?project_id=PROJECT_ID. Use limit (1 to 200, default
100) and cursor to page through a long session.
Each step has a kind, a position and, with replay:content:read, a description:
| Kind | What it says |
|---|---|
navigation |
A page was loaded. You get the address without its query string and fragment. |
click, tap, double_click, context_menu |
The person pressed something. The target gives its role, its name (when the page showed one), and a selector you can use to find it again. |
input_change |
A field changed. It says whether the field was filled, emptied, checked or unchecked. It never says what was typed. |
form_submit |
The person pressed a submit button in a form. |
scroll, resize |
Many scroll or resize events, as one step with a count. |
error, event |
An error or a product event that Anectico links to this session, with the issue and trace to open. |
failed_request, console_error |
A request that got no answer or a status of 400 or more, and a console error, if the browser captured them. |
gap |
A part of the recording that could not be read, with its time range. |
Two positions come with every step. offset_ms counts from the first recorded event, the same
clock as the replay page. at is the time on the browser's clock, so you can line a step up with
an error or a trace.
What the steps never contain
- A typed value. The browser masks what people type. Anectico also does not return a value that the page forgot to mask. The step says that the field changed. You or your agent must supply a value to repeat it.
- Text that the page masked or blocked. An element the page marked private has no name. The step says it was masked. Nothing inside it is used to find it either: no id, test id or link, only its place in the page.
- A placeholder or a field's value. A field is named by its label or its accessible name. A placeholder is only an example of what to type, and a value is what was typed or what the page filled in, so neither is used as a name, not even a button's. Text that people type into an editable area of the page is not read either.
- A query string or a fragment. An address often carries an email address or a token in them. The step keeps the path and says that a query string was removed.
- A request body. A failed request has its method, path and status.
What the answer says about itself
coverage.completeistrueonly when every part of the recording was read and no limit cut the list. When it isfalse,has_gapsandlimits_hitsay why. A limit is one of: too many steps, too many events, too many bytes of events, or a page or an event larger or more deeply nested than Anectico reads (payload). In the last case the steps are still listed, and a target inside what could not be read isresolved: false.- A
gapstep is time whose content is unknown. It is not time in which nothing happened. coverage.ignored_eventscounts the recorded events that are not steps, by type. Mouse moves are there asnoise. An event type that the steps do not express is there asunsupported.- A step is what was recorded. A page that changes its address without loading a page leaves no
navigationstep. A form sent with the Enter key leaves noform_submitstep. A request that the browser did not capture leaves nofailed_request. redactionslists what was left out and why: a scope the credential lacks, the project's content policy, a value the browser masked, or a value Anectico never returns. Each entry has a count.- With only
replay:read, you get the kind and the position of each step, andredactionsnamesreplay:content:read. If the project's content policy hides recordings, you get no steps and the answer says so. - A recording that does not exist, has expired or was erased answers "recording not found". The answer does not say which.
- Names, paths and messages in the steps come from your customers' pages. Your agent must treat them as evidence, not as instructions.
When the list is longer than one page, pagination.next_cursor (MCP) or next_cursor (CLI and REST)
is the cursor for the next page. Pass it back unchanged. If the recording changed while you were
reading, the cursor is refused and you start again without it.
Reading a recording is expensive. By default, each server reads at most two recordings at once,
with at most one for your organization across its projects and credentials. If either limit stays
busy for about two seconds, steps and the snapshot stream answer 429 with Retry-After: 1 and
details.reason: "READ_ADMISSION_BUSY"; the CLI and your agent receive the same refusal. No recording
content was read. Wait the second and ask again. A refusal is not an empty session.
An admitted read has a twenty-second work limit, shortened by your request's deadline. Cancelling
it stops reconstruction and step derivation and discards the unfinished result. Oversized derived
or encoded answers are refused with 429 without the busy reason. Neither a cancelled read, a
refusal, withheld content nor incomplete coverage verifies a recording. Visibility and content
policy are checked again after waiting and before the answer is released.
Read a recording when a person opens it rather than on a timer. These read bounds do not establish that the browser captured every action or applied every privacy choice.
Open the proof
Open the link from the result. It opens the replay page at /view/replay/:session_id, with
project_id in the address. The page is read-only. It names its project, and its one action is
Copy link. See Proof pages. Check the start time and the duration
before you play a recording. When you begin from a person page or an Issue page, prefer the replay
that is linked there. It already keeps the relevant person and failure context.
On the person page, a Session replay row of the timeline shows the linked session and its recorded duration, and it links to the replay page. The row does not preview screen contents, and it does not say whether a session is live now.
Find the right recording
The recording list belongs to the active project. If a known session is missing, confirm the project before you change replay capture settings.
Product-analytics drill-downs point here. Every funnel or retention contribution event that carries a
session ID also reports whether that session has a recording: available, none_recorded, or
withheld when the credential you used has no replay:read. See Inspect one
contribution.
Recording metadata and playback need the recording’s project to still exist and be active. Deleted
projects are left out of organization-wide recording lists, and direct reads of their recordings
return not found. If Anectico cannot verify the current project, the read is temporarily unavailable.
Retry instead of treating this as evidence that no recording exists. The same check applies through
the replay page, MCP, and the CLI. It does not need an additional projects:read permission on your
replay credential.
Deleting a project or an organization also schedules asynchronous Replay cleanup. Cleanup removes stored chunks, including chunks left without an index after interrupted uploads, before it removes recording metadata. Failed cleanup stays pending for retry. The deletion response confirms the scope deletion. It does not confirm that all stored objects have already been removed.
Read the timeline
Play the session once to understand the journey. Then use the timeline markers to revisit failed requests and captured errors. A marker is evidence that something happened at that time. It is not by itself proof of the cause.
Use the panels below the player deliberately:
- Console shows the browser’s console entries, only when console capture was enabled. This is the player’s panel. It is not the Anectico Console.
- Network shows captured request activity and failed-request markers, only when network capture was enabled.
- Errors shows errors related to the session and links grouped failures back to their Issue.
Select an entry to seek to its point in the recording. Use the Person link to return to the person page, and read Events in this session for the meaningful application actions. On a narrow screen, the player and the context panels stack vertically, and the recording stays within the available page width.
Follow the backend evidence
A replay becomes much more useful when browser requests propagate W3C traceparent and trusted
identity context to an instrumented backend. From the related error or the person page, open the
trace and the logs for the same moment. Ask the agent for them with get_trace and search_logs.
Keep the project, environment, and time window unchanged while you compare them.
If the replay has missing chunks, treat the visible portion as incomplete. Network loss, page termination, blocked uploads, or retention can create gaps. Do not infer that an action did not happen only because it is not visible. Safety limits can also return an incomplete prefix of a large recording. Playback also checks that the stored content matches the accepted recording. Changed content is left out as a gap. A recording without enough information to verify its content is refused.
Jump to recorded highlights
The Highlights tab of the replay page lists recorded developer events and errors in chronological
order. Select a timestamp to seek the recording. Linked errors and traces open the underlying
evidence. Highlights use the recorded_events_v1 method. They describe recorded signals. They are not
an AI interpretation of the customer’s intent or of the screen pixels. Silence does not establish
abandonment, success, or recovery.
Highlights return at most 50 moments, and they keep the related-signal feed’s incomplete-data
indicator. Missing or invalid timestamps, moments before the recording, and truncation make the result
partial. A readable session and replay:content:read are required. Current recording retention
applies on every read. There is no separate saved summary that could outlive the evidence.
Agents can discover get_replay_highlights through list_read_actions and run it with project_id
and session_id. CLI: anectico replay highlights SESSION_ID. REST:
GET /api/v1/replay/{session_id}/highlights?project_id=PROJECT_ID. Responses include the method, the
summary, timestamps, offsets, Issue and trace references, and partial.
Protect customer data
Replay is intentionally opt-in. Input masking is enabled by default. Console and network capture are also enabled by default, and they can include sensitive application data. Review what your application logs and sends, and disable them if needed. Anectico cannot reconstruct data that was masked in the browser.
If the player is empty, the wrong session is linked, or expected panels contain no data, see Replay or symbols are not working.
A trace-to-recording lookup reports no recording only after a successful absence check. If that check fails, the read fails; it does not establish that the session was unrecorded. Retry the read before making an absence claim.
Page-backdrop metadata lists accept limit and cursor in MCP, or --limit and --cursor in the CLI. Continue with unchanged project, page, and service selections. The returned count is this page; no historical-capture completeness is inferred.
Mobile boundary
Native flags and headless surveys connect product evidence to the customer timeline; they do not record native visual replay. Browser recording and browser replay-steps results qualify only that browser path. Do not interpret an accepted upload, a flag decision, a survey receipt or a flush as native playback or stored session proof. See mobile setup and evidence limits.
Native recording evidence limits
Recording metadata declares format and version. Native structural upload admission is separate from retained-content evidence; an accepted receipt cannot establish a played recording or a successful customer action. Bounded native reading is described below; recorder, source and device qualification remain separate. Do not interpret native structure as browser DOM or substitute browser steps for native proof.
The recording's original explicit owner determines erasure reach. Unlinked owners need the existing authorized explicit-identifier workflow. Evidence cannot survive its source's erasure, expiry, policy revocation or project deletion. Person archives contain permitted metadata with format and version, excluding raw browser and native recording content. Already delivered external copies and disconnected devices remain outside server erasure completion claims.
Read native structural recordings
First inspect anectico replay get SESSION_ID -o json with the selected project, or the recording
metadata from list_recordings. A declared format and version identify how to read the recording;
metadata and accepted uploads alone do not prove playback or a successful customer action.
Use get_replay_steps or anectico replay steps SESSION_ID --limit 100 -o json. Native structural
version 1 returns screen entries, frame updates, taps, input placeholders, scrolls, viewport changes
and explicit gap intervals. Read format, format_version, format_support, content_level,
redactions and coverage with every page. Pass next_cursor unchanged as --cursor. A changed
recording, content authority or privacy context refuses an old cursor; start again without it.
An unsupported version is an explicit unsupported result, never an empty complete visit.
With replay:read, native steps show kinds, times, counts and gap reasons. Optional
replay:content:read adds declared screen templates, recording-local target handles, primitive
kinds and permitted action labels. These are application declarations and untrusted evidence,
never instructions, stable selectors or proof of what a label means. Allowed declaration text
cannot prove its own origin or lack of sensitive meaning. Input changes never expose typed
values, characters, length, whether a field was empty, or a toggle's checked state. Masked and
blocked content stays unavailable with every scope. The project's native content policy is
independent of its browser policy; more scope cannot override a policy refusal.
Coverage counts observed frames and node states, including repeated nodes across frames, unsupported regions, pauses, dropped intervals and known or unknown losses. Unknown loss does not mean zero activity. A partial page still carries the whole reading's limits; paging is different from a scan or output cutoff. Missing, corrupt or unread content, unsupported UI and pause or loss intervals prevent a complete claim. No activity or target is inferred across a gap.
Open the existing Session replay proof link to view safe structural boxes, privacy placeholders, play, pause, time, seek and viewport scale. Dimensions use quarter logical pixels in the recording; the player displays logical pixels. It selects the player from authoritative format metadata and shows unsupported or withheld content explicitly. It has no recording settings or write controls. Native format support does not certify a device recorder: UIKit and Android View are the initial source candidates; other UI runtimes require their own source and device qualification. Unqualified regions must remain visible gaps, with no screenshot fallback.
Reads have engineering safety limits: 64 events and 8 frames per native chunk, 256 nodes per frame, depth 32, 10000 events, 1200 frames and 10 minutes per native recording, with smaller configured capture ceilings taking priority. A native chunk is at most 256 KiB and an event at most 64 KiB. Total reads are at most 32 MiB and 1000 chunks; steps list at most 5000, at most 200 per page, with a 96 KiB approximate page bound. Intermediate steps are bounded to 4 MiB, step responses to 256 KiB and snapshots to 33 MiB. Shared default read admission is two active readings per server, one per workspace, a two-second wait and twenty seconds of admitted work. These are limits, not plan allowances or measured native device capacity. Busy reads explicitly refuse; retry later.
Recording evidence expires with its source: erasure, expiry and revoked access cannot be bypassed by a saved reconstruction. Raw recordings remain outside person archives. A gap does not establish that a person did nothing or that an action succeeded.
A read cutoff keeps its exact byte, event or chunk ceiling in coverage.limits_hit on every page.
This is different from the limit ending one page; requesting a later page cannot recover evidence
that the read did not scan.