Session replay with data masking and privacy controls

Self-hosted session replay can keep sensitive data out of recordings, but only if masking is set at capture, tested after every front-end release and backed by retention and access controls. This page covers what to configure on OpenReplay or PostHog and what to verify.

On this page

Why session replay masking is the hard part of self-hosting

A regulated team that wants to watch real user journeys faces a hard constraint: the replays must show where people get stuck without capturing card numbers, health details, account balances or the contents of forms. Self-hosting OpenReplay or PostHog keeps those recordings inside your own infrastructure, which matters for vendor risk and data location. It does not, by itself, remove personal data from the recordings. If the browser sends a balance or a diagnosis to your server, your server now stores it, whoever operates the box. That is why masking at capture, before data leaves the browser, is the control that matters, and why it should be designed and tested as a product requirement rather than left to the default settings.

The short answer is that OpenReplay's README describes capture-time sanitization that masks or skips data before it reaches the server, including masking by CSS selector and input redaction, plus a private mode that masks all text and inputs by default. Private mode is the safer starting point for regulated screens, with selective unmasking only for elements a reviewer has approved. PostHog's session replay sits in the same product family and needs the same configuration discipline, but the masking settings you rely on are part of your own configuration, so confirm them against the current PostHog documentation for your version. Before you deploy either tool, check the license terms for any feature you plan to use: the PostHog README states that premium features in its ee/ directory on a self-hosted instance require a PostHog license, and OpenReplay's Enterprise Edition under ee/ is covered by a separate commercial license.

Which privacy requirements shape the masking design

This table maps each privacy requirement that affects session replay to the source it comes from and the design decision it forces. Read it top to bottom as a build checklist, then confirm each row against your own data classification and legal review. The main takeaway is that masking must be enforced in the browser and verified after every front-end release, because server-side cleanup cannot recover data that has already been captured.

RequirementSource of the requirementWhat it means for the build
Sensitive values masked before they leave the browserInternal data classification policy and the principle of minimizing personal data collectedConfigure capture-time masking so values are redacted in the client SDK. OpenReplay documents sanitization that runs before data reaches the server, so confirm the equivalent behavior in your chosen platform and version.
Input fields redacted by defaultInternal policy for form data such as account numbers, identifiers and health or financial entriesRequire input redaction on all form fields, then allow specific non-sensitive fields to be unmasked by explicit allowlist rather than by default.
Private-by-default mode for sensitive flowsInternal risk assessment for login, onboarding, payment, benefits, or clinical pagesEnable a mode that masks all text and inputs on high-risk routes. Record which routes use it and review the list whenever pages are added.
Masking by CSS selector maintained as codeEngineering standard for change control and the reader's own privacy reviewKeep selector rules in version control with owners. Selectors break when markup changes, so each rule needs a test that fails when a sensitive element is no longer covered.
Network request and response bodies filteredInternal data minimization rule covering API payloads that carry personal or account dataDrop or redact sensitive fields in captured network bodies and headers, including authorization tokens and cookies. Confirm which network data the platform records by default.
Masking survives front-end releasesInternal release and change management controls, and the assessor's expectation of ongoing control operationAdd automated masking tests to the release pipeline that load sensitive pages, record a session and check that protected values never appear in captured output.
Access controls on replay viewingInternal access policy and the principle of least privilege for recorded user activityRestrict who can view recordings, log each view, and separate replay access from general analytics access. Confirm role and audit features in your edition, since some are sold as paid packages or enterprise options.
Self-hosted data residency for recordingsInternal data location policy and any contractual or sector limits on third-party processingKeep replay storage inside your own infrastructure. Document where recordings, backups and logs are stored and who can reach them.

How capture-time masking works in OpenReplay and PostHog

