Glossary

What rrweb Records, and How Its Privacy Options Work

Taras Shynkarenko
Taras Shynkarenko
•Updated: •8 min read
What rrweb Records, and How Its Privacy Options WorkWhat rrweb Records, and How Its Privacy Options Work

TL;DR, Quick Answer

8 min read

The open-source library rrweb records a browser session as one serialized DOM snapshot followed by a stream of incremental events (DOM mutations, mouse movement, clicks, scrolls, resizes and input), then rebuilds the page inside a sandboxed iframe to replay it. It records no video. It is MIT licensed, and its guide now points new projects to @rrweb/record and @rrweb/replay instead of the older rrweb package. Out of the box it masks only password inputs; maskAllInputs, blockClass, maskTextClass and their selector twins widen that.

What is rrweb?

The open-source library rrweb, short for "record and replay the web", records a user's session in the browser as structured JSON and plays it back as a watchable reconstruction of the page. The project README describes it as "a tool for recording and replaying users' interactions on the web." It lives at github.com/rrweb-io/rrweb, the repository was created in October 2018, and the code is written in TypeScript so the recorder and the player share one typed event format.

rrweb is a library, not a product. It gives you a recorder that emits events and a player that consumes them. Where those events go, how long you keep them and who can watch them is your code's job. That split is why so many commercial replay tools start from it, and why session replay in general looks so similar from vendor to vendor.

Does rrweb record video?

No. rrweb records the state of the page, not its pixels. On start, the recorder walks the DOM and serializes it into a tree of nodes, each with a unique numeric id. The project's serialization doc calls this output "descriptive": scripts are swapped for placeholder noscript tags, input values are copied into a value attribute, relative URLs become absolute, and external stylesheets are inlined so the replay still renders when the original CSS is unreachable.

After that full snapshot, everything is a diff. The recorder attaches a MutationObserver and a set of listeners, and the observer doc lists what it captures:

  • DOM changes: node creation, deletion, attribute changes and text changes
  • Mouse movement
  • Mouse interaction: mouse up and down, click, double click, context menu, focus, blur, and touch start, move and end
  • Page or element scrolling
  • Window size changes
  • Input

Every event carries a timestamp and a numeric type. The event types are DomContentLoaded, Load, FullSnapshot, IncrementalSnapshot, Meta and Custom, and incremental events add a data.source field that says whether the change was a mutation, a mouse move, a scroll and so on.

The replayer rebuilds the snapshot inside an iframe and applies the incremental events in order. It never executes the recorded page's JavaScript. rrweb's sandbox doc explains that the iframe's sandbox attribute blocks form submission, pop-ups such as window.open, and scripts, including inline handlers and javascript: URLs. Because the page is rebuilt from nodes, text in a replay is real text you can select. If you do need a video file, the monorepo ships rrvideo, which it describes as "a tool for transforming the session recorded by rrweb into a video."

The same dependency on MutationObserver sets rrweb's browser floor. The guide states that "rrweb does not support IE11 and below because it uses the MutationObserver API".

Which rrweb packages should you install?

The rrweb guide recommends @rrweb/record plus @rrweb/replay for most projects, and @rrweb/all when you want one import for recording, replay and the packer. The table lists the main packages in the monorepo as its packages README describes them. Every one was at version 2.1.6 on npm, published 18 September 2026, when this page was written.

PackageWhat it does
@rrweb/recordThe recording code, meant to run in your front-end app or page
@rrweb/replayRebuilds and replays recorded events in an iframe
@rrweb/allRecord, replay and the packer in one package, no plugins
rrweb-playerA playback UI with pause, fast-forward and seeking, built on @rrweb/replay
rrweb-snapshotSerializes the DOM and rebuilds it, the basis of the FullSnapshot event
@rrweb/packerPer-event compression before network transfer
@rrweb/types, @rrweb/utilsShared types and helpers
rrdom, rrdom-nodejsA virtual DOM used to fast-forward mutations during replay, plus a Node.js version
rrvideoConverts a recording into a video
rrwebThe original package with record and replay together

