← Blog
Session Replay·2026-04-28·6 mindraft · not yet final

Session Replay masking — the privacy guide nobody wrote

Default masking covers form inputs. It does not cover account balances, internal IDs, or PII rendered in plain text. Here's what to actually configure.

Amplitude Session Replay's default privacy configuration covers form inputs. That is the entire scope of the default. Any text content rendered in the page — account balances, internal IDs, PII shown in tooltips, sensitive copy in modals — is recorded as-is and visible to anyone in the team who can view replays.

For most B2B and finance-adjacent products, this is below the privacy bar the rest of the company assumes the tool meets. The fix is straightforward, but it is not the default and it is not loudly documented.

What the default actually masks

maskAllInputs: true is the default. It replaces text in <input>, <textarea>, and <select> elements with asterisks during replay capture. That covers signup forms, search bars, settings panels, and most explicit user-input surfaces.

It does not cover:

  • Read-only data displayed to the user (balances, transaction histories, customer lists)
  • PII shown in notifications, tooltips, banners, modal headers
  • Internal identifiers displayed in admin panels
  • Free-text content in messaging interfaces (chats, comments, notes)
  • API responses rendered into the DOM after the user authenticates
  • Anything injected via JavaScript after the page initially loads

For most product surfaces in B2B SaaS, the bulk of sensitive content lives in those categories.

What to configure instead

Two privacy primitives matter: blockSelector (the element is not recorded at all) and maskSelector (the element is recorded structurally but the text is replaced with asterisks).

The right pattern in most products: tag sensitive elements with a data attribute, then configure the SDK to block or mask everything that carries that attribute.

import { sessionReplayPlugin } from '@amplitude/plugin-session-replay-browser';

amplitude.add(sessionReplayPlugin({
  sampleRate: 0.1,
  privacyConfig: {
    blockSelector: [
      '[data-sensitive]',          // anything explicitly tagged
      '.account-balance',          // known sensitive UI patterns
      '.payment-details',
      '[data-replay-block]'
    ],
    maskSelector: [
      '[data-pii]',                // PII that should be replaced but visible structurally
      '.account-number',
      '[data-replay-mask]'
    ],
  },
}));

The benefit of using data attributes: the privacy decision lives next to the element that needs the privacy. When designers build new screens, they tag the sensitive elements as part of the build, and the privacy config keeps working without coordination.

Common patterns that need explicit configuration

Inventory of what to tag, by typical SaaS surface area.

Account / billing surfaces. Account balances, payment methods, invoice line items, billing email. block everything; the structural information is rarely needed for replay analysis.

Admin panels. Customer lists, internal IDs, support tickets. block if the panel is staff-only; mask if it shows data the user themselves needs to see.

Messaging surfaces. Chat content, comment bodies, notes. mask the body content; the structural shape (timestamps, sender, length) is fine to replay.

B2B account information. Other employees' names, internal team structures, organisation-level settings. Mask names and IDs; the layout can stay.

Notification / banner surfaces. Anything that displays user-specific data after authentication. Mask the dynamic content; the banner shape can stay.

What we check for

The Amplitude Auditor flags Session Replay configurations where:

  • Replay is enabled with default masking only (no custom blur or mask rules)
  • No blockSelector or maskSelector rules are defined
  • The team has not added at least one custom rule

The finding is rendered as replay:masking and explains the specific configuration gap on your project. Run an audit and the masking config is reported with the specific rule recommendations.

How to test the masking is working

Three tests, in order.

  1. Local DOM test. Add a sensitive-tagged element to a test page. Trigger a session replay. Open it in Amplitude. Verify the element is blocked or masked.
  2. Production smoke test. After deploying the privacy config, run an end-to-end session in a known-sensitive flow (sign in, view billing, view admin). Open the resulting replay. Verify the sensitive content is not visible.
  3. Quarterly audit. Designers ship new sensitive UIs that nobody tagged. Run a periodic check — a structured pass through the most-recorded screens — and add tags to whatever was missed.

FAQ

Why is the default masking so limited? Defaults are conservative — masking too aggressively breaks analysis. Forms are the universally sensitive surface, so they are masked by default. Read-only content varies by product, so it is left to each implementation to configure.

Does masking affect storage costs? No. Replays are stored compressed regardless of masking. Masking changes what the SDK captures, not how much. It does, however, affect what is rendered when someone views the replay.

Can I retrofit masking on existing replays? No. Masking is applied at capture time. Existing replays remain as they were captured. The fix is forward-only — configure masking now, ensure new captures are protected, accept that older captures are not retroactively fixed.

How often should this be audited? Quarterly is reasonable for stable products. Monthly is reasonable for products shipping a lot of new UI. Tag the privacy audit as a recurring engineering chore — design changes are the most common source of new gaps.

Get the post when it lands

Plus the audit when access opens.