epok

Replay privacy

Updated Oct 21, 2026 · today

Browser replay records DOM structure and changes. Non-input text is recorded by default. Input masking is not a guarantee that a page contains no personal data: review the actual pages and uploaded chunks before enabling replay for your users.

Default masking and its limits

The shipped recorder uses maskAllInputs: true. It masks ordinary text, password, and credit-card-shaped text input values, including populated autofill values, as well as textarea and select values. It does not detect payment data wherever it appears. File inputs are an exception: a selected filename can be recorded. Button labels and checkbox or radio state are not covered by the ordinary input-value masking guarantee.

Contenteditable text, open shadow-DOM text, accessible same-origin iframe text, SVG text, document titles, CSS content rules, data-* attributes, aria-label and placeholder values can be recorded. Put sensitive values behind explicit masking or blocking; do not assume that moving them out of an input makes them private. Closed shadow roots and inaccessible frames are not a privacy boundary to rely on across browser integrations.

URL redaction removes query values and fragments and scrubs sensitive or dynamic path segments. Shared text redaction also handles recognized secret patterns, but neither is a general detector for personal information in arbitrary text or attributes.

Mask text or block sensitive regions

html
<p data-private>Sensitive text: masked, element still recorded</p>
<p class="epok-mask">Sensitive text: masked</p>
<section class="epok-block">
  Sensitive contents: omitted, a sized placeholder remains
  <input type="file">
</section>

[data-private] and .epok-mask mask descendant text; they do not remove the element or guarantee attribute redaction. .epok-blockomits the element's contents and preserves a placeholder with layout dimensions. Use blocking for sensitive regions, including file pickers, and keep secrets out of class names. Apply these markers before recording starts; adding them later cannot recall earlier chunks. Changing recorder options changes this posture and needs its own validation.

What replay does not capture by default

The default browser recorder does not capture canvas pixels or drawing commands (recordCanvas is off), file contents, microphone or camera recordings, or cross-origin iframe contents. It is a DOM replay, not a video of the screen. Same-origin iframe content can be captured. Canvas fallback DOM and media element attributes can still appear in the DOM snapshot.

Replay activity captures console warnings and errors after text redaction, plus fetch method, scrubbed URL, status and timing. It does not collect request or response bodies or headers through that network hook. A console message can still contain unrecognized sensitive text; disable console capture or avoid logging such values.

User identity on RUM spans

When your app calls rum.setUser({ id }), that id is stored as user_idon the browser spans of the session so you can find one user's sessions. Spans are kept for the log retention period (seven days by default) and are not erased by the session erasure endpoint above. Pass an opaque internal id, not an email address or another direct identifier. If you do not call setUser, no user id is stored.

Retention depends on deployment settings

Automatic replay retention is disabled by default. When enabled, an hourly sweep selects expired sessions by last event time, using the configured retention window (default seven days; Growth and Enterprise tier windows are 30 days). Sessions marked to keep are skipped. For other expired sessions, it deletes payloads and retains session metadata with a purged marker. The sweep is batched, so expiry is not an exact deletion deadline.

Retention blob deletion is best effort. Failed deletions and orphaned objects require an object-store lifecycle policy configured by the operator; the application does not install that policy. Do not assume automatic expiry is active without checking the deployment. Explicit session erasure removes metadata too and reports storage failures for retry.

What the local privacy corpus verifies

The SDK corpus records a sentinel fixture through the built snippet and its bundled recorder, serializes the events into the stored gzip chunk form, and checks both masked-value absence and real DOM and mutation capture. Turning input masking off makes the same leak assertion fail. It also checks that unprotected channels remain visible, including filenames.

These are local DOM tests, not a browser compatibility certification: autofill and file selection are simulated, the iframe is same-origin, and the test environment cannot render canvas pixels. Test your own pages and browsers as well. See the browser installation guide and authentication guide.