Documentation
Privacy and masking
What is masked by default in the browser, how to hide elements and how to add your own rules.
Wutbug masks sensitive data in the user's browser, before sending anything. Masked values never reach our servers. In addition, nothing is uploaded until the person submits a report (unless you enable auto-capture).
What is masked by default
Replay and screenshot
- The value of all inputs, textareas and selects (
maskAllInputs: true). It appears as•••. - Passwords, always, even if you disable
maskAllInputs. - The text of elements with
class="wutbug-mask"ordata-wutbug-mask. - Elements with
class="wutbug-block"ordata-wutbug-blockare replaced with a gray block: their content is not recorded. - Canvases are not recorded and images are not embedded in the replay.
Request and response headers
The value of these headers is replaced with [REDACTED]:
authorization, proxy-authorization, cookie, set-cookie, x-api-key, x-auth-token, x-csrf-token, x-xsrf-token.
Keys in JSON, forms and URLs
If the name of a JSON key, an x-www-form-urlencoded field or a URL parameter matches any of these patterns (case-insensitive, anywhere in the name), its value is replaced with [REDACTED]:
pass(word)?, pwd, secret, token, api[-_]?key, authorization, ^auth$, auth[-_]?token, cookie, session(id)?, credit[-_]?card, card[-_]?number, cvv, cvc, ssn.
For example, access_token, userPassword and x-api-key match. The username and password embedded in a URL (https://user:pass@…) are also removed.
Free text
In all captured text (console arguments, error messages, stack traces, URLs and bodies), the following are searched for and replaced:
- JWTs (
eyJ….eyJ….…). - Credentials in text:
Bearer …,Basic …,Token …. - Provider keys: Stripe (
sk_live_…,rk_test_…), GitHub (ghp_…,gho_……), Slack (xoxb-……) and AWS (AKIA…). - Card numbers: sequences of 13 to 19 digits that pass the Luhn check.
Bodies
- They are truncated to 10,000 characters (
maxBodyLength). - Binary and streaming bodies are not read.
- With
captureBodies: false, no body is captured.
Hide parts of your page
<p class="wutbug-mask">Ana Pérez · SSN 123-45-6789</p>
<div class="wutbug-block">
<iframe src="https://payments.example.com/card"></iframe>
</div>If you can't touch the HTML, use selectors:
wutbug.init({
projectKey: 'pk_your_key',
endpoint: 'https://api.wutbug.dev',
privacy: {
maskTextSelector: '.profile-name, [data-pii]',
blockSelector: '#payments-widget',
},
});Add your own rules
Your own rules are added to the defaults; they never replace them.
wutbug.init({
projectKey: 'pk_your_key',
endpoint: 'https://api.wutbug.dev',
privacy: {
redactHeaders: ['x-tenant-secret'], // headers
redactKeys: ['ssn', 'dni', 'phone'], // JSON / form / query keys (regex)
redactPatterns: [/\bACME-\d{6}\b/], // any text
captureBodies: true,
maxBodyLength: 10_000,
},
ignoreUrls: ['https://payments.example.com', /\/api\/medical\//], // requests that are not recorded
});beforeSend: the last filter
For cases the rules don't cover, edit or discard the report before it is sent:
wutbug.init({
projectKey: 'pk_your_key',
endpoint: 'https://api.wutbug.dev',
beforeSend(report) {
report.network = report.network.filter((r) => !r.url.includes('/api/health-records/'));
return report;
},
});What is not masked
- Visible text on the page that isn't in an input or marked with
wutbug-mask: names, addresses or amounts your app displays are visible in the replay and screenshot. - The optional screen recording is a video of whatever the person chooses to share: it can't be masked. It only exists if the user starts it and accepts the browser permission.
- Whatever your app passes to
setUser()andsetMetadata()is stored as-is. - Whatever your app writes to the console is stored, except what matches the free-text patterns.
Recommendations
- Mark areas with visible personal data (profile, addresses, customer tables) with
wutbug-mask. - Use
wutbug-blockon payment or health iframes and widgets. - Add your country's or industry's identifiers to
redactKeys(ssn,dni,curp,nss…). - Add the suggested text about Wutbug to your privacy policy.
- Choose a retention that fits what you need.