OpenReplay's README describes capture-time sanitization that masks or skips data before it reaches the server, so the goal of masking is to keep sensitive values out of the recording pipeline entirely, not only hide them in the player. The README names three controls: masking by CSS selector, input redaction, and a private mode that masks all text and inputs by default. Private mode is the strongest starting point for regulated applications because it changes the default from capture to suppression, and teams then open up specific, reviewed elements.

  • Selector-based masking: Mark elements that display account numbers, balances or personal details with the masking attribute or selector your SDK version expects, and keep those selectors in version control.
  • Input redaction: Confirm that password, card and identifier fields are redacted at capture, not only blurred in the player.
  • Private mode: Enable the default-masked mode for pages that handle personal or financial data, then allowlist only elements with a documented reason.
  • Self-hosted storage: Because sanitization runs before data reaches the server, the masked output is what your infrastructure stores, which narrows the access review.

Before relying on these controls, check the masking configuration against the SDK and server versions you run, using the OpenReplay deployment documentation as the reference.

Which self-hosted platforms fit a masking-sensitive program

Two self-hosted options dominate this use case, and each brings a different licensing split and a different set of paid features. The cards below cover what each platform documents about capture-time masking, where its license boundary falls, and which decisions need to be settled before a masking design is signed off.

OpenReplay core and masking features

OpenReplay's README documents capture-time sanitization that masks or skips data before it reaches the server, including masking by CSS selector, input redaction and a private mode that masks all text and inputs by default. Most of the monorepo is AGPLv3, and some directories are MIT. Check that your deployment only uses the code under those licenses, and test the masking rules against your own pages, since a README describes features, not your configuration.

OpenReplay Enterprise and the ee directory

Everything under the ee/ directory falls under a separate commercial license, defined in ee/LICENSE. The self-hosted Enterprise edition adds SSO and SAML, SCIM provisioning, roles and permissions, an audit trail, a custom SLA and dedicated support, sold on custom pricing with multi-year contracts. Decide whether access controls over who can view recordings need those features, and ask the vendor which capabilities sit in ee/ before you design around them.

OpenReplay single-VM starting point

The README states that a single VM with 2 vCPUs, 8 GB of RAM and 50 GB of storage is enough to start self-hosting, with targets including Docker, Kubernetes with Helm and several major clouds. That is a starting point for a test environment, not a sizing for production replay volume. Confirm storage, retention and the staging location of raw recordings before a masking rule is promoted to production.

PostHog license split and posthog-foss

PostHog's repository is MIT except for the ee/ directory, which is covered by a separate license. Premium features from ee/ on a self-hosted instance require a PostHog license. Teams that need fully free software should check this split first, then consider the posthog-foss repository, which the README says is purged of proprietary code and features. Verify which masking and privacy controls you need are present in the code you are permitted to run.

PostHog hobby deployment and support limits

PostHog offers a free Docker Compose hobby deployment under the MIT license, installed with a deploy-hobby script, and recommends a server equivalent to 4 vCPU, 16 GB of RAM and more than 30 GB of storage. Its docs state that self-hosted deployments are officially unsupported and that PostHog does not provide customer support for product or infrastructure questions on self-hosted instances. Any masking test and patch cycle you rely on is your responsibility or your implementation partner's.

PostHog volume guidance and managed regions

The README says open-source deployments should scale to approximately 100k events per month and recommends migrating to PostHog Cloud above that. Because the hosted option has US (Virginia) and EU (Frankfurt) regions, a team with high replay volume or residency rules can compare self-hosting against a managed region. Decide where masked recordings must reside, then size the deployment against that decision.

How a masking rollout moves from inventory to recurring tests

