Fix WebRTC Connection Failed: ICE Failure Explained

WebRTC peer-to-peer latency, jitter, and packet loss. All measurement runs in the browser. No backend, no account.

ZERO UPLOAD · ALL LOCAL
  1. Wait for the automatic STUN probe to complete; it shows your public IP and NAT type.
  2. Choose a role: click "Start Session" on one browser to become the Initiator, "Join Session" on the other.
  3. Initiator: copy the offer SDP and send it to your partner.
  4. Joiner: paste the offer, click "Generate Answer", then copy the answer SDP and send it back.
  5. Initiator: paste the answer and click "Connect". The live dashboard starts automatically.
  6. Use the Simulated Loss and Artificial Latency sliders to test degraded conditions.

What to look for

  • UDP 3478
  • 5349

PROBING...

Public IP NAT Type Candidate Types STUN Reachable Gathering Time

YOUR OFFER — COPY AND SEND TO PARTNER

PASTE PARTNER'S ANSWER HERE

PASTE PARTNER'S OFFER HERE

YOUR ANSWER — COPY AND SEND BACK

Current RTT Average RTT Min RTT Max RTT Jitter Packets Sent Packets Received Packet Loss ICE Candidate Type

Accent line = RTT over time. Red markers = simulated packet drops.

Data Channel State Packets Echoed

Fix WebRTC Connection Failed: ICE Failure Explained

WebRTC ICE failure has a specific cause. When "connection failed" appears in a WebRTC application, the ICE protocol has exhausted all candidate pairs (host, reflexive, and relay) without establishing a working data channel.1 Understanding which candidate type failed tells you exactly what to fix: symmetric NAT requires a TURN relay2; a blocked STUN port requires firewall changes; a missing TURN server configuration requires adding relay candidates.

The STUN probe on this page runs through the same ICE negotiation steps that a failing WebRTC application uses. Completing it reveals your NAT type, the ICE candidate types your network generates, and whether reflexive candidates are reachable. If the probe succeeds but a specific application fails, the problem is in that application's ICE configuration, not the network itself.

Why ICE fails: the three common causes

Symmetric NAT on one or both peers is the most frequent cause of WebRTC connection failure. ICE hole-punching requires that both peers' routers accept incoming packets on the same external port used for the outbound STUN request; symmetric NAT assigns different ports per destination, defeating this mechanism2. The second cause is firewall blocking of UDP traffic on non-standard ports. Some corporate and guest Wi-Fi networks block all UDP above port 1024, preventing ICE candidates from being tested3. The third cause is a missing TURN configuration: when direct connection fails, ICE needs a configured TURN server to generate relay candidates. Without one, no fallback path exists and ICE reports failure1.

How to distinguish each cause from the browser console

Each cause produces a distinct signature in the browser developer console, which you can open with F12 on any WebRTC application. Symmetric NAT produces reflexive candidates that fail connectivity checks because the per-destination port assignment prevents the hole-punch from matching. A blocked UDP firewall produces no reflexive candidates at all because STUN requests never receive a response from the public server. A missing TURN configuration produces only host candidates with no relay fallback, and ICE reports "failed" after exhausting the host-only candidate pairs.

Reading ICE failure messages in the browser console

Opening the browser developer console (F12) during a WebRTC connection attempt logs the ICE agent state transitions: "checking", "connected", "completed", "failed", or "disconnected". A transition to "failed" after "checking" indicates ICE could not match any candidate pair. Furthermore, the ICE candidates gathered are logged as STUN binding responses; examining whether the gathered candidates include "srflx" (reflexive) or only "host" (local network) candidates reveals whether STUN server contact is succeeding. No reflexive candidates indicates STUN is blocked; reflexive candidates with no connection means the hole-punch failed and TURN is needed. CapyToolkit performs the same ICE negotiation sequence as any WebRTC application, so if the tester connects successfully but your application fails, the issue is in your application's ICE server configuration rather than the underlying network path.

Fixing ICE connection failures

For symmetric NAT: configure a TURN relay server and add its credentials to the WebRTC ICE server list in your application configuration. For firewall-blocked UDP: enable TCP fallback in your TURN server configuration (port 3478 TCP) or add TURN over TLS on port 443, which most firewalls allow4. For missing TURN: add at least one TURN server from a public provider or self-hosted instance to the RTCPeerConnection iceServers array. Conversely, reflexive candidates on a usable NAT path from the STUN probe here mean the network itself is fine; the issue is in the specific application's ICE server list or SDP negotiation.

Isolating the failure source with constrained ICE testing

