Skip to content

Network Recorder and Replayer

This feature aims to provide developers with more information about the bug scene. There are some options for recording and replaying network output.

Enable Recording Network

You can enable using default option like this:

js
import { record } from '@rrweb/record';
import { getRecordNetworkPlugin } from '@rrweb/rrweb-plugin-network-record';

record({
  emit: function emit(event) {
    events.push(event);
  },
  // to use default record option
  plugins: [getRecordNetworkPlugin()],
});

You can also customize the behavior of logger like this:

js
import { record } from '@rrweb/record';
import { getRecordNetworkPlugin } from '@rrweb/rrweb-plugin-network-record';

const recordingId = crypto.randomUUID();

record({
  emit: function emit(event) {
    fetch(`https://api.rrweb.com/recordings/${recordingId}/events`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        events: [event],
      }),
    });
  },
  // customized record options
  plugins: [
    getRecordNetworkPlugin({
      initiatorTypes: ['fetch', 'xmlhttprequest'],
      // mask/block recording event for request
      transformRequestFn: (request) => {
        // request.name is url
        if (request.name.includes('api.rrweb.com')) return; // skip request
        delete request.requestHeaders?.Authorization; // remove sensitive data
        request.responseBody = maskTextFn(request.responseBody);
        return request;
      },
      recordHeaders: true,
      recordBody: true,
      recordInitialRequests: false,
    }),
  ],
});

alert: If you are uploading events to a server, you should always use transformRequestFn to mask/block recording events for these requests or else you will cause a nasty loop.

All options are described below:

keydefaultdescription
initiatorTypes['fetch','xmlhttprequest','img',...]Default value contains names of all initiator types. You can override it by setting the types you need.
transformRequestFn(request) => requestTransform recording event for request to block (skip) or mask/transform request (e.g. to hide sensitive data)
recordHeadersfalseRecord the request & response headers for fetch and xmlhttprequest requests
recordBodyfalseRecord the request & response bodies for fetch and xmlhttprequest requests
recordInitialRequestsfalseRecord an event for all requests prior to record() being called

Replay Network Requests

It is up to you to decide how to best replay your network events using the onNetworkData callback.

js
import rrweb from 'rrweb';
import { getReplayNetworkPlugin } from '@rrweb/rrweb-plugin-network-replay';

const replayer = new rrweb.Replayer(events, {
  plugins: [
    getReplayNetworkPlugin({
      onNetworkData: ({ requests }) => {
        for (const request of requests) {
          const name = request.name; // url
          const method = request.method;
          const status = request.status;
          console.log(`${method} ${name} ${status}`);
        }
      },
    }),
  ],
});
replayer.play();

Description of replay option is as follows:

keydefaultdescription
onNetworkDataundefinedYou could use this interface to replay the network requests in a simulated browser console

Technical Implementation

This implementation records fetch and XMLHttpRequest by patching their object & methods. We record document navigation using PerformanceNavigationTiming and we use PerformanceResourceTiming for recording everything else (script, img, link etc.) via PerformanceObserver API.

For more information please see [network-plugin] Feat: Capture network events #1105 PR.