The original rrweb package is where the documentation and the registry disagree. The guide says: "The rrweb package is deprecated. It still works, but new projects should use @rrweb/record and @rrweb/replay." On npm, rrweb 2.1.6 carries no deprecation notice, and it still out-downloads its replacement: npm's download API counted 1,874,214 downloads of rrweb in the week of 15 to 21 September 2026, against 498,366 for @rrweb/record. Anyone installing it gets no warning. If you are starting fresh, follow the guide and install the split packages, because the rrweb package is the one the maintainers plan to slim down and remove.

What licence is rrweb released under?

rrweb is released under the MIT License. The repository's LICENSE file opens with "Copyright (c) 2018 Contributors", and npm lists MIT for each package above. MIT lets you use, modify and ship rrweb in closed-source commercial software as long as you keep the copyright and licence notice.

That permissive licence explains the forks. Sentry's replay package depends on @sentry/rrweb and @sentry/rrweb-snapshot, according to its package.json in the sentry-javascript repository. PostHog's browser SDK depends on @posthog/rrweb and @posthog/rrweb-record. Both vendors maintain their own copy, so a fix in upstream rrweb does not reach their users until the vendor merges it, and the option names and defaults in their SDKs differ from rrweb's own.

Which rrweb options control privacy?

rrweb exposes its privacy controls as options on record(). The names and defaults below are copied from the Record Options table in guide.md.

OptionDefaultWhat it does
blockClass'rr-block'Elements to block, as a string or RegExp
blockSelectornullA selector for elements to block
ignoreClass'rr-ignore'Elements whose input events are ignored, as a string or RegExp
ignoreSelectornullA selector for elements to ignore
maskTextClass'rr-mask'Elements whose text is masked, as a string or RegExp
maskTextSelectornullA selector for elements to mask
maskAllInputsfalseMasks all input content as *
maskInputOptions{ password: true }Masks some kinds of input
maskInputFnnoneCustom logic for masking input content
maskTextFnnoneCustom logic for masking text content
ignoreCSSAttributesnullAn array of CSS attributes to ignore
recordCanvasfalseWhether to record canvas elements
recordCrossOriginIframesfalseWhether to record cross-origin iframes, which needs rrweb injected into each child frame

The three classes behave differently, and people mix them up. The guide's privacy section spells it out. An element with .rr-block "will not be recorded. Instead, it will replay as a placeholder with the same dimension." An element with .rr-ignore "will not record its input events." And "all text of elements with the class name .rr-mask and their children will be masked." Blocking removes the element. Ignoring keeps the element but drops what the user types into it. Masking keeps the layout and replaces the characters.

Hands typing on a laptop keyboard, standing in for the form input that rrweb records unless you mask it.

Three privacy classes, three effects
blockClassRemoves the element, replays a placeholder
ignoreClassKeeps the element, drops its input events
maskTextClassKeeps the element, replaces its text
Each class in rrweb's Record Options table changes a different part of the recording.

What does rrweb mask by default?

rrweb masks one thing by default: the value of password inputs. The guide says it in one line, "input[type="password"] will be masked by default", and the recorder source confirms it: when maskAllInputs is not true and you pass no maskInputOptions, the recorder falls back to { password: true }.

Flowsery
Flowsery

Start Your 14-Day Free Trial

Real-time dashboard

Goal tracking

Cookie-free tracking

Everything else, including email, phone, address and free-text fields, leaves the browser as typed unless you configure more. maskInputOptions accepts these keys, from MaskInputOptions in the rrweb-snapshot types: color, date, datetime-local, email, month, number, range, search, tel, text, time, url, week, textarea, select and password. Setting maskAllInputs: true switches all of them on at once.

No option exists to unmask a child inside a masked parent. rrweb has no unmask or unblock setting, so vendors that offer one built it into their fork. If you compare libraries on defaults, our breakdown of where PII redaction defaults leave data exposed puts rrweb next to Sentry and Clarity.

A practical rule for a new install: start with maskAllInputs: true, add maskTextClass or maskTextSelector to any container that renders account data, and put blockClass on third-party widgets you have no reason to see.

Rows of server racks in a data center, where rrweb recordings pile up and take storage.

How do you reduce the size of an rrweb recording?

rrweb's storage recipe lists three strategies: block DOM elements that emit many events, use the sampling config to drop events, and compress or deduplicate what you keep.

