WebRTC API Complete Technical Guide: From Interfaces to Implementation
A comprehensive deep-dive into WebRTC API architecture, core interfaces, protocol stack, and security mechanisms based on official MDN documentation.
Introduction
WebRTC (Web Real-Time Communication) is a powerful technology that enables web applications to exchange audio, video, and arbitrary data directly between browsers without intermediaries. This guide provides a comprehensive technical overview based on the official MDN Web Docs specification.
Core Architecture
WebRTC is built on a layered architecture that handles everything from network traversal to media encoding:
┌─────────────────────────────────────────────┐
│ Application Layer │
│ (Your JavaScript Application) │
├─────────────────────────────────────────────┤
│ WebRTC API Layer │
│ RTCPeerConnection RTCDataChannel etc. │
├─────────────────────────────────────────────┤
│ Session Layer │
│ SDP DTLS SCTP SRTP │
├─────────────────────────────────────────────┤
│ Network Layer │
│ ICE STUN TURN │
├─────────────────────────────────────────────┤
│ Transport Layer │
│ UDP / TCP │
└─────────────────────────────────────────────┘
Core Interfaces
RTCPeerConnection
The most important interface in WebRTC, RTCPeerConnection represents a connection between the local device and a remote peer.
const configuration = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{
urls: 'turn:turn.example.com:3478',
username: 'user',
credential: 'password'
}
]
};const peerConnection = new RTCPeerConnection(configuration);
Key Responsibilities:
RTCDataChannel
Enables bidirectional transfer of arbitrary data between peers. This is the interface ZeroSend uses for file transfer.
// Creating a data channel
const dataChannel = peerConnection.createDataChannel('fileTransfer', {
ordered: true, // Guarantee message order
maxRetransmits: 3 // Maximum retry attempts
});// Receiving a data channel
peerConnection.ondatachannel = (event) => {
const receivedChannel = event.channel;
receivedChannel.onmessage = (e) => {
console.log('Received:', e.data);
};
};
Data Channel Options:
| Option | Type | Description |
| ordered | boolean | Whether messages arrive in order |
| maxPacketLifeTime | number | Max time to attempt delivery (ms) |
| maxRetransmits | number | Max number of retransmission attempts |
| protocol | string | Sub-protocol name |
| negotiated | boolean | Whether channel is negotiated out-of-band |
| id | number | Channel ID (if negotiated) |
RTCSessionDescription
Contains information about the session, particularly the SDP (Session Description Protocol) data.
// Creating an offer
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);// The offer contains SDP like:
// v=0
// o=- 4611731400430051336 2 IN IP4 127.0.0.1
// s=-
// t=0 0
// a=group:BUNDLE 0
// a=msid-semantic: WMS
// m=application 9 UDP/DTLS/SCTP webrtc-datachannel
// ...
RTCIceCandidate
Represents a candidate Interactive Connectivity Establishment (ICE) server for establishing the peer connection.
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
// Send this candidate to the remote peer via signaling
signalingChannel.send({
type: 'ice-candidate',
candidate: event.candidate
});
}
};// Receiving and adding a remote candidate
const candidate = new RTCIceCandidate(receivedCandidate);
await peerConnection.addIceCandidate(candidate);
ICE Candidate Types:
Connection Establishment Flow
The Offer/Answer Model
Peer A (Caller) Peer B (Callee)
1. createOffer()
2. setLocalDescription(offer)
3. Send offer via signaling -->
4. setRemoteDescription(offer)
5. createAnswer()
6. setLocalDescription(answer)
<-- 7. Send answer via signaling
8. setRemoteDescription(answer)
<-- ICE Candidates Exchange -->
========= Connected =========
Complete Connection Example
// Peer A: Creating and sending offer
async function createOffer() {
const pc = new RTCPeerConnection(config); // Create data channel before creating offer
const dc = pc.createDataChannel('chat');
// Gather ICE candidates
pc.onicecandidate = (e) => {
if (e.candidate) {
sendToRemote({ type: 'candidate', candidate: e.candidate });
}
};
// Create and send offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
sendToRemote({ type: 'offer', sdp: offer });
return { pc, dc };
}
// Peer B: Receiving offer and sending answer
async function handleOffer(offer) {
const pc = new RTCPeerConnection(config);
// Handle incoming data channel
pc.ondatachannel = (e) => {
const dc = e.channel;
dc.onmessage = (msg) => console.log(msg.data);
};
// Gather ICE candidates
pc.onicecandidate = (e) => {
if (e.candidate) {
sendToRemote({ type: 'candidate', candidate: e.candidate });
}
};
// Set remote description and create answer
await pc.setRemoteDescription(offer);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
sendToRemote({ type: 'answer', sdp: answer });
return pc;
}
Protocol Stack Deep Dive
ICE (Interactive Connectivity Establishment)
ICE is the framework that enables WebRTC to find the best path between peers.
ICE Gathering States:
ICE Connection States:
STUN (Session Traversal Utilities for NAT)
STUN servers help peers discover their public IP address and port:
Client STUN Server
<-- Binding Response --
(Your public IP:
203.0.113.50:
54321)
TURN (Traversal Using Relays around NAT)
When direct connection fails, TURN relays traffic:
Peer A <==> TURN Server <==> Peer BNote: Traffic is still encrypted!
The TURN server only sees encrypted packets.
DTLS (Datagram Transport Layer Security)
DTLS provides encryption for all WebRTC communications:
- Based on TLS 1.2/1.3 but for UDP
- Mandatory in WebRTC (cannot be disabled)
- Provides encryption, authentication, and integrity
- Keys are derived during the DTLS handshake
SCTP (Stream Control Transmission Protocol)
SCTP runs over DTLS and provides data channel functionality:
- Message-oriented (unlike TCP's byte stream)
- Supports multiple streams over one connection
- Configurable reliability per message
- Handles congestion control
Security Mechanisms
Built-in Encryption
All WebRTC communications are encrypted by default:
Media Streams: SRTP (Secure RTP)
Data Channels: DTLS + SCTP
Key Exchange: DTLS handshake
Certificate and Identity
// Generate a certificate
const certificate = await RTCPeerConnection.generateCertificate({
name: 'ECDSA',
namedCurve: 'P-256'
});// Use it in configuration
const pc = new RTCPeerConnection({
certificates: [certificate],
iceServers: [...]
});
// Get fingerprint for verification
const fingerprint = certificate.getFingerprints()[0];
console.log(fingerprint.algorithm, fingerprint.value);
Security Considerations
- User Consent: Browsers require explicit permission for camera/microphone
- Secure Origins: WebRTC only works on HTTPS (or localhost)
- No IP Leaking: Modern browsers protect against WebRTC IP leaks
- Perfect Forward Secrecy: Each session uses unique keys
Media Stream Handling
MediaStream Structure
MediaStream
├── MediaStreamTrack (audio)
│ ├── id: "unique-audio-id"
│ ├── kind: "audio"
│ ├── label: "Built-in Microphone"
│ └── enabled: true
│
└── MediaStreamTrack (video)
├── id: "unique-video-id"
├── kind: "video"
├── label: "FaceTime HD Camera"
└── enabled: true
RTP Sender and Receiver
// Adding a track
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true
});stream.getTracks().forEach(track => {
const sender = peerConnection.addTrack(track, stream);
console.log('Added track:', track.kind);
});
// Receiving tracks
peerConnection.ontrack = (event) => {
const [remoteStream] = event.streams;
videoElement.srcObject = remoteStream;
};
Advanced Features
DTMF Support
For telephony applications, WebRTC supports DTMF tones:
const sender = peerConnection.getSenders()
.find(s => s.track.kind === 'audio');const dtmfSender = sender.dtmf;
dtmfSender.insertDTMF('1234', 100, 50);
// Sends tones: 1, 2, 3, 4
// Duration: 100ms each
// Gap: 50ms between tones
Statistics and Monitoring
const stats = await peerConnection.getStats();stats.forEach(report => {
if (report.type === 'candidate-pair' && report.state === 'succeeded') {
console.log('Round-trip time:', report.currentRoundTripTime);
console.log('Bytes sent:', report.bytesSent);
console.log('Bytes received:', report.bytesReceived);
}
});
Browser Compatibility
WebRTC is supported in all modern browsers, but implementations vary. Use adapter.js for compatibility:
import adapter from 'webrtc-adapter';console.log('Browser:', adapter.browserDetails.browser);
console.log('Version:', adapter.browserDetails.version);
Real-World Applications
WebRTC powers numerous applications:
- Video Conferencing: Google Meet, Zoom (web version)
- File Sharing: ZeroSend, ShareDrop
- Gaming: Real-time multiplayer games
- IoT: Device-to-device communication
- Live Streaming: Low-latency broadcasts
- Customer Support: Browser-based calling
Conclusion
WebRTC is a powerful and complex technology that enables real-time communication directly in the browser. Understanding its layered architecture—from the high-level JavaScript APIs down to the network protocols—is essential for building robust P2P applications.
The combination of mandatory encryption, NAT traversal mechanisms, and flexible data channels makes WebRTC the ideal foundation for privacy-focused applications like ZeroSend.
Further Reading: