Official Sentry SDK for browsers providing comprehensive error monitoring, performance tracking, user feedback collection, and session management capabilities for client-side JavaScript applications.
—
Complete user session recording and playback capabilities for debugging and understanding user behavior through visual reproduction of user sessions.
Core session replay functionality.
/**
* Session replay recording integration
* @param options - Replay configuration options
* @returns Replay integration
*/
function replayIntegration(options?: ReplayOptions): Integration;
/**
* Canvas recording for session replay
* @param options - Canvas replay options
* @returns Canvas replay integration
*/
function replayCanvasIntegration(options?: ReplayCanvasOptions): Integration;
/**
* Get the current replay client instance
* @returns Replay client or undefined
*/
function getReplay(): ReplayClient | undefined;Usage Example:
import { replayIntegration, replayCanvasIntegration } from "@sentry/browser";
Sentry.init({
dsn: "YOUR_DSN",
integrations: [
replayIntegration({
sessionSampleRate: 0.1, // 10% of sessions
errorSampleRate: 1.0, // 100% of error sessions
// Privacy settings
maskAllText: false,
maskAllInputs: true,
blockAllMedia: true,
// Performance settings
maxReplayDuration: 60 * 60, // 1 hour max
sessionSegmentDuration: 5 * 60, // 5 minute segments
}),
replayCanvasIntegration({
enableManualSnapshot: true,
fps: 4, // 4 frames per second
quality: "medium",
}),
],
});interface ReplayOptions {
/** Sample rate for normal sessions (0.0 to 1.0) */
sessionSampleRate?: number;
/** Sample rate for error sessions (0.0 to 1.0) */
errorSampleRate?: number;
/** Mask all text content */
maskAllText?: boolean;
/** Mask all input values */
maskAllInputs?: boolean;
/** Block all media elements (images, videos, audio) */
blockAllMedia?: boolean;
/** CSS selectors for elements to mask */
maskTextSelectors?: string[];
/** CSS selectors for elements to block completely */
blockSelectors?: string[];
/** CSS selectors for elements to ignore during recording */
ignoreSelectors?: string[];
/** Maximum replay duration in seconds */
maxReplayDuration?: number;
/** Duration of each session segment in seconds */
sessionSegmentDuration?: number;
/** Minimum duration before sending a replay */
minReplayDuration?: number;
/** Maximum mutations to capture per second */
mutationLimit?: number;
/** Maximum mutations for breadcrumbs */
mutationBreadcrumbLimit?: number;
/** Timeout for slow clicks in milliseconds */
slowClickTimeout?: number;
/** CSS selectors to ignore for slow click detection */
slowClickIgnoreSelectors?: string[];
/** Network request recording options */
networkDetailAllowUrls?: (string | RegExp)[];
networkDetailDenyUrls?: (string | RegExp)[];
networkCaptureBodies?: boolean;
networkRequestHeaders?: string[];
networkResponseHeaders?: string[];
/** Privacy configuration */
privacy?: {
maskAllText?: boolean;
maskAllInputs?: boolean;
blockAllMedia?: boolean;
maskTextSelectors?: string[];
blockSelectors?: string[];
};
/** Callback before sending replay */
beforeSend?: (event: ReplayEvent, hint: EventHint) => ReplayEvent | null;
/** Callback before adding breadcrumb to replay */
beforeAddRecordingEvent?: (event: RecordingEvent) => RecordingEvent | null;
}interface ReplayCanvasOptions {
/** Enable manual canvas snapshots */
enableManualSnapshot?: boolean;
/** Recording frame rate (fps) */
fps?: number;
/** Recording quality */
quality?: "low" | "medium" | "high";
/** Maximum canvas width to record */
maxCanvasWidth?: number;
/** Maximum canvas height to record */
maxCanvasHeight?: number;
/** Canvas elements to record (CSS selectors) */
recordCanvas?: string[];
/** Canvas elements to ignore (CSS selectors) */
ignoreCanvas?: string[];
}interface ReplayClient {
/** Start recording a replay */
start(): void;
/** Stop recording */
stop(): void;
/** Check if currently recording */
isEnabled(): boolean;
/** Get current session ID */
getSessionId(): string | undefined;
/** Flush current replay data */
flush(): Promise<void>;
/** Add breadcrumb to replay */
addBreadcrumb(breadcrumb: Breadcrumb): void;
}
type ReplayEventType = "custom" | "fullsnapshot" | "incremental" | "meta";
interface ReplayEventWithTime {
type: ReplayEventType;
data: any;
timestamp: number;
}
interface ReplayBreadcrumbFrame {
type: "breadcrumb";
category: string;
message?: string;
level?: SeverityLevel;
timestamp: number;
data?: any;
}
interface ReplaySpanFrame {
type: "span";
op: string;
description?: string;
startTimestamp: number;
endTimestamp?: number;
data?: any;
}
interface ReplayFrameEvent {
type: ReplayEventType;
timestamp: number;
data: any;
}interface ReplayEvent {
type: "replay_event";
replay_id: string;
segment_id: number;
timestamp: number;
replay_start_timestamp: number;
urls: string[];
error_ids: string[];
trace_ids: string[];
dist?: string;
platform: string;
environment?: string;
release?: string;
user?: User;
tags?: { [key: string]: string };
extra?: { [key: string]: any };
}Replay automatically masks sensitive data:
replayIntegration({
// Text masking
maskAllText: false, // Don't mask all text
maskTextSelectors: [
'.sensitive-data',
'[data-private]',
'input[type="password"]',
'.ssn',
'.credit-card',
],
// Input masking
maskAllInputs: true, // Mask all input values by default
// Element blocking
blockSelectors: [
'.secret-content',
'[data-secret]',
'iframe[src*="payment"]',
],
// Media blocking
blockAllMedia: true, // Block images, videos, audio
});Control network request recording:
replayIntegration({
// Only record specific API calls
networkDetailAllowUrls: [
/^https:\/\/api\.mysite\.com\/public/,
"https://analytics.example.com",
],
// Exclude sensitive endpoints
networkDetailDenyUrls: [
/\/api\/auth/,
/\/api\/payment/,
/\/api\/admin/,
],
// Don't capture request/response bodies
networkCaptureBodies: false,
// Only specific headers
networkRequestHeaders: ["content-type", "accept"],
networkResponseHeaders: ["content-type", "status"],
});Use different sampling rates for different scenarios:
replayIntegration({
// Low sampling for normal sessions to reduce bandwidth
sessionSampleRate: 0.01, // 1% of sessions
// High sampling for error sessions for debugging
errorSampleRate: 1.0, // 100% of error sessions
// Limit replay duration to control storage
maxReplayDuration: 30 * 60, // 30 minutes max
// Smaller segments for better streaming
sessionSegmentDuration: 2 * 60, // 2 minute segments
// Performance limits
mutationLimit: 10000, // Limit DOM changes per second
slowClickTimeout: 7000, // 7 second slow click threshold
});Start/stop recording based on conditions:
import { getReplay } from "@sentry/browser";
// Start recording on user action
function startRecordingSession() {
const replay = getReplay();
if (replay) {
replay.start();
}
}
// Stop recording when leaving sensitive area
function stopRecordingForPrivacy() {
const replay = getReplay();
if (replay) {
replay.stop();
}
}
// Conditional recording based on user consent
if (userHasConsentedToRecording) {
startRecordingSession();
}Record HTML5 canvas elements:
replayCanvasIntegration({
// Record specific canvas elements
recordCanvas: ["#game-canvas", ".chart-canvas"],
// Performance settings
fps: 2, // Low frame rate for performance
quality: "medium",
// Size limits
maxCanvasWidth: 1920,
maxCanvasHeight: 1080,
// Manual snapshot mode for better performance
enableManualSnapshot: true,
});replayIntegration({
// Conservative privacy defaults
maskAllInputs: true,
blockAllMedia: true,
maskTextSelectors: [".pii", "[data-sensitive]"],
blockSelectors: [".admin-only", "[data-secret]"],
// No network details by default
networkDetailAllowUrls: [],
networkCaptureBodies: false,
// Before send filtering
beforeSend: (event) => {
// Additional privacy checks
if (containsSensitiveData(event)) {
return null;
}
return event;
},
});Install with Tessl CLI
npx tessl i tessl/npm-sentry--browser