← Chrome 148 reference

v148 · webrtc · web api · shipped

WebRTC Datachannel: Always negotiate data channels

A new alwaysNegotiateDataChannels option for RTCPeerConnection that pre-negotiates the application m-section in SDP offers, allowing either endpoint to call createDataChannel() later without a full SDP renegotiation. Ships in Chrome 148 on all platforms.

at a glance

Shipped inChrome 148 (desktop, Android, WebView)
StatusEnabled by default
SpecWebRTC Extensions — Always negotiating datachannels
ChromeStatus5113419982307328 — WebRTC Datachannel: Always negotiate data channels

background: the SDP data channel problem

In WebRTC, data channels use SCTP over DTLS, negotiated via an application m-section in SDP. The problem: an application m-section only appears in the SDP offer if createDataChannel() has already been called on that connection. This creates a chicken-and-egg situation:

For many applications — particularly those that conditionally open data channels based on user action — this means an extra round-trip of renegotiation just to establish a data channel.

the new option: alwaysNegotiateDataChannels

Setting alwaysNegotiateDataChannels: true in the RTCPeerConnection constructor makes Chrome include the application m-section in SDP offers from the start — even before any createDataChannel() call. This means:

const pc = new RTCPeerConnection({
  alwaysNegotiateDataChannels: true,
});

// Later, create a data channel without triggering renegotiation:
pc.addEventListener('connectionstatechange', () => {
  if (pc.connectionState === 'connected') {
    const channel = pc.createDataChannel('chat');
    channel.addEventListener('open', () => {
      channel.send('Hello!');
    });
  }
});

// The remote endpoint receives the channel via ondatachannel:
remotePc.addEventListener('datachannel', ({ channel }) => {
  channel.addEventListener('message', (e) => console.log(e.data));
});
Source: WebRTC Extensions specification.

without alwaysNegotiateDataChannels

Without the option, the typical workaround is to call createDataChannel() before creating the initial offer — usually creating a throw-away "placeholder" channel just to force the m-section into the SDP — and close or ignore it once the connection is established. The new option eliminates this workaround.

// Before Chrome 148: workaround — create a dummy channel to force m-section
const pc = new RTCPeerConnection();
const placeholder = pc.createDataChannel('_placeholder'); // forced m-section
const offer = await pc.createOffer();

// After answering, immediately close the placeholder
pc.addEventListener('connectionstatechange', () => {
  if (pc.connectionState === 'connected') {
    placeholder.close();
  }
});

browser support

Chrome / Edge148 (all platforms)
FirefoxNo signal
SafariNo signal
Source: chromestatus.com browser positions, May 2026.

see also