DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

WebRTC in Firefox: getUserMedia, RTCPeerConnection, Data Channels, and Privacy Considerations

WebRTC (Web Real-Time Communication) is a collection of APIs and protocols that enables peer-to-peer audio, video, and data communication directly in the browser. Firefox has had full WebRTC support since Firefox 22 (2013) and has shaped much of the WebRTC spec. This guide covers how WebRTC works in Firefox, common integration patterns, and the privacy implications.

What WebRTC Is

WebRTC is not a single API but a group:

  • getUserMedia(): access camera and microphone
  • RTCPeerConnection: peer-to-peer connection for audio/video/data
  • RTCDataChannel: peer-to-peer data transfer (binary or text)
  • getDisplayMedia(): screen/window/tab capture

These combine to enable video conferencing, file sharing, real-time collaboration, and P2P communication without plugins or server-relayed media.

Firefox WebRTC Support

Firefox has been at the forefront of WebRTC:

  • Unified Plan (RFC 8829): supported; Firefox migrated from Plan B in 2019
  • AV1 video codec: supported in Firefox
  • VP8/VP9: full support
  • H.264: hardware-assisted on supported systems
  • Opus audio codec: the default, superior to G.711 for voice
  • DTLS-SRTP encryption: all WebRTC media is encrypted by default
  • Data channels (SCTP): reliable and unreliable modes

Basic getUserMedia Example

// Request camera and microphone
async function startCamera() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { width: 1280, height: 720 },
      audio: {
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true
      }
    });

    const video = document.getElementById('localVideo');
    video.srcObject = stream;
    video.play();

    return stream;
  } catch (err) {
    if (err.name === 'NotAllowedError') {
      console.error('User denied camera/microphone permission');
    } else if (err.name === 'NotFoundError') {
      console.error('No camera/microphone found');
    }
    throw err;
  }
}
Enter fullscreen mode Exit fullscreen mode

Firefox prompts for permissions with a persistent doorhanger that saves the choice per-domain.

RTCPeerConnection: Setting Up a Call

const config = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' }, // Google STUN (free public server)
    { 
      urls: 'turn:your-turn-server.com:3478',
      username: 'user',
      credential: 'password'
    }
  ]
};

const pc = new RTCPeerConnection(config);

// Add local stream tracks
localStream.getTracks().forEach(track => pc.addTrack(track, localStream));

// Create offer (caller side)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

// Send offer to remote peer via your signaling server
signalingServer.send(JSON.stringify({ type: 'offer', sdp: offer.sdp }));

// Handle ICE candidates
pc.onicecandidate = ({ candidate }) => {
  if (candidate) {
    signalingServer.send(JSON.stringify({ type: 'candidate', candidate }));
  }
};

// Receive remote stream
pc.ontrack = ({ streams }) => {
  const remoteVideo = document.getElementById('remoteVideo');
  remoteVideo.srcObject = streams[0];
};
Enter fullscreen mode Exit fullscreen mode

Note: WebRTC needs a signaling server to exchange SDP and ICE candidates — WebRTC doesn't define this, you implement it (WebSocket, HTTP polling, etc.).

STUN vs TURN Servers

  • STUN (Session Traversal Utilities for NAT): discovers your public IP/port for direct P2P connection. Free public servers exist. ~80% of connections succeed with STUN alone.
  • TURN (Traversal Using Relays around NAT): relay server for the ~20% of cases where direct P2P fails (symmetric NAT, corporate firewalls). TURN costs bandwidth — you pay for it.

For production applications, you need both. Coturn is the standard open-source TURN server.

Screen Sharing with getDisplayMedia

async function shareScreen() {
  const stream = await navigator.mediaDevices.getDisplayMedia({
    video: {
      displaySurface: 'browser' // 'browser', 'monitor', or 'window'
    },
    audio: false // Most browsers don't capture system audio on Linux
  });

  return stream;
}
Enter fullscreen mode Exit fullscreen mode

Firefox shows a native picker dialog. On Linux, Firefox uses PipeWire for screen capture (Firefox 116+).

Data Channels for P2P File Transfer

const dataChannel = pc.createDataChannel('fileTransfer', {
  ordered: true,  // TCP-like reliability
  // maxRetransmits: 0  // Unreliable (UDP-like) for games/real-time
});

dataChannel.binaryType = 'arraybuffer';

dataChannel.onopen = () => console.log('Data channel open');

// Send a file
async function sendFile(file) {
  const buffer = await file.arrayBuffer();
  const chunkSize = 16384; // 16KB chunks
  for (let i = 0; i < buffer.byteLength; i += chunkSize) {
    dataChannel.send(buffer.slice(i, i + chunkSize));
  }
};
Enter fullscreen mode Exit fullscreen mode

Data channels go P2P — no server bandwidth cost for file transfer once the connection is established.

Firefox-Specific WebRTC Behavior

ICE candidate filtering: Firefox exposes IP addresses to websites via ICE candidates unless you configure the media.peerconnection.ice.default_address_only preference. By default, Firefox may reveal your local network IP.

Codecs: Firefox does not support H.264 hardware encode on all platforms. If interoperability with H.264-only endpoints is required, test thoroughly.

Simulcast: Firefox supports simulcast (sending multiple stream qualities) via RTCRtpSender.setParameters().

Stats API: pc.getStats() is very detailed in Firefox — useful for debugging connection quality, packet loss, and codec negotiation.

Privacy: WebRTC IP Leaks

WebRTC can expose your local and public IP addresses even through a VPN (because ICE gathers all network interface candidates). This is a known privacy concern.

In Firefox about:config:

Setting Description
media.peerconnection.enabled false = disable WebRTC entirely
media.peerconnection.ice.default_address_only true = only use default interface IP
media.peerconnection.ice.no_host true = don't expose local network IPs
media.peerconnection.ice.proxy_only true = use proxy for ICE (most private)

For most users: enable media.peerconnection.ice.default_address_only and media.peerconnection.ice.no_host. This prevents local IP disclosure while keeping WebRTC functional.

Debugging WebRTC in Firefox

about:webrtc — built-in WebRTC diagnostic page. Shows:

  • All active peer connections and their state
  • ICE candidate gathering (what IPs were found)
  • Codec negotiation details
  • Packet statistics

Essential for debugging connection failures, codec mismatches, and NAT traversal issues.

DevTools → Console: WebRTC errors appear here with useful messages.

Top comments (0)