Privacy and Masking
Session Replay masks form inputs by default. Mask all page text, block elements, and use selector overrides for additional control.
Session Replay masks every form input by default. It also does not record <script> contents verbatim or capture <canvas> content. Page text is recorded as it appears unless you mask it. Use text masking, blocking, and path scoping to control what is captured.
| Behavior | What appears in replay |
|---|---|
| Mask | Asterisks replace text; element structure is intact |
| Block | Blank placeholder box; no content captured, position preserved |
| Unmask | Real text. This is an explicit opt-in for that element |
Default masking
| Surface | Default behavior | Configurable? |
|---|---|---|
<input> / <textarea> / <select> values | Always masked | No |
| Page text (paragraphs, headings, links, buttons, labels) | Recorded as it appears | Yes, mask it all with mask_all_text or mask specific elements with the classes and selectors below |
<script> text | Not recorded verbatim | No |
<canvas> content | Not captured | No |
Layer 1: Global text masking
Set mask_all_text: true to mask every piece of visible page text.
ours('init', '{cdp_token}', {
session_replay: {
token: 'replay_token',
mask_all_text: true,
},
});Replay still records the page's structure (layout, scroll position, mouse trails, and click locations) while text remains masked. Use op-session-replay-ignore only for the specific text you want to make visible.
What the masked text looks like
Text masking preserves whitespace and punctuation and replaces letters and numbers with *.
| Original | Masked |
|---|---|
Hello World | ***** ***** |
Order #1234! | ***** #****! |
you@example.com | ***@*******.*** |
日本語テキスト | ******* |
Whitespace and punctuation are preserved so the page layout stays stable in the replay.

Layer 2: CSS classes
Add these classes to specific elements throughout your application. They work with or without mask_all_text.
<!-- Replace element with a placeholder box -->
<div class="op-session-replay-block">Sensitive content</div>
<!-- Bypass masking: text captured unredacted -->
<div class="op-session-replay-ignore">Non-essential content</div>
<!-- Mask text content -->
<div class="op-session-replay-mask">Sensitive text</div>| Class | Behavior |
|---|---|
op-session-replay-block | Element is replaced with a placeholder box. No children, text, or inner HTML is captured, but the element's position and dimensions are preserved in replay |
op-session-replay-ignore | Element is captured with full structure and text: masking is bypassed. Text appears unredacted even when mask_all_text: true is active. This does not unmask form control values; <input>, <textarea>, and <select> values remain masked |
op-session-replay-mask | Element's text is masked; structure is captured |
In this replay, the form's field labels and its submit button carry op-session-replay-ignore, so they stay readable while the heading, helper text, and every typed value are masked.

When to use which
- Block PII/PHI containers, payment forms, password fields you can't otherwise reach, and any third-party iframe whose content you don't control
- Unmask (
op-session-replay-ignore) only non-sensitive elements you need legible in the replay, such as stable UI labels - Mask elements that may contain personal data but whose structure matters for analysis (for example, search results or customer names in an admin UI)
You can use mask_all_text: true with op-session-replay-ignore to carve out only the elements that should stay legible.
Layer 3: Selector overrides
When you can't add classes (third-party widgets, headless CMS output, code you don't own), pass CSS selectors directly.
ours('init', '{cdp_token}', {
session_replay: {
token: 'replay_token',
block_selector: '.cc-card, [data-private]',
ignore_selector: '.cc-noise',
mask_text_selector: '.cc-pii',
},
});| Option | Equivalent class | Notes |
|---|---|---|
block_selector | op-session-replay-block | Any standard CSS selector; comma-separated lists are supported |
ignore_selector | op-session-replay-ignore | Unmasks matching elements. This does not unmask form control values; <input>, <textarea>, and <select> values remain masked |
mask_text_selector | op-session-replay-mask | Masks text inside matching elements |
You can also enable mask_all_text: true and use ignore_selector to selectively reveal only the elements that need to stay visible.
Picking a strategy
| If you... | Start with |
|---|---|
| Have HIPAA / PHI exposure | mask_all_text: true + block_selector for any container that holds sensitive information you must exclude entirely (forms, image-based sensitive information, third-party widgets) |
| Have PII in some pages but not most | mask_text_selector or block_selector on the affected pages as needed |
| Run a heavily third-party-script-driven page | block_selector for every embed you do not control |
| Need to verify what's captured | Run a session, open it in the dashboard, and review before going live with new pages |
Next steps
- Configuration: full options reference
- FAQs
How is this guide?

