Why Session Replay Struggles With Iframes, Canvas, and Shadow DOM
Session replay rebuilds a page from its DOM, so anything that is not ordinary DOM is hard to capture. Learn why cross-origin iframes, canvas, shadow DOM, animations, and external assets cause gaps in recordings, and what you can do about each.
Short answer: replay works by serialising the DOM and replaying changes to it. Content that lives outside the reachable DOM cannot be serialised: a cross-origin iframe belongs to another site, a canvas is pixels with no structure, and a closed shadow root is deliberately hidden. Recordings also depend on styles, fonts, and images that may load differently at playback. Knowing these limits tells you when a blank area in a recording is a real bug and when it is a capture gap.
Table of Contents
- The Rule
- Cross-Origin Iframes
- Canvas and WebGL
- Shadow DOM and Web Components
- Animations
- External Assets
- Theme and Media Queries
- How to Tell a Gap From a Bug
- Key Takeaways
The Rule
A recorder can capture what its script can read. It runs in your page, with your page's permissions. Anything the browser will not let that script read cannot be recorded. Anything that is not a tree of elements cannot be serialised as one (how replay works).
Cross-Origin Iframes
An iframe showing content from another domain is a separate document with its own security boundary. Your page's scripts cannot read inside it. That is a core browser protection, and no recorder can bypass it.
Typical examples:
- Payment forms hosted by a payment provider
- Embedded video players
- Third-party chat widgets
- Maps
- Login and verification providers
- Advertisements
In a recording these appear as an empty box of the right size.
What you can do
- Accept it for payment forms. Not capturing card entry is the desired outcome.
- Record events around the frame instead: track "payment started" and "payment completed" as custom events so the funnel still works.
- Watch what the visitor does next. Repeated clicks near a frame, or leaving, tell you something went wrong inside it.
- If you control both sites, the recorder can be installed inside the framed page as well.
Same-origin iframes, served from your own domain, can generally be recorded.
Canvas and WebGL
A canvas is a drawing surface. Whatever is on it exists as pixels, with no elements, no text nodes, and nothing to serialise. Charts drawn on canvas, maps, games, design tools, 3D viewers, and signature pads all work this way.
Capturing a canvas means reading its pixels repeatedly and sending images, which is closer to video and costs far more in processing and data. WebGL adds a further obstacle: by default its drawing buffer is cleared after each frame, so reading it back often returns nothing.
What you can do
- Expect canvas areas to be blank or static in most recordings.
- Track meaningful actions as events: "chart filter changed", "level completed".
- Prefer SVG or DOM-based charts where practical. They record fully and are more accessible.
For products that are mostly canvas, such as games, events and funnels carry the analysis and replay covers the surrounding pages (gaming platforms).
Shadow DOM and Web Components
Shadow DOM lets a component keep its internal structure separate from the page. There are two modes.
- Open: scripts can reach the internal tree. A recorder can traverse and capture it, though it must do so deliberately and attach a separate observer to each shadow root.
- Closed: the internal tree is hidden from outside scripts by design. It cannot be read, so it cannot be recorded.
Styles add a wrinkle. Components increasingly use constructable stylesheets, which are attached through script and are not style elements in the tree. A recorder has to capture those separately or the component replays unstyled.
What you can do
- Use open mode for your own components unless you have a specific reason not to.
- Test a recording of any page built with a component library.
- If a third-party component uses a closed root, treat it like a cross-origin frame and track events around it.
Animations
Playback controls time. To allow pausing and seeking, a player takes charge of animations instead of letting them run on the real clock.
That causes a specific failure with entrance animations. Many sites render elements at zero opacity and animate them into view. The recorder captures the starting state. If the player then holds the animation at its start, those elements stay invisible, and the recording shows a background with nothing on it.
We hit exactly this. The capture was complete, and the page looked empty. Our fix was to inject style rules at playback that force animated elements to their finished state.
If your recordings show blank sections on pages with scroll-reveal effects, this is the likely cause, not missing data.
External Assets
A recording stores the page's structure. Depending on configuration, images, fonts, and stylesheets are either copied into the recording or referenced at their original addresses.
| Approach | Benefit | Cost |
|---|---|---|
| Inline into the recording | Self-contained, survives later changes | Larger recordings; some attributes can be lost |
| Reference the original address | Small recordings, exact rendering | Breaks if the asset is later removed or protected |
Common symptoms:
- Broken images in old recordings, because the file was replaced or deleted.
- Wrong fonts, when a font cannot be loaded from the player's origin.
- Missing styles, when a stylesheet on another domain does not permit cross-origin reading, so its rules could not be captured.
- Authenticated assets, such as a profile photo that requires a login cookie.
We moved from inlining images to referencing them after finding that inlining dropped width and height attributes on optimised images, so they replayed at the wrong size. The trade is that an image must still be reachable when the recording is watched.
What you can do: serve stylesheets and fonts with headers that permit cross-origin access, and avoid deleting assets that recent recordings rely on.
Theme and Media Queries
A recording is replayed on the viewer's machine, in the viewer's browser settings. If the visitor saw your site in dark mode and the person watching uses light mode, media queries in the recorded styles can resolve the other way and the replay shows the wrong theme.
The same applies to anything keyed to the environment: reduced-motion preferences, pointer type, and print styles. The page's own viewport size is recorded and reproduced, which is why layout is usually right even when theme is not.
How to Tell a Gap From a Bug
When part of a recording looks wrong, ask:
- Is it an iframe, canvas, or third-party component? Likely a capture gap.
- Does it have an entrance animation? Likely the animation issue.
- Is it an image or font? Likely an asset problem.
- Does the visitor's behavior suggest they saw it? If they clicked a button you cannot see, it was there for them.
- Does the console timeline show an error at that moment? Then it may be a real fault.
- Does it reproduce on the live page with the same browser and viewport?
Point four is the most useful. The visitor's actions are the evidence of what they saw.
Key Takeaways
- Replay captures the readable DOM; anything outside it is a gap.
- Cross-origin frames, canvas, and closed shadow roots cannot be serialised.
- Animations and external assets cause most visual differences.
- Use the visitor's actions to judge what they actually saw.
Conclusion
A recording is a reconstruction, not a photograph. Understanding where reconstruction is impossible stops you chasing bugs that are not there, and helps you instrument the parts that cannot be seen.
Frequently Asked Questions
Related articles
Stay in the loop
Get the latest insights on product analytics and user behavior delivered to your inbox.



