Examples/Sensitive Masking

Sensitive Masking

Screenshots are masked. The DOM payload is not. See both.

Right-click the form. Watch what leaves.

Sign in & pay

Internal reference .my-secret: sk_live_51H…9fQ2

What's different: masking happens at screenshot time, by CSS selector, before the image is encoded. Password, card, data-sensitive and .my-secret fields are painted over. The element's outerHTML and innerText are still captured as text, which is why the reveal highlights them.

app/providers.tsx
'use client';
import { AnyclickProvider, DEFAULT_SENSITIVE_SELECTORS } from '@ewjdev/anyclick-react';
// Never leaves the browser: this demo only compares what was captured.
const adapter = { submitAnyclick: async () => {} };
export function Providers({ children }) {
return (
<AnyclickProvider
adapter={adapter}
scoped
menuItems={[{ type: 'capture', label: 'Capture & compare', showComment: false }]}
screenshotConfig={{
sensitiveSelectors: [...DEFAULT_SENSITIVE_SELECTORS, '.my-secret'],
maskColor: '#000000',
showPreview: true,
}}
highlightConfig={{ containerSelectors: ['[data-stage-card]'] }}
>
{children}
</AnyclickProvider>
);
}
Default selectors, custom selectors and how it works

Default Sensitive Selectors

These are masked out of the box. Add data-sensitive="true" or data-mask="true" to any element to mask it too.

// DEFAULT_SENSITIVE_SELECTORS
[
"input[type=\"password\"]",
"input[type=\"credit-card\"]",
"input[autocomplete=\"cc-number\"]",
"input[autocomplete=\"cc-csc\"]",
"input[autocomplete=\"cc-exp\"]",
"[data-sensitive=\"true\"]",
"[data-mask=\"true\"]",
".sensitive",
".private"
]

Custom Selectors

Extend the defaults rather than replacing them, unless you mean to.

app/providers.tsx
import { AnyclickProvider, DEFAULT_SENSITIVE_SELECTORS } from '@ewjdev/anyclick-react';
<AnyclickProvider
adapter={adapter}
screenshotConfig={{
sensitiveSelectors: [
...DEFAULT_SENSITIVE_SELECTORS,
'.ssn-field',
'[data-pii]',
'#api-key-display',
],
maskColor: '#000000',
}}
>
{children}
</AnyclickProvider>

How It Works

  1. 1When a screenshot is captured, anyclick injects a style that paints every element matching the sensitive selectors in the mask color.
  2. 2The image is rendered with html-to-image, then the style is removed.
  3. 3The mask is applied before compression and encoding, so the data never exists in the image.
  4. 4The preview dialog shows the masked screenshot before anything is sent.
  5. 5Text capture (outerHTML, innerText, selectors) is separate. Use stripAttributes, or keep secrets out of the DOM.