This sequence turns masking from a configuration setting into evidence: every sensitive field is mapped to a control, proven in staging and in production replays, and re-tested each time the front end ships. Each phase produces a record that a security or privacy reviewer can check.

  1. Inventory screens and fields carrying sensitive data

    Walk every page, form, modal and API response in the user journey with product, front-end and privacy owners, and list each field that can hold personal, financial or health data. Include content that users type, content the page renders from the back end, and values that appear only after login or in error states. The output is a screen-by-field register, reviewed by the privacy lead, and it is done when the front-end team confirms no route in the recording scope is missing from the list.

  2. Map each field class to a masking control

    Group the register into field classes such as account identifiers, balances, contact details, free text and health information, then assign each class a control: masking by CSS selector, input redaction, skipping the element entirely, or private-by-default mode for whole screens. The policy document records the control, the owner and the reason for each class. It is complete when every row in the register points to exactly one control and the privacy lead has signed it.

  3. Deploy a staging instance and seed synthetic data

    Install the self-hosted platform in a non-production environment that matches the production topology as closely as the team can confirm, then load the front end with synthetic accounts that carry realistic-looking but fictional values for every field class. Configure the sanitization rules from the policy, including the selectors and input settings. The output is a staging deployment with the policy applied and a list of the synthetic values planted for testing.

  4. Audit captured frames against rendered sensitive text

    Run scripted journeys with the planted synthetic values, then compare what the browser rendered with what the replay stored. Check the recorded frames, console and network captures, and any event properties for the planted strings. Any match is a defect that goes back to the policy or the selector configuration. The audit is done when every planted value is absent from stored data across all tested screens, and the results are saved as a dated report.

  5. Configure access, retention and network filtering

    Set role-based access so that only named groups can open recordings, decide the retention period with the privacy lead, and filter network payloads so that request and response bodies from sensitive endpoints are not stored. Confirm these settings in the platform's own administration screens and record them in the configuration baseline. The step closes when a test user without the right role cannot open a recording and the baseline is committed to version control.

  6. Go live with a signed sign-off record

    Enable capture in production for the agreed scope and in a limited first wave where the team can watch for problems. Repeat a short version of the capture audit against production replays using test accounts, then gather sign-off from security, privacy and product owners. The sign-off record lists the policy version, the configuration hash, the audit results and the scope enabled, and it is the document an assessor or internal reviewer will ask to see first.

  7. Gate every front-end release with masking tests

    Add the synthetic-data journey and the frame comparison to the front-end release pipeline so that a build fails when a planted value reaches a stored replay or a new screen lacks a mapped control. Route new screens through the inventory step before they ship. The gate is working when a deliberately introduced unmasked field is caught in a pre-production run and the failure is traced to the release that introduced it.

Evidence a privacy reviewer will ask for and where it comes from

This table maps each piece of evidence a privacy reviewer or assessor typically requests for a masked session replay deployment to the system or process that produces it. Use it to plan what your team must export, version and retain before an review begins. DeployOpen prepares these artifacts, but auditors, privacy regulators and your own legal function make the determination of whether the controls are adequate.

Evidence itemWhat it showsProduced byWhere it usually falls short
Masking configuration exportWhich selectors, inputs and text nodes are masked or skipped at capture, and whether private mode is onReplay platform project settings, exported and stored under change controlExported once at launch and never refreshed after later edits
Masked and excluded selector list per releaseWhich elements were covered by each front-end build that went to productionRelease pipeline that snapshots the selector inventory alongside each buildSelectors renamed in a refactor silently stop matching
Masking regression test reportsThat sensitive fields stay masked in replays after each front-end releaseAutomated browser tests run in the CI pipeline against a staging replay instanceTests cover a few pages and miss payment, profile or form screens
Network payload filter rulesWhich request and response bodies or query parameters are dropped before leaving the browserReplay SDK configuration and its version historyRules cover the main API but not third-party or newly added endpoints
Retention settingsHow long recordings and derived events are kept, per project and per data classReplay platform retention configuration and the storage lifecycle policyRetention is set for the default project but not for separate environments
Viewer and admin access logsWho opened which recordings, when, and which administrative changes were madePlatform audit trail where the edition provides it, plus identity provider logsAudit logging is an enterprise feature in some editions, so confirm availability before design
Change history of masking rulesWho changed masking rules, what changed, and the approval recorded for itVersion control for the configuration, linked to tickets or change approvalsChanges made in a web console without a corresponding commit or ticket
Records of processing entryPurpose, categories of data, recipients, retention and safeguards for session replayPrivacy office, drawn from the configuration, retention and access evidence aboveEntry describes the tool but not the masking rules actually in force

