WebRTC Diagnostics

Check browser WebRTC, ICE candidates, STUN, and TURN

Loading tool…

About WebRTC Support, ICE Candidate, STUN & TURN Checker

WebRTC Support, ICE Candidate, STUN & TURN Checker answers three separate questions on one page: whether this browser exposes the WebRTC APIs at all, whether each STUN or TURN service you configure actually answers from this network, and which ICE candidates this machine can gather right now. Every server is probed on its own with its own verdict, so a blocked or retired host shows up as one failed row instead of disappearing into an aggregate count.

A WebRTC connection is never made to an address you type in. Both sides gather candidates — every address a packet might arrive on — exchange them, and let the ICE agent probe the pairs until one passes. A STUN server contributes exactly one thing to that process: it reports the public address and port your NAT mapped your socket to, which becomes the server-reflexive candidate. A TURN server contributes a rented transport address on the relay itself, which is the only candidate that still works when neither side can be reached directly. Almost every "WebRTC does not work here" report resolves into one of three layers — browser API, candidate gathering, or server reachability — and checking them separately is what stops the guessing.

How to use this developer tool

  1. Read the capability card first: RTCPeerConnection, RTCDataChannel, and a secure context. WebRTC is gated on HTTPS or localhost, so a plain http:// page fails here before any network question arises.
  2. Add the services you intend to use. Pick entries from the built-in public STUN catalogue, or type your own URL such as turn:turn.example.net:3478?transport=tcp.
  3. Fill in the username and credential for every turn: or turns: row. A TURN row without credentials is reported as a credential failure rather than being probed.
  4. Run the server check. Each row is probed alone within a four-second budget and reports the candidate type it produced, the transport, the relay protocol, the mapped address, and the elapsed time.
  5. Run the candidates check to gather from the whole configuration at once, then read the per-type counts: they are exactly what this browser could offer a peer.
  6. Expand Raw candidate under any card when you need the literal SDP line — foundation, priority, related address, and ufrag are all there.

Worked example: reading a server-reflexive candidate line

One STUN service and one TURN service are configured, and the candidates check is run on a laptop behind a consumer router. Three candidates come back. The second one is the line that proves STUN answered, and every field in it carries information.

ICE configuration
stun:stun.example.org:3478

turn:turn.example.net:3478?transport=udp
  username:   1774915200:devtools
  credential: q0Zp3rVYbK8n1xS2mE7aQd4H
Gathered candidates
candidate:1854123094 1 udp 2122262783 9b8f0a1c-6d3e-42f7-9c0a-7f21b6d5e310.local 54123 typ host generation 0 ufrag Qq7A network-cost 999
candidate:842163049 1 udp 1686052863 203.0.113.44 54123 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag Qq7A
candidate:3096142582 1 udp 41885439 198.51.100.7 60112 typ relay raddr 203.0.113.44 rport 54123 generation 0 ufrag Qq7A

The srflx line, field by field:

  842163049      foundation    identifies candidates sharing a base, interface and server, so ICE can skip redundant pair checks
  1              component     1 is RTP; a data channel only ever has component 1, so a 2 here means media was negotiated too
  udp            transport     the protocol this candidate speaks to the peer
  1686052863     priority      type preference (srflx = 100) combined with local preference and component; ICE probes high to low
  203.0.113.44   address       the public address your NAT mapped the socket to, learned from the STUN binding response
  54123          port          the external port of that mapping
  typ srflx      type          server-reflexive: this candidate exists only because a STUN server replied
  raddr 0.0.0.0  related addr  the local base address is withheld, because the host candidate is mDNS-obfuscated
  rport 0        related port  withheld for the same reason
  ufrag Qq7A     ICE ufrag     ties the candidate to this gathering session; it changes on every ICE restart

The srflx line is the proof that STUN worked: without a binding response the browser has no way to learn 203.0.113.44. Notice that its port, 54123, is the same as the host candidate's port — a router that keeps the port stable across destinations is doing endpoint-independent mapping, which is the friendly case for peer-to-peer.

ICE candidate types: what each one proves and what it gives away

Read the per-type counts on the results panel against this table; a missing row is as informative as a present one. STUN costs its operator one small packet, while TURN carries the entire session, which is why public STUN is everywhere and public TURN essentially is not. A relay only becomes necessary when no host or srflx pair survives the connectivity checks — typically symmetric NAT on both ends, or a network that drops UDP outright.

TypeProduced byWhat a result provesWhat it reveals
hostA local network interface. No server is involved and nobody pays for traffic.The browser could enumerate an interface and bind a socket to it.Your LAN address — unless the browser replaced it with a random .local mDNS name, which is the default in current Chrome and Firefox.
srflxA STUN binding request. The STUN server answers one small packet and never carries payload.Outbound UDP reaches the STUN service and a NAT mapping exists that an outside host can address.Your public IP and the external port the NAT chose. The STUN operator sees the same pair.
prflxConnectivity checks, when a packet arrives from an address that neither side advertised.A working path exists that gathering did not predict.That the remote NAT remaps per destination — a strong hint that symmetric NAT is in play.
relayA TURN allocation. Every byte of the session crosses the TURN server, so its owner pays for all of the bandwidth.Your credentials were accepted and the server handed out a transport address on itself.Only the relay's address to your peer. Your own address is hidden from the peer and fully visible to the TURN operator.

Troubleshooting

Every host candidate shows a random .local hostname instead of a LAN IP.

Why it happens Chrome and Firefox obfuscate host candidates behind an mDNS name so that a web page cannot fingerprint your internal network. The name still resolves over multicast DNS on the local subnet, so peers on the same LAN connect normally; only the page's JavaScript is blinded.

Fix Nothing to fix — this is the designed behaviour, and the tool labels those candidates as masked. If you specifically need to see which local addresses are exposed, the Browser Leak Check page is the tool built for that question.

A TURN row reports unreachable while a STUN row on the same host passes.

Why it happens Two causes look identical from the browser. Time-limited TURN credentials are usually an HMAC over a unix expiry timestamp, and an expired pair is refused at allocation time with an error indistinguishable from a dead server. The other cause is transport: if the relay only offers UDP on 3478 and the local network drops UDP, the allocation never completes.

Fix Regenerate the credential pair and check the expiry you were handed, then retry with a turns: URL on 443 with ?transport=tcp. The relay protocol column tells you which transport actually carried the allocation when it does succeed.

The candidates check returns host candidates only — no srflx and no relay.

Why it happens Outbound UDP is being dropped. Corporate, campus, and hotel networks routinely allow only TCP on 80 and 443, which kills STUN on 3478 outright, and a UDP TURN allocation with it.

Fix Try a catalogue STUN entry on port 53 or 443 first, since those ports are often passed. If nothing returns srflx, the network has no UDP path at all and only turns: over TCP on 443 will work, because it is indistinguishable from ordinary TLS to most middleboxes.

A turn: URL is rejected as unsupported before a single packet is sent.

Why it happens The host behind it is a public STUN service that was entered with a turn: scheme. Public STUN servers answer binding requests but do not relay, so probing them under a relay-only policy would only burn the four-second budget.

Fix Enter that host as stun:, and configure a genuine TURN server separately — a self-hosted coturn or a commercial relay. This site does not run or host a TURN relay for you.

A server that passed a minute ago now fails, with no configuration change.

Why it happens The probe has a four-second budget and a single attempt. A dropped UDP packet, a rate limiter on a heavily used public service, or an anycast route that moved you to a different node all produce a timeout without any error.

Fix Re-run the check before concluding anything, and prefer a service you control for anything load-bearing. Treat a public STUN entry that fails intermittently as unfit for production regardless of the reason.

When this tool is the right choice

  • Proving that a newly deployed coturn really hands out relay candidates, before an application team starts blaming their signalling layer.
  • Deciding which public STUN service is actually reachable from a specific office, campus, or country before hard-coding one into an app.
  • Narrowing down a one-sided connection failure by comparing which candidate types each end can gather.
  • Checking whether a locked-down or managed browser supports data channels at all, including the secure-context requirement.

When to use something else

  • Investigating what your browser exposes to the sites you visit. Browser Leak Check is built for that and covers WebRTC addresses alongside IPv4/IPv6 paths and DNS resolver signals.
  • Measuring call quality, jitter, or packet loss. These are one-shot gathering probes; use a media-quality tool or getStats on a live session instead.
  • Assessing general IPv4 and IPv6 reachability, which IP Network Check answers directly by probing both families.

Privacy and data handling

Every check runs inside this browser tab. STUN binding requests and TURN allocate requests go straight from your browser to the hosts you entered, so those operators see your public IP, and a TURN operator additionally sees the credentials you supplied; this site is not in that path and never receives a candidate. The server list, usernames, and credentials are kept in this browser's local storage under devtoys:webrtc-ice so they survive a reload — use Restore defaults to clear them on a shared machine. Candidate lines contain your public IP and, when mDNS masking is off, your LAN address, so redact them before pasting a result into a ticket.

Related developer tools

Frequently asked questions

Do my candidates or TURN credentials reach your server?

No. Capability detection, candidate gathering, and every probe run in this browser tab, and the requests go directly from your browser to the STUN or TURN hosts you entered. Those operators necessarily see your public IP, and a TURN operator sees the username and credential you supplied. Your configuration is stored only in this browser.

Do you provide a STUN or TURN server?

No. The tool ships a catalogue of well-known public STUN addresses as a convenience so you can find one that answers from your network, and it can re-check each of them. This site does not run or host a TURN relay, because relaying means paying for every transferred byte. For TURN, use your own coturn or a commercial provider.

Does a passing STUN check mean my application will connect?

No, only that this browser on this network can learn its own mapping. A connection also needs the other side to gather a compatible candidate and both NATs to let the connectivity checks through. A passing STUN check rules out one whole class of failure; it does not confirm the pair.

Why does TURN require a username and credential?

A TURN server allocates a port and forwards every byte of the session, so an open relay is abused within hours of being discovered. Most deployments therefore issue short-lived credentials derived from a shared secret and an expiry timestamp. The checker treats a TURN entry as reachable only when the server hands back a relay candidate using the credentials you gave it.

Why are my local IP addresses replaced with .local names?

Modern Chrome and Firefox generate a random mDNS hostname per host candidate so that a page cannot enumerate your internal network. Peers on the same subnet resolve the name over multicast DNS, so local connections still work. The tool reports these candidates as masked rather than pretending they are missing.

What does relay-only mode change about the check?

It sets the ICE transport policy to relay, so the browser gathers nothing but relay candidates. That is the honest way to test a TURN configuration in isolation, because a working direct path can otherwise hide a broken relay. It also keeps host and server-reflexive addresses out of the result entirely.