What ICE, STUN, and TURN Do in Protoface Realtime Avatar Streaming

ICE, STUN, and TURN explained for Protoface WebRTC avatar streaming: NAT traversal, relays, and reliable realtime media paths.
Introduction
If you build realtime avatars, you eventually run into the same question every WebRTC system has to answer: how do two endpoints actually find each other and move media when one or both are behind NATs, firewalls, or restrictive corporate networks?
That is the job of ICE, STUN, and TURN. They are not avatar-specific concepts; they are the connectivity plumbing that lets a browser, a mobile client, or a server-side media worker establish a usable path for audio and video. In a product like Protoface, this matters because the avatar is not just a video file. It is a low-latency, synchronized stream that has to keep up with a voice agent, lip sync timing, interruptions, and network churn.
By the end of this post, you should be able to explain what each of these pieces does, why ICE is a process rather than a server, when STUN is enough, when TURN becomes necessary, and what that means for integrating realtime avatars into an application without getting surprised by connectivity failures.
The short version: ICE finds a path, STUN discovers your public address, TURN relays when direct paths fail
Let’s start with the clean mental model.
ICE is the connection-finding framework. It gathers candidate network paths, tests them, and picks the best working one.
STUN is a lightweight server used during ICE candidate gathering to discover how a client appears from the public internet.
TURN is a relay server used when a direct peer-to-peer path is not possible or not reliable.
In practice, ICE runs over time. It collects candidates such as host addresses, server-reflexive addresses learned via STUN, and relayed addresses from TURN. Then the endpoints exchange those candidates in signaling, test them with connectivity checks, and settle on the best path. If the best path is direct, great. If not, TURN keeps the session alive by forwarding media.
For realtime avatars, that distinction matters because media quality is only half the problem. You also care about start time, stability, and how often the session falls back to a relay. A relay adds latency and cost, but it can save the user experience when networks are hostile.
ICE is the control plane for connectivity, not a transport protocol
ICE stands for Interactive Connectivity Establishment. The easiest mistake is to think of ICE as “the thing that makes WebRTC work.” It is more precise to say that ICE is the process WebRTC uses to establish connectivity between two endpoints.
ICE does a few concrete things:
Collects candidates from each side. These may be local interface addresses, public-facing addresses discovered via STUN, or relayed addresses allocated through TURN.
Exchanges candidates through your signaling channel.
Pairs and tests candidates using connectivity checks.
Chooses the best successful pair and keeps monitoring for failures.
That last point is important. ICE is not a one-time lookup. Network conditions can change. A mobile client may switch Wi-Fi networks, a NAT mapping can expire, or a browser can sleep and wake. ICE is designed to recover when it can.
In a realtime avatar product, this means your app should expect connection state transitions. “Connected” is not a permanently stable state; it is the result of an ongoing negotiation. If you are instrumenting sessions, you want to watch whether the connection is direct or relayed, how long setup takes, and whether reconnects are happening more than they should.
STUN: discover the public-facing address through NAT
STUN, Session Traversal Utilities for NAT, is the simplest piece of the puzzle. A STUN server tells a client what public IP and port the server sees for that client’s request.
Why does that matter? Because most devices are not directly addressable from the internet. They sit behind NAT. A browser might think it is reachable at 192.168.x.x or 10.x.x.x, but that address is only meaningful inside the local network. To talk to another endpoint outside the network, the client needs to know the mapped public address created by the NAT.
STUN helps the client discover a server-reflexive candidate — essentially, “this is what the outside world sees for me right now.” That candidate can often be used for a direct peer-to-peer path if the remote side can reach it and if the NAT behavior is cooperative enough.
What STUN does not do:
It does not relay media.
It does not guarantee reachability.
It does not solve symmetric NAT, restrictive firewalls, or networks that block UDP entirely.
That is why STUN alone is often enough for consumer networks, but not enough for every enterprise or mobile environment.
TURN: the fallback that trades latency for reliability
TURN, Traversal Using Relays around NAT, exists for the cases where direct connectivity fails. Instead of trying to make endpoint A talk directly to endpoint B, each endpoint sends media to the TURN server, which relays packets between them.
This is slower than a direct path, but it is vastly more robust. If a corporate firewall blocks unknown UDP traffic, if NAT mappings are too restrictive, or if both sides cannot establish a viable direct pair, TURN provides a path that is usually allowed because it looks like ordinary outbound connectivity to the relay.
For realtime avatars, TURN is often the difference between “works on my network” and “works in production.” It is also why you should think about latency budgets realistically. A relayed path can add enough delay to make lip sync and conversational turn-taking feel slightly less crisp. Good systems tolerate that, but they should measure it.
Operationally, TURN also has cost implications. Relay bandwidth is your bandwidth. If your product sees a significant percentage of sessions using TURN, you should expect higher infrastructure cost and somewhat worse media efficiency.
How this shows up in a realtime avatar stack
In an avatar streaming system, the media path is only one part of the pipeline. You typically have:
a voice agent or model producing audio or structured speech events,
an avatar renderer generating synchronized video frames or a live face stream, and
a transport layer carrying that media to the browser or client.
ICE, STUN, and TURN live in the transport layer. They do not know anything about lip sync or avatar identity. They only care about establishing a viable network path for the audio/video stream.
That separation is useful. If the avatar feels delayed, the root cause might be model latency, rendering latency, jitter buffering, or network relaying. Don’t assume it is “the avatar service” until you inspect the connection path and ICE state.
A practical debugging checklist:
Confirm whether the session is using a direct or relayed candidate pair.
Measure setup time from offer/answer to connected media.
Check whether failures correlate with a specific network type: corporate Wi-Fi, mobile tethering, VPN, or restricted browser environments.
Watch for ICE restarts during long-lived sessions.
If you are exposing a live avatar in a browser, the user’s network may be the main source of variance. The same app can behave beautifully on a home network and fail on a locked-down office network unless TURN is available and properly configured.
A minimal signaling example
Below is a simplified WebRTC-style flow. The exact signaling details depend on your stack, but the idea is always the same: create an offer, gather ICE candidates, send them to the remote side, and let ICE select the path.
The important detail is not the exact JavaScript. It is that STUN and TURN are configured as ICE servers, and ICE does the actual candidate gathering and connectivity checks.
Where Protoface fits: the product should hide the network plumbing, not pretend it does not exist
In a developer platform like Protoface, the ideal experience is that you create a realtime avatar session and let the transport work underneath. You should not have to manually reason about ICE candidate types for every integration, but you should know that the platform’s realtime path is still subject to the same network realities as any other WebRTC-style stream.
For example, if you are using the LiveKit Agents plugin, the avatar is inserted into the voice agent pipeline so the agent gains a synchronized talking face. The plugin abstraction is convenient, but the same connectivity rules apply: if the media path needs a relay, that will be reflected in latency and session behavior. If you want examples, the plugin repository is a good place to start: https://github.com/protoface-ai/protoface-plugin-pipecat.
If you prefer to manage sessions directly, the REST API and Python SDK let you create and inspect avatars and sessions programmatically. That is useful when you want to correlate session state with connection issues from your own telemetry. See the main docs at https://docs.protoface.com for the exact request and response shapes, since those fields can evolve.
The snippet above is intentionally schematic. The key point is that your backend, not the browser, should hold the API key when you are creating sessions via the REST API.
Common gotchas
A few mistakes come up repeatedly:
Assuming STUN is enough. It is not enough in many enterprise and VPN environments.
Ignoring relayed traffic. If you do not measure TURN usage, you will miss a major source of latency and cost.
Confusing signaling with media transport. Signaling exchanges offers, answers, and ICE candidates; it does not carry the avatar stream itself.
Treating connection success as binary. Direct vs relayed matters, and transient ICE restarts matter too.
Also, for browser-based embeds, the transport layer is only part of the security story. If you are embedding an avatar in an iframe, you want the browser-facing surface to stay credential-free and constrained, while the backend handles session creation and policy. That is the right place to keep network and auth complexity out of the client.
Conclusion
ICE is the process that finds a working path. STUN helps discover what public address a client can present to the outside world. TURN provides the fallback relay when direct connectivity is not possible. Together, they are the network substrate that makes realtime avatar streaming reliable enough to ship.
For developers building voice agents, conversational video assistants, or embedded avatar experiences, the practical takeaway is simple: do not treat transport as an invisible detail. Measure it, expect relays in the wild, and make sure your stack can survive restrictive networks without falling apart.
If you are integrating an avatar into a production app, start with the docs at https://docs.protoface.com, then validate your path with real-world networks early. That will save you a lot of “works locally, fails on corporate Wi-Fi” debugging later.
