ICE coordinates everything between "two peers want to talk" and "media is flowing". Each endpoint gathers candidate addresses — its local interface IPs, its STUN-reported public address, and a TURN-allocated relay address — and exchanges them with the other peer through a signalling channel (typically SDP offer/answer over WebSocket). Each side then performs connectivity checks against every pairing of local and remote candidates, in priority order, until one pair works.
The priority order matters. ICE tries host candidates first (same LAN), then server-reflexive (STUN, direct internet), then relayed (TURN). The first working pair is "nominated" and used for media. If the path later degrades — Wi-Fi to cellular handoff, for instance — ICE restart can re-run the gathering and re-pick. ICE Trickle (RFC 8838, January 2021) lets candidates flow incrementally so connection establishment can begin as soon as the first viable pair is found, rather than waiting for the whole gathering to finish.
For developers, ICE is mostly hidden inside RTCPeerConnection. The visible parts are configuring iceServers (STUN and TURN URLs and credentials) and listening to iceconnectionstatechange events. The operational visibility is in TURN traffic ratios and connection-failure rates — both reported by every commercial WebRTC observability tool.

