Prompt
How do I handle NAT traversal for WebRTC?
Latest observation
Nov 2, 2026
OpenAI APIWeb search: off
NAT traversal in WebRTC is usually handled with ICE plus a combination of STUN and TURN servers.
The short version
- STUN helps a browser discover its public-facing IP/port.
- ICE tries multiple connection paths and picks the best one.
- TURN relays media when a direct peer-to-peer path fails, such as with restrictive NATs or firewalls.
What you should do
-
Set up a signaling channel
- WebRTC does not define signaling.
- Use WebSocket, HTTP, MQTT, etc. to exchange:
- SDP offers/answers
- ICE candidates
-
Configure STUN servers
- This lets peers discover their public address.
- Example:
const pc = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' } ] }); -
Configure TURN servers
- Required for reliability in real-world networks.
- Use TURN over UDP first, then TURN over TCP/TLS if needed.
- Example:
const pc = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' }, { urls: 'turn:turn.example.com:3478', username: 'user', credential: 'pass' }, { urls: 'turns:turn.example.com:5349', username: 'user', credential: 'pass' } ] }); -
Exchange ICE candidates
- Listen for
icecandidateevents and send candidates to the other peer via signaling. - Add remote candidates as they arrive.
- Listen for
-
Wait for ICE to complete
- WebRTC automatically tests candidate pairs:
- host candidates
- server reflexive candidates from STUN
- relayed candidates from TURN
- If a direct route works, it uses that. If not, it falls back to TURN.
- WebRTC automatically tests candidate pairs:
Important practical advice
- Always provide TURN, not just STUN. Many networks block direct peer-to-peer connectivity.
- Use
iceTransportPolicy: "relay"if you want to force TURN only:const pc = new RTCPeerConnection({ iceServers: [ { urls: 'turn:turn.example.com:3478', username: 'user', credential: 'pass' } ], iceTransportPolicy: 'relay' }); - Prefer TURN over UDP, then TCP, then TLS for best compatibility.
- Make sure your TURN server is properly secured and monitored, since relaying traffic can be expensive.
Common pitfalls
- Forgetting to exchange ICE candidates.
- Using only STUN and expecting it to work everywhere.
- Misconfigured TURN credentials.
- Firewall/network policies blocking UDP.
- Not handling ICE restart when network changes.
Rule of thumb
If you want WebRTC to work reliably for real users on real networks, use:
- a signaling server
- at least one STUN server
- a production TURN server with fallback over TCP/TLS
If you want, I can also show:
- a minimal JavaScript WebRTC setup with signaling and ICE exchange, or
- how to deploy a TURN server with Coturn.