What teams ask before configuring replay masking

How much effort does replay masking take, and what drives it up?

The effort depends mostly on how many screens and components handle sensitive data, how many custom components sit outside standard form fields, and how often the front end ships. Each screen that shows balances, identifiers, health details or free text needs a masking decision, and each custom input widget may need its own selector rule. A capture audit on a sample of real user journeys shows how many elements need attention before anyone writes configuration. Teams with a small set of screens and a stable release cadence usually spend far less time than teams with dozens of flows and weekly deploys. Ask any partner to quote against a written screen inventory and a stated release rhythm, not a general estimate. Implementation effort is largely one-time, while re-checking masking after each release recurs.

What does our team need to supply before masking work starts?

Three inputs make the work faster and safer: a screen inventory, a data classification, and named owners who sign off on what gets masked. The screen inventory lists every route, modal and flow that the replay tool will record, including logged-in areas and embedded third-party frames. The data classification states which fields are personal, financial, health or credential data, and which can be captured for product analysis. Owners, usually a product lead, a privacy or compliance representative and a front-end lead, approve the rules so that nobody loosens masking later without review. Without sign-off, masking rules tend to drift as engineers add features. Confirm these artifacts with your privacy office before the engagement begins, since they define what counts as sensitive in your organization.

Can our in-house team configure replay masking without an outside partner?

Yes, if the team can run a capture audit and owns the front-end release process. Configuring capture-time masking by CSS selector, redacting inputs and enabling a private-by-default mode are engineering tasks that a competent front-end or platform team can learn from the vendor documentation. The harder part is proving the result: someone must replay real sessions, confirm that card numbers, balances and free text never appear, and repeat that check whenever the interface changes. If no one on the team has time for that cycle, or if the organization needs independent evidence for an assessment, an implementation partner can take on the audit and documentation. Compare the internal headcount cost with the cost of a fixed-scope engagement, using the scope and the release frequency as the basis.

What changes in masking after each front-end release?

Every release can add, rename or restructure elements, which can silently break a masking rule. A selector that matched a balance field may stop matching after a component refactor, and a new widget may render sensitive text without any rule at all. The practical response is a regression step in the release pipeline: replay a fixed set of test journeys against a staging environment, check that masked elements still show placeholders, and review any new screens before they reach production. Record which build each check covered so that the evidence trail is clear. Cadence matters here, so a team that deploys several times a week needs an automated check, while a team that deploys monthly may manage with a scripted manual review. Confirm with your engineering leads how releases are gated today.

Does self-hosting session replay satisfy our privacy duties?

No. Self-hosting keeps session data in your own infrastructure, and OpenReplay's documentation notes that first-party tracking from your domain is not blocked by ad blockers, but hosting location does not decide whether collection is lawful, proportionate or properly limited. Privacy duties still require you to decide what is captured, to mask sensitive data before it leaves the browser, to set retention limits, to control who can view recordings, and to honor access and erasure requests where they apply. Consent obligations may also apply in some jurisdictions, depending on the data and the purpose. Self-hosting reduces third-party transfer risk, which is one input among several. Review these duties with your privacy counsel, and treat hosting as only one control in the design.

How are retention periods and viewer access set for recordings?

