Header Logo

How to Configure ICE, STUN, and TURN in the Protoface Node SDK for Realtime Avatar Apps

How to Configure ICE, STUN, and TURN in the Protoface Node SDK for Realtime Avatar Apps

Configure ICE, STUN, and TURN for Protoface Node SDK WebRTC avatar apps: NAT traversal, TURN fallback, and session setup.

Introduction


When you add a realtime avatar to a voice agent, you are not just streaming video. You are negotiating a peer-to-peer media session over hostile networks: browsers behind NAT, corporate firewalls, mobile carriers, flaky Wi-Fi, and sometimes all of the above. That is where ICE, STUN, and TURN matter. If you configure them correctly, your avatar session connects quickly, keeps latency low, and survives the messy parts of the public internet.


This post explains the practical role of each component, how they interact in a WebRTC-based avatar flow, and how to configure them in a Node.js app that talks to a realtime avatar service. By the end, you should be able to choose sensible ICE servers, understand when TURN is required, and avoid the common “works on my laptop, fails in production” trap.


ICE, STUN, and TURN: what each piece actually does


WebRTC does not send media on a fixed socket. It uses ICE (Interactive Connectivity Establishment) to discover a working network path between endpoints. ICE is the orchestration layer: it gathers candidate addresses, tests them, and selects the best pair.


STUN and TURN are the infrastructure ICE uses to do that job:


  • STUN lets a client discover its public-facing address as seen from the outside. This is useful for direct peer-to-peer connectivity when NAT traversal is possible.

  • TURN relays media when direct connectivity fails. If both peers cannot reach each other directly, they send media to the TURN server, which forwards it. This adds latency and cost, but it is the fallback that keeps sessions alive.

  • ICE picks among host, reflexive, and relay candidates and continuously checks connectivity. In practice, ICE decides whether your avatar can connect directly or needs a relay.


For realtime avatars, the key point is that video and audio must start quickly and stay up under real network conditions. Direct paths are preferable because they are cheaper and lower latency. TURN is the safety net. If you disable it, some percentage of users will simply fail to connect from restrictive networks.


How the connection path works in an avatar app


In a typical setup, your application creates or joins a realtime session, then establishes a media connection where the avatar publishes synchronized audio and video. The exact signaling flow depends on the SDK or integration surface, but the network mechanics are the same:


  1. The client gathers ICE candidates.

  2. It uses STUN servers to determine public endpoints when possible.

  3. If direct candidate pairs fail ICE checks, it falls back to TURN relays.

  4. Once a valid candidate pair is selected, media flows over that path until connectivity changes.


Two practical implications follow from this:


  • Ice server configuration is not optional if you need reliable production connectivity.

  • You should expect different behavior on home Wi-Fi, enterprise networks, and mobile networks, even with the same code.


Configuring ICE servers in Node.js


In Node-based WebRTC apps, ICE configuration usually lives in the RTCPeerConnection options or in the library that wraps it. The important part is the iceServers list. It can include one or more STUN servers, one or more TURN servers, and TURN credentials if authentication is required.


A minimal example looks like this:


const pc = new RTCPeerConnection({
});
const pc = new RTCPeerConnection({
});
const pc = new RTCPeerConnection({
});


That snippet is intentionally generic. In a real application, the STUN/TURN URLs, usernames, and credentials should come from your infrastructure or the session setup returned by your avatar platform. Do not hardcode long-lived TURN credentials into a browser bundle.


A few practical rules:


  • Use at least one STUN server for candidate discovery.

  • Provide TURN over UDP and TCP if your provider supports both. TCP helps on locked-down networks.

  • If you are serving browsers, keep TURN credentials short-lived and generated server-side.

  • Prefer regional TURN deployments close to your users and your media backend to reduce relay latency.


Credential strategy and failure modes


TURN servers typically require authentication because they consume bandwidth. The common pattern is ephemeral credentials: your backend issues a username/password pair with a short TTL, and the client uses those credentials only for the duration of the session. This prevents arbitrary public use of your relay infrastructure.