The sampling option thins events inside a recording rather than choosing which sessions to record. Its keys come from the SamplingStrategy type. mousemove takes false or a throttle threshold, mouseInteraction takes false or a per-interaction map, scroll and media take throttle thresholds, input takes 'all' or 'last', and canvas takes 'all' or a snapshot rate between 1 and 60 per second. The recipe's example sets scroll: 150 with the comment "do not emit twice in 150ms" and input: 'last' to keep only the final value of a typed sequence. That is event-level sampling, which is a different lever from the session replay sampling rate that vendors expose.

For compression, @rrweb/packer provides a pack function you pass as packFn, and the matching unpack goes to the replayer as unpackFn. The recipe notes that compressing the whole session on the backend usually beats per-event compression. slimDOMOptions strips parts of the DOM such as scripts and comments, and checkoutEveryNth or checkoutEveryNms take a fresh full snapshot at intervals, which lets you keep only the last stretch of a session when an error fires. The guide warns that this is approximate: with checkoutEveryNth: 200 you end up sending "the last 200 to 400 events".

Recording cost is also a page speed question. The published numbers on what a recorder adds to bundle size and main-thread time are collected in how much session replay slows a site down.

Frequently asked questions

Is rrweb free to use commercially?

Yes. rrweb is MIT licensed, so you can use and modify it in closed-source commercial software. You must keep the copyright notice and the licence text with the code you ship.

Does rrweb capture what users type?

Yes, unless you mask it. rrweb records input events and masks only input[type="password"] by default. Set maskAllInputs: true or list specific input types in maskInputOptions to mask more.

What is the difference between blockClass and maskTextClass in rrweb?

blockClass (default 'rr-block') removes an element from the recording and replays a same-sized placeholder. maskTextClass (default 'rr-mask') keeps the element and replaces the text inside it and its children.

Should I install rrweb or @rrweb/record?

Install @rrweb/record for recording and @rrweb/replay for playback. The rrweb guide calls the combined rrweb package deprecated, even though npm shows no deprecation warning on it.

Can rrweb record canvas and iframes?

Yes, both are off by default. recordCanvas: false and recordCrossOriginIframes: false are the defaults, and cross-origin iframes also need rrweb injected into each child frame.

Which browsers does rrweb support?

rrweb supports browsers that implement MutationObserver. Its guide states that it does not support Internet Explorer 11 and below.

How does rrweb's sampling option reduce recording size?

The sampling config thins events inside a session instead of dropping whole recordings. scroll and media take a throttle threshold, mousemove takes one too, and input accepts 'last' to keep only the final value of a typed sequence. The storage recipe's example sets scroll: 150 so a scroll only fires once every 150 milliseconds.

Flowsery
Flowsery

Start Your 14-Day Free Trial

Real-time dashboard

Goal tracking

Cookie-free tracking

Can you convert an rrweb recording into a video file?

The rrweb monorepo ships rrvideo, described as "a tool for transforming the session recorded by rrweb into a video." This turns a recording made of a DOM snapshot and mutations into an actual video file. rrweb itself still records no video; rrvideo is a separate conversion step run afterward.

How many downloads does the deprecated rrweb package get compared to @rrweb/record?

In the week of 15 to 21 September 2026, npm counted 1,874,214 downloads of the rrweb package against 498,366 for @rrweb/record. The guide calls rrweb deprecated, but npm shows no deprecation notice on it, so installing it shows no warning. The older package still gets downloaded far more than its replacement.

Do Sentry and PostHog use the original rrweb package directly?

Sentry and PostHog each maintain their own fork rather than depending on rrweb directly. Sentry's replay package depends on @sentry/rrweb and @sentry/rrweb-snapshot, and PostHog's browser SDK depends on @posthog/rrweb and @posthog/rrweb-record. A fix in upstream rrweb only reaches their users once the vendor merges it, and each fork's option names and defaults differ from rrweb's own.

Was This Article Helpful?

Let us know what you think!

See us more often in Google

One click marks Flowsery as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.

Before you go...

Flowsery

Flowsery

Revenue-first analytics for your website

Track every visitor, source, and conversion in real time. Simple, powerful, and cookie-free.

Real-time dashboard

Goal tracking

Cookie-free tracking

Related Glossary Terms

Related Articles