Retention and access are configured at the platform level and should be decided before recording starts, not after data accumulates. Retention needs a written period for each category of recording, a deletion method, and confirmation that the platform actually removes expired replays. Access needs role-based permissions, so that only staff who need to diagnose a journey can open a recording, and an audit trail of who viewed what. Open-source editions may offer self-managed retention with community support, while enterprise editions list features such as SSO, SAML, SCIM provisioning, roles and permissions, and audit trail. Confirm in writing which of these your chosen edition provides, because access controls are often part of a paid tier, and verify them in a test environment before go-live.

What evidence should we keep to show masking works?

Keep a masking register, dated capture audit results, and release-level test records. The register lists each masked selector or field, the data class it protects, the owner who approved it and the date it was last verified. Audit results show which journeys were replayed, what was visible and what was masked, with screenshots or notes stored in a controlled location. Release records tie each verification to a build number, so you can show that the current version was checked. These artifacts help internal reviewers and external auditors assess controls, but they do not constitute an audit or certification. Ask your partner to define the evidence format up front, and confirm with your assessor which artifacts they expect.

What to ask an implementation partner about masking

Start by asking how the partner proves masking works, not only how it is configured. A masking setting that exists in a config file is not evidence that the rendered replay hides the value. Ask for the test method: whether they load seeded test accounts with known card numbers, balances and health or identity data into the real pages, record sessions, and then search the stored replay and the captured network payloads for those strings. Ask which pages are covered, including payment confirmation, account settings, search results and error states, and whether the test runs in each browser and screen size you support. Ask who keeps the test data and who can read the results.

Then ask what happens when the front end changes. Masking by CSS selector breaks quietly when a developer renames a class or moves a field into a new component, so the partner should describe how a front-end release triggers a masking regression run before it reaches production, who reviews the failures, and who has authority to block a release. Ask for the named approver on your side and on theirs. Also ask how new fields are classified, since a field nobody tagged is captured by default. For fixed-scope work, ask whether masking maintenance after go-live is covered by the agreed scope or by a separate retainer, and what the written scope says about that.

Ask how the fixed scope defines masking coverage. The scope should list the pages, flows, selectors, input types and network endpoints in or out of capture, and it should state what is excluded, such as third-party embeds, cobrowsing sessions or mobile apps if those are not part of the work. Ask for the vendor edition in writing: PostHog's README states that premium features from its ee directory need a PostHog license, and OpenReplay separates its open-source edition from Enterprise features such as SSO, SCIM and audit trail, so confirm which masking and access controls each edition provides. Finally, ask how they document configuration for reviewers: a versioned register of masking rules, the test evidence for each release, and who on your team is trained to read it. PostHog's self-host documentation says it does not provide customer support for self-hosted instances, so ask what support the partner provides instead and in what hours.

How DeployOpen scopes and supports masked session replay

DeployOpen plans, implements, hardens and documents self-hosted session replay inside your own cloud accounts, data centers or air-gapped networks. For masking work, the focus is on proving that sensitive values are removed in the browser before any recording leaves the page, and on keeping that proof valid through every front-end release.

How we scope

  • The written scope lists which pages, flows and form fields need masking, and who signs off on that list.
  • Scope covers masking rules by CSS selector, input redaction, private-by-default settings and network payload filters.
  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.

How we build

  • We deploy the chosen platform, such as OpenReplay or PostHog, inside your infrastructure and configure capture-time sanitization.
  • We write masking rules as versioned configuration and test them against sample pages that contain dummy card numbers and balances.
  • We document each rule, its owner and the release it was last verified in, so reviewers can trace every masked field.

How we hand over

  • You receive the deployed configuration, runbooks, a masking test suite and a record of what each rule covers.
  • Handover includes a checklist for front-end teams to follow when they add or rename fields, pages or third-party scripts.
  • We confirm with your teams which settings, access roles and retention limits remain under your control after go-live.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers, including re-running masking tests after front-end releases.
  • Where the platform's own support does not cover self-hosted deployments, we agree in the scope who handles fixes and upgrades.
  • Support terms are set in the written agreement, so you know who responds to a masking gap found in production.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.