Be careful with three failure modes:


  • No TURN fallback: users behind restrictive NATs may never establish media.

  • Expired TURN credentials: sessions that initially connect can later fail after network changes or ICE restarts.

  • Misconfigured transport: some environments block UDP, so relying only on UDP TURN is fragile.


Also remember that ICE restarts happen. If a network changes mid-session, the connection may renegotiate. Your configuration should allow the client to recover without a full application reload.


Node SDK example: wiring session setup to media config


If you are using a Node SDK to create or manage sessions, the usual pattern is:


  1. Create the avatar/session on the server.

  2. Return session metadata and any short-lived connectivity data to the client.

  3. Instantiate the WebRTC connection with that data.


Illustratively:


import { ProtofaceClient } from "@protoface/sdk-node";

});
import { ProtofaceClient } from "@protoface/sdk-node";

});
import { ProtofaceClient } from "@protoface/sdk-node";

});


On the client side, you would pass the returned iceServers into your WebRTC stack. The exact shape depends on the SDK and runtime, but the engineering idea is the same: keep sensitive connectivity credentials on the server, and pass only the minimum needed to the browser or edge runtime.


Practical tuning: latency, reliability, and cost


There is no single “best” ICE configuration. The right trade-off depends on your audience and your tolerance for relay costs.


For low-friction consumer usage, a good default is:


  • One or more STUN servers for discovery.

  • At least one TURN server with UDP and TCP transports.

  • Short-lived TURN credentials generated per session.

  • Regional placement near your users.


For enterprise or B2B deployments, assume a higher TURN usage rate. Corporate firewalls often block direct UDP or impose strict NAT behavior. In that environment, TURN is not an edge case; it is the path that keeps sessions reliable.


If you measure media quality, track more than just connection success. Useful signals include:


  • Time to first media.

  • ICE candidate pair type selected, especially relay vs direct.

  • Reconnect frequency.

  • Audio/video jitter and packet loss.


Those metrics tell you whether your configuration is merely “working” or actually providing an acceptable realtime experience.


How Protoface fits in


For a Protoface-backed avatar session, you generally do not want to hand-roll the whole realtime stack unless you need to. The platform exposes session and avatar management through its REST API and SDKs, and the session setup can surface the connectivity details your client needs. That keeps your application code focused on the media connection rather than on low-level signaling plumbing.


If you are using the Node SDK or the REST API, the implementation pattern is straightforward: create the session server-side, return the session payload to the client, and feed the ICE server list into your WebRTC layer. The exact response fields and request schema are documented in the API docs, so treat the examples here as structural guidance rather than a drop-in contract. See the documentation for the current session and avatar shapes.


If your avatar is integrated into a voice agent, this setup matters even more. The agent’s audio can be perfect while the video face silently fails if media connectivity is weak. Reliable ICE configuration is what keeps the avatar synchronized with the conversation.


Common debugging checklist


When a session fails to connect, work through the problem in this order:


  1. Confirm the client receives valid ICE server configuration.

  2. Check whether STUN is reachable from the target network.

  3. Verify TURN authentication and credential lifetime.

  4. Test TURN over both UDP and TCP.

  5. Inspect whether ICE selected a relay candidate or failed before nomination.


If a session works locally but not for external users, the usual culprit is missing TURN or overly aggressive firewall assumptions. If it works on Wi-Fi but not on mobile or corporate networks, suspect transport restrictions or expired credentials.


Conclusion


ICE is the decision engine, STUN helps discover public reachability, and TURN keeps you connected when direct paths fail. For realtime avatar apps, that trio is not infrastructure trivia; it is the difference between a demo and a production-ready experience.


In practice, configure at least one STUN server, always provide TURN as a fallback, keep TURN credentials short-lived, and test on restrictive networks before you ship. If you are building on Protoface, use the session APIs or Node SDK to keep connectivity data server-side and pass only the necessary ICE configuration to the client. For implementation details and current request/response shapes, start with docs.protoface.com.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.