Running a WebRTC connection with only STUN (no TURN) in the ICE server list tells you whether direct NAT traversal is possible on your network. If the connection succeeds with only STUN servers configured, symmetric NAT is not the issue. If it fails with only STUN but succeeds when a TURN server is added, symmetric NAT is the confirmed cause and the application needs TURN relay in its ICE configuration.

Testing both configurations from the same network within minutes eliminates timing variability as a factor. Configure a test RTCPeerConnection with only a STUN server (stun.l.google.com:19302), complete an ICE negotiation, and note the result. Then add a TURN server alongside the STUN server and retest. The difference between the two results isolates whether NAT traversal itself is failing or whether a TURN configuration problem is present independently.

Using iceTransportPolicy to force relay-only candidate selection

The iceTransportPolicy: "relay" option in the RTCPeerConnection configuration forces ICE to use only relay candidates, bypassing STUN and direct traversal entirely5. A connection that succeeds with relay-only policy but fails without it confirms TURN is available and working; the ICE failure in the normal configuration is a NAT traversal problem, not a TURN problem. All major browsers supporting the RTCPeerConnection spec accept this policy option, and no server-side changes are required to test it.

Monitoring ICE state transitions with browser event listeners

Attaching event listeners to RTCPeerConnection exposes the full ICE lifecycle in real time. The iceconnectionstatechange event fires on every state transition: from new to checking, checking to connected on success, or checking to failed when all candidate pairs are exhausted6. Logging each state change with a timestamp reveals exactly how long the ICE negotiation took and at which state it terminated.

The icegatheringstatechange event fires when ICE completes gathering all candidates6. A long delay between gathering and complete suggests TURN candidate allocation is slow, which may indicate a misconfigured or geographically distant TURN server. Short gathering time followed by a failed ICE connection state indicates that candidates were gathered successfully but no candidate pair passed connectivity checks; this points to a NAT or firewall issue rather than a TURN availability problem.

Logging individual ICE candidates to identify blocked candidate types

Adding an icecandidate event listener to the RTCPeerConnection logs each discovered candidate as it arrives. Candidates of type srflx confirm STUN reached the server and returned a reflexive address. Candidates of type relay confirm TURN allocated an address7. An absence of srflx candidates indicates STUN is blocked by a firewall; an absence of relay candidates indicates TURN credentials are missing or the TURN server is unreachable. Both are immediate diagnostic signals that point to a specific configuration issue in the application or network.

Watching the candidate log during a live connection attempt shows exactly where negotiation breaks, which is faster than guessing from a generic failure message. The absence of a specific type tells you which network layer to investigate first, whether that is a firewall rule, a missing TURN credential, or a symmetric NAT upstream. Keeping this log alongside the console state transitions gives you a complete picture that support engineers or a WebRTC library's documentation can act on without requesting the test be repeated.

When to use this

Run this test when a WebRTC application reports a connection failure, when you need to determine whether the failure is network-side or application-side, or when setting up a new WebRTC deployment and verifying that ICE can succeed between two specific network configurations.

Examples

WebRTC app fails on corporate Wi-Fi but works on home network

The STUN probe on corporate Wi-Fi shows no reflexive candidates; UDP is blocked. The app must use TURN over TLS port 443 to traverse the corporate firewall. Standard STUN and UDP TURN will not work on this network.

STUN probe shows reflexive candidates but ICE still fails

Both peers can reach STUN servers, but the reflexive candidates are not connecting. One peer is behind symmetric NAT. The application needs a TURN relay in the ICE server list. Add TURN credentials and the relay candidate should succeed.

Sources
  1. 1.

    A. Keranen, C. Holmberg, and J. Rosenberg, "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal," RFC 8445, IETF, July 2018. https://www.rfc-editor.org/rfc/rfc8445.html

  2. 2.

    "STUN," Wikipedia, accessed June 2026. https://en.wikipedia.org/wiki/STUN

  3. 3.

    J. Rosenberg, R. Mahy, and P. Matthews, "Session Traversal Utilities for NAT (STUN)," RFC 5389, IETF, October 2008. https://datatracker.ietf.org/doc/html/rfc5389

  4. 4.

    P. Srisuresh and M. Holdrege, "Peer-to-Peer Communication across Network Address Translators," RFC 5128, IETF, February 2008. https://datatracker.ietf.org/doc/html/rfc5128

  5. 5.

    Mozilla Developer Network, "RTCPeerConnection() constructor," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection

  6. 6.

    Mozilla Developer Network, "RTCPeerConnection: iceconnectionstatechange event," developer.mozilla.org, accessed June 2026. https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceconnectionstatechange_event

  7. 7.

    J. Rosenberg, "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal," RFC 5245, IETF, February 2010. https://www.rfc-editor.org/rfc/rfc5245.txt

FAQ