WebRTC Cheatsheet

WebRTC Basics

Use this WebRTC reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

What WebRTC Is

WebRTC (Web Real-Time Communication) is a browser API for peer-to-peer audio, video, and data without plugins. Three core APIs cover everything:

APIPurpose
getUserMedia() / getDisplayMedia()Capture mic, camera, or screen
RTCPeerConnectionEstablish and manage a P2P connection
RTCDataChannelSend arbitrary binary/text data peer-to-peer

WebRTC is not a standalone protocol — it requires a signaling channel (WebSocket, HTTP, etc.) you build yourself to exchange session descriptions and ICE candidates before the P2P link forms.

Core Concepts

The Connection Lifecycle (always in this order)

  1. Capture local media (getUserMedia)
  2. Create RTCPeerConnection with ICE server config
  3. Add tracks / create data channels
  4. Create offer (caller) or answer (callee) — SDP
  5. Exchange SDP and ICE candidates via your signaling channel
  6. Connection negotiates, iceConnectionState"connected"

SDP — Session Description Protocol

SDP is a text blob that describes codecs, bandwidth, encryption fingerprints, and media directions. You never hand-parse it; pass it opaquely between peers.

// SDP looks like:
// v=0
// o=- 4611731400430051336 2 IN IP4 127.0.0.1
// s=-
// t=0 0
// a=group:BUNDLE 0 1
// m=audio 9 UDP/TLS/RTP/SAVPF 111 …

ICE — Interactive Connectivity Establishment

ICE finds the best network path. It gathers candidates (host addresses, server-reflexive via STUN, relayed via TURN) and tries them in priority order.

DTLS + SRTP

All media is encrypted with SRTP keyed via DTLS handshake — mandatory in WebRTC. You cannot disable encryption.

Browser Support

FeatureChromeFirefoxSafariEdge
RTCPeerConnection23+22+11+79+
getUserMedia53+36+11+79+
getDisplayMedia72+66+13+79+
RTCDataChannel31+22+11+79+
Unified Plan SDP72+63+12.1+79+

Safari requires playsInline on <video> and a user gesture before audio plays. Always test Safari separately.

Minimal End-to-End Skeleton

// ---- CALLER ----
const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });

// Add local tracks first, then create offer
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach(t => pc.addTrack(t, stream));

pc.onicecandidate = ({ candidate }) => {
  if (candidate) signaling.send({ type: 'ice', candidate });
};

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
signaling.send({ type: 'offer', sdp: pc.localDescription });

// ---- CALLEE ----
const pc2 = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });

pc2.ontrack = ({ streams }) => {
  document.getElementById('remoteVideo').srcObject = streams[0];
};

signaling.on('offer', async ({ sdp }) => {
  await pc2.setRemoteDescription(sdp);
  const answer = await pc2.createAnswer();
  await pc2.setLocalDescription(answer);
  signaling.send({ type: 'answer', sdp: pc2.localDescription });
});

signaling.on('answer', async ({ sdp }) => {
  await pc.setRemoteDescription(sdp);
});

signaling.on('ice', async ({ candidate }) => {
  await pc.addIceCandidate(candidate);
});

Key Gotchas

  • Add tracks before creating an offer — tracks added after require renegotiation via onnegotiationneeded.
  • Never set remote description before local — always setLocalDescription first on the side that created the SDP.
  • ICE candidates can arrive before setRemoteDescription — buffer them and add after remote description is set.
  • RTCSessionDescription is now optional — pass plain { type, sdp } objects directly to setLocalDescription / setRemoteDescription.
  • Trickle ICE is the default; wait for icegatheringstate === 'complete' only if your signaling can't handle incremental candidates.
  • HTTPS requiredgetUserMedia and WebRTC in general are restricted to secure contexts (https:// or localhost).

RTCPeerConnection Constructor

const pc = new RTCPeerConnection(configuration);
configuration propertyTypeDefaultDescription
iceServersRTCIceServer[][]STUN/TURN servers
iceTransportPolicy"all" | "relay""all""relay" forces TURN
bundlePolicy"balanced" | "max-compat" | "max-bundle""balanced"How to bundle media
rtcpMuxPolicy"require""require"Must mux RTCP
certificatesRTCCertificate[]auto-generatedPre-generated DTLS certs
iceCandidatePoolSizenumber0Pre-gather N candidates

Useful Utilities

// Check if WebRTC is available
const supported = typeof RTCPeerConnection !== 'undefined';

// Get browser capabilities
const caps = RTCRtpReceiver.getCapabilities('video');
console.log(caps.codecs); // [{mimeType:'video/VP8', …}, …]

// Generate a certificate upfront (avoids DTLS delay)
const cert = await RTCPeerConnection.generateCertificate({
  name: 'ECDSA',
  namedCurve: 'P-256',
});
const pc = new RTCPeerConnection({ certificates: [cert] });