When two browsers try to connect, each produces a list of possible network routes. In WebRTC, each route is an ICE candidate: a short string beginning with candidate: that means, roughly, “try reaching me here.” ICE stands for Interactive Connectivity Establishment.

The browsers exchange candidates, build possible pairs, and test those pairs in priority order. Once one browser nominates a successful pair, it becomes the selected path for the screen share. This is the networking step inside WebRTC; the full connection journey also includes signaling, encryption, and media setup.

Anatomy of one candidate

Here is MDN’s example of a candidate as it appears on the wire:

candidate:4234997325 1 udp 2043278322 192.0.2.172 44323 typ host

Read from left to right, following the SDP candidate grammar:

  • Foundation — 4234997325: a grouping key. Candidates share a foundation when they have the same type, base IP address, transport protocol, and STUN or TURN server.
  • Component — 1: which media component this route serves. In MDN’s example, 1 means RTP.
  • Transport — udp: the network transport for this route.
  • Priority — 2043278322: the candidate’s rank, which helps determine the order in which pairs are tested.
  • Address and port — 192.0.2.172 44323: where the other browser can try to send a check.
  • Type — typ host: where this address came from.

Some candidates add raddr and rport. These fields identify the related address from which a server-reflexive, peer-reflexive, or relayed candidate was derived. An implementation may replace that related address with a blank placeholder for privacy.

On Linkside, the candidate string travels through the signaling service inside an ice_candidate message, alongside sdpMid, sdpMLineIndex, and usernameFragment. It is connection metadata, not a piece of the shared screen or audio.

The four ICE candidate types

The typ field uses four standard tokens. STUN and TURN explain the servers behind two of them; this table focuses on what each token means during ICE.

TokenWhere the address comes fromWhen it appearsRFC-recommended type preference
hostA local network interfaceCandidate gathering126
srflxA NAT mapping learned through STUNCandidate gathering100
prflxA previously unknown mapping observed by the peer during a checkConnectivity checks110
relayAn address allocated on a TURN serverCandidate gathering0

prflx, short for peer-reflexive, is the unusual one: it is discovered while checks are already running. A STUN response reveals an address that was not on the original list, and ICE adds it as a candidate.

The numbers in the last column are recommendations, not a promise that every implementation uses those exact values. They express the intended order: try direct routes before spending relay capacity. A low relay preference does not mean TURN is unreliable. It means a working direct route should normally be tried first.

The priority number is not random

RFC 8445 defines the candidate priority formula as:

priority = (2^24 × type preference)
         + (2^8 × local preference)
         + (256 - component ID)

Type preference occupies the most significant part of the number, local preference lets an implementation rank candidates of the same type, and the final term ranks the component. Priority is an ordering instruction, not a speed test and not proof that a route will work. The candidate’s explicit typ field is more useful than trying to infer its type from the decimal number.

From two lists to one checklist

ICE combines compatible local and remote candidates into pairs. One agent is assigned the controlling role and the other the controlled role. If G is the controlling candidate’s priority and D is the controlled candidate’s priority, the pair rank is:

pair priority = 2^32 × min(G, D)
              + 2 × max(G, D)
              + (G > D ? 1 : 0)

That last bit breaks an otherwise equal tie. Pairs are checked from higher to lower priority. Redundant candidates are pruned, and RFC 8445 sets a default checklist limit of 100 pairs; if the limit is exceeded, the lowest-priority pairs are discarded.

Each remaining pair has one of five states:

  • Frozen: held back until ICE’s unfreezing rules allow it to run.
  • Waiting: ready to be checked.
  • In-Progress: a check has been sent and is awaiting a result.
  • Succeeded: the check worked.
  • Failed: the check timed out or returned a failure.

Connectivity checks test the real route

A connectivity check is a STUN request-and-response transaction sent from the pair’s local candidate to its remote candidate. Both browsers run checks, producing a four-message exchange for a successful pair. The checks use the same IP addresses and ports that will later carry the media, so they test the actual route rather than a proxy for it.

Trickle ICE avoids waiting for the full candidate list. Candidates are exchanged as they become available, and new pairs enter the checklist while gathering continues. Linkside follows that pattern: each discovered candidate is forwarded to the other participant as it arrives.

Nomination: how one pair wins

With regular nomination, the controlling agent considers the successful pairs, chooses one, and sends another check with the USE-CANDIDATE flag. If that check succeeds, the nominated pair becomes the selected pair: the addresses used to send and receive media for that component. Remaining checks for the component are cancelled.

Older ICE also allowed aggressive nomination, which put USE-CANDIDATE on every check. RFC 5245 described it as faster but less flexible; RFC 8445 deprecated it. The selected route can still change after an ICE restart or later network change, so “selected” does not mean permanent.

What “ICE failed” really means

In the browser, iceConnectionState: 'failed' means ICE checked its candidate pairs but could not find compatible matches for every required component. It does not necessarily mean the internet connection is down; it means the two browsers did not establish a usable ICE path.

disconnected is a weaker signal. It can appear briefly on an unreliable network and return to connected without intervention. A failed connection may require an ICE restart or another route. On an eligible free Linkside room, a host-side ICE failure can start the one-time five-minute encrypted TURN relay trial.

What ICE reveals, and what it does not

An ICE candidate can contain network addresses, so it is not secret metadata. Candidates are exchanged with the other participant, and a direct connection can expose your public IP address to them. Linkside’s Connection details panel says so plainly. Only a relay candidate on your local side hides your public IP behind the relay; a relay used only by the remote side changes their exposure, not yours.

The candidate does not contain the screen, audio, or encryption keys. Linkside is peer-to-peer first, so media normally travels directly between browsers. If the direct path fails and TURN is used, the relay and its network provider can observe the routing of encrypted packets, but the media remains encrypted in transit with DTLS-SRTP. The browsers handle the keys; Linkside’s signaling and relay services do not hold them. Linkside does not record sessions, and rooms disappear after the session ends.

How Linkside reads the winner back out

The browser exposes ICE results through getStats(), and Linkside uses them in its Connection details panel. The app first follows the transport report’s selectedCandidatePairId. This matters after an ICE restart, when more than one old or current pair may still be marked succeeded. If that pointer is unavailable, Linkside falls back to a nominated pair, then to a succeeded pair.

Linkside reads the local and remote candidate types from the resolved pair. A relay candidate on either side produces “Relayed through server”; otherwise the panel shows “Direct peer-to-peer.” It also translates combinations into notes such as “Both behind NAT, connected directly” and reports the public-IP exposure described above.

ICE does not decide whether a product is private by itself. It tells you which network path succeeded. The useful trust questions come next: who can see the connection metadata, whether media stays encrypted on every path, and what the service retains. Linkside exposes the selected path, keeps media encrypted on direct and relay routes, and does not record the session.

Create a room, open Connection details, and see which route the browsers selected.