ICE restart is a mechanism in WebRTC that triggers a fresh round of ICE negotiation on an existing PeerConnection without tearing down the session.
It is defined in IETF RFC 8445 (the current ICE specification) and exposed in the WebRTC API as RTCPeerConnection.restartIce().
Why ICE restart is needed
Once ICE completes, the chosen candidate pair stays in use for the duration of the call. That works until the network underneath changes. Common triggers:
- A device switches from Wi-Fi to cellular (or between two Wi-Fi networks)
- A NAT binding times out and a new public address is assigned
- The ICE connection state moves to
failedordisconnected - A TURN allocation expires or the relay path breaks
Without ICE restart, the only option in these situations is to drop the call and create a new PeerConnection from scratch. ICE restart lets the session recover in place, usually without the user noticing more than a short media freeze.
In many ways, the reasons to use ICE restart is to reduce the time to handle connection breakages that are temporary in nature, shaving a couple hundreds of milliseconds versus the alternative.
How ICE restart works
An ICE restart is essentially a fresh ICE session running inside the same PeerConnection:
- One side generates a new SDP offer with new
ice-ufragandice-pwdvalues (the credentials that scope an ICE session) - Both peers gather ICE candidates again from scratch, including fresh STUN reflexive candidates and TURN relay candidates
- Connectivity checks run against the new candidate pairs
- Once a working pair is nominated, media switches to the new path
- The old ICE session is discarded
During the restart, the existing media path continues to be used for as long as it is still working. If it is already broken, there is a gap until the new path is established.
Triggering an ICE restart
There are two ways to start an ICE restart from JavaScript:
pc.restartIce()– This approach marks the connection as needing an ICE restart, firesnegotiationneeded, and the nextcreateOffer()will include the restart flag automaticallypc.createOffer({ iceRestart: true })– Works just as well, thoughrestartIce()is preferred if you plann on using Perfect Negotiation patterns
A common pattern is to listen for ICE state changes and restart automatically:
pc.oniceconnectionstatechange = () => {
if (pc.iceConnectionState === 'failed') {
pc.restartIce();
}
};
Some applications also preemptively restart ICE on disconnected instead of waiting for failed, trading a small amount of extra signaling for faster recovery.
ICE restart vs full renegotiation
ICE restart is narrower than a full SDP renegotiation:
- ICE restart replaces only the ICE credentials and candidates. Codecs, SDP media sections, and DTLS keys stay the same
- Full renegotiation (calling
createOffer()without the restart flag) can add or remove tracks, change codecs, or renegotiate media parameters
Restart is cheaper and faster because the DTLS handshake and SRTP keys are preserved. It is the right tool for pure connectivity recovery, not for media changes.
ICE restart and mobile networks
Mobile clients are the main reason ICE restart exists in practice. Network handovers (Wi-Fi to LTE, LTE to 5G, switching access points) change the local IP address and often invalidate NAT bindings. Applications that run long calls on mobile devices – especially call center and telehealth apps – should always wire up automatic ICE restart on failed, and consider restarting on disconnected for faster recovery.
Media servers and ICE restarts
For ICE restart to work in a scenario involving media servers, the media servers themselves need to support this logic. This isn’t always the case.
ICE restart for example, isn’t commonly found in VoIP media servers that focus on SIP connectivity. Some SFUs also don’t support ICE restart. If you need ICE restart, be sure the media server you choose supports this mechanism.


