> ## Documentation Index
> Fetch the complete documentation index at: https://docs.daily.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Network events

> Events for network quality changes, connection interruptions, CPU load, and prejoin test results.

These events fire when network quality or connection state changes, when CPU load fluctuates, and when prejoin tests complete.

***

## network-quality-change

<Badge color="green">{"✓"} Prebuilt</Badge> <Badge color="green">{"✓"} Custom</Badge>

Fires when the network quality assessment changes.

<Warning>
  As of daily-js 0.77.0, `threshold` and `quality` are deprecated in favor of `networkState` and `networkStateReasons`. Version 0.77.0 also added the `stats` bundle to the event payload.
</Warning>

<ResponseField name="action" type="string">
  Always `"network-quality-change"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="networkState" type="string">
  Current network assessment: `'good'`, `'low'`, or `'bad'`.
</ResponseField>

<ResponseField name="networkStateReasons" type="string[]">
  Reasons contributing to a `'low'` or `'bad'` state. Possible values include `'sendPacketLoss'` and `'recvPacketLoss'`. Omittied if `networkState` is `'good'`.
</ResponseField>

<ResponseField name="stats" type="object">
  The latest network stats bundle. Shape matches the return value of [`getNetworkStats()`](/reference/daily-js/instance-methods/get-network-stats).
</ResponseField>

<ResponseField name="threshold" type="string" deprecated>
  Deprecated. Use `networkState` instead.
</ResponseField>

<ResponseField name="quality" type="number" deprecated>
  Deprecated. Use `networkState` instead.
</ResponseField>

```json theme={null}
// Example event object
{
  "action": "network-quality-change",
  "callClientId": "17430118453690.12992179309705953",
  "networkState": "bad",
  "networkStateReasons": ["sendPacketLoss", "recvPacketLoss"],
  "stats": {
    "averageNetworkRoundTripTime": 0.01992261904761905,
    "latest": {
      "audioRecvPacketLoss": 0.15053763440860216,
      "videoSendBitsPerSecond": 1589251.349980054,
      "..."
    }
  }
}
```

```javascript theme={null}
call.on('network-quality-change', ({ networkState, networkStateReasons }) => {
  if (networkState === 'bad') {
    showNetworkWarning(networkStateReasons);
  }
});
```

***

## network-connection

<Badge color="green">{"✓"} Prebuilt</Badge> <Badge color="green">{"✓"} Custom</Badge>

Fires when a network connection is established or interrupted. Every call uses two connections simultaneously:

* **`signaling`** — carries call setup and management. If interrupted and not reconnected within \~20 seconds, the participant is ejected from the call.
* **`peer-to-peer`** or **`sfu`** — carries audio and video. A call uses one or the other, never both. All calls default to SFU topology, including 1:1 calls. See [P2P vs SFU calls](/docs/guides/architecture-and-monitoring/intro-to-video-arch#the-architecture-of-a-room-p2p-vs-sfu-calls) for details. Both reconnect automatically as long as `signaling` is alive.

<ResponseField name="action" type="string">
  Always `"network-connection"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="type" type="string">
  The connection type: `'signaling'`, `'peer-to-peer'`, or `'sfu'`.
</ResponseField>

<ResponseField name="event" type="string">
  The connection event: `'connected'` or `'interrupted'`.
</ResponseField>

<ResponseField name="session_id" type="string">
  Present for `peer-to-peer` connections. The remote peer's `session_id`.
</ResponseField>

<ResponseField name="sfu_id" type="string">
  Present for `sfu` connections. The SFU server ID — useful for debugging and support reports.
</ResponseField>

```json theme={null}
// Example: signaling connected
{
  "action": "network-connection",
  "type": "signaling",
  "event": "connected",
  "callClientId": "17225364729060.9442072768918943"
}
```

```json theme={null}
// Example: peer-to-peer connected
{
  "action": "network-connection",
  "type": "peer-to-peer",
  "event": "connected",
  "session_id": "123e4567-e89b-12d3-a456-426655440000",
  "callClientId": "17225364729060.9442072768918943"
}
```

```json theme={null}
// Example: sfu interrupted
{
  "action": "network-connection",
  "type": "sfu",
  "event": "interrupted",
  "sfu_id": "server-id",
  "callClientId": "17225364729060.9442072768918943"
}
```

***

## cpu-load-change

<Badge color="green">{"✓"} Prebuilt</Badge> <Badge color="green">{"✓"} Custom</Badge>

<Warning>
  The `cpu-load-change` event applies to video calls only.
</Warning>

Fires when the CPU load state changes. When `cpuLoadState` is `'high'`, consider lowering outgoing video quality via [`updateSendSettings()`](/reference/daily-js/instance-methods/update-send-settings), requesting a lower simulcast layer via [`updateReceiveSettings()`](/reference/daily-js/instance-methods/update-receive-settings), or reducing video subscriptions in large calls.

<ResponseField name="action" type="string">
  Always `"cpu-load-change"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="cpuLoadState" type="string">
  Current CPU load assessment: `'low'` or `'high'`.
</ResponseField>

<ResponseField name="cpuLoadStateReason" type="string">
  The reason for the current state: `'none'` (load is low), `'encode'` (video encoding), `'decode'` (video decoding), or `'scheduleDuration'` (Daily code not completing within its scheduled interval).
</ResponseField>

```json theme={null}
// Example event object
{
  "action": "cpu-load-change",
  "cpuLoadState": "low",
  "cpuLoadStateReason": "none",
  "callClientId": "17225364729060.9442072768918943"
}
```

***

## test-completed

<Badge color="green">{"✓"} Prebuilt</Badge> <Badge color="green">{"✓"} Custom</Badge>

Fires when a prejoin test completes.

<Note>
  Daily Prebuilt runs [`testCallQuality()`](/reference/daily-js/instance-methods/test-call-quality) automatically in its prejoin UI — you can listen for this event to read the results without calling it manually.
</Note>

<ResponseField name="action" type="string">
  Always `"test-completed"`.
</ResponseField>

<ResponseField name="callClientId" type="string">
  The ID of the call client instance that emitted this event.
</ResponseField>

<ResponseField name="test" type="string">
  Which test completed: `'call-quality'`, `'p2p-call-quality'`, `'network-connectivity'`, or `'websocket-connectivity'`.
</ResponseField>

<ResponseField name="results" type="object">
  The test results. Shape matches the return type of the corresponding test method — see [`testCallQuality()`](/reference/daily-js/instance-methods/test-call-quality).
</ResponseField>

```json theme={null}
// Example: call-quality test completed
{
  "action": "test-completed",
  "test": "call-quality",
  "results": {
    "result": "good",
    "data": {
      "maxRoundTripTime": 0.247,
      "avgRoundTripTime": 0.13130370781129388,
      "avgSendPacketLoss": 0.0036800000000000014,
      "avgAvailableOutgoingBitrate": 2060985,
      "avgSendBitsPerSecond": 1778201
    },
    "id": "47dc6b22-2909-46f3-8d0f-ec1f3807046c",
    "secondsElapsed": 22
  },
  "callClientId": "17225364729060.9442072768918943"
}
```

***

## See also

<CardGroup>
  <Card title="Methods" icon="code" iconType="solid">
    * [getNetworkStats()](/reference/daily-js/instance-methods/get-network-stats)
    * [updateSendSettings()](/reference/daily-js/instance-methods/update-send-settings)
    * [updateReceiveSettings()](/reference/daily-js/instance-methods/update-receive-settings)
    * [testCallQuality()](/reference/daily-js/instance-methods/test-call-quality)
  </Card>

  <Card title="Guides" icon="book-open" iconType="solid">
    * [Events](/docs/daily-js/concepts/events)
    * [Network quality](/docs/daily-js/guides/network-quality)
    * [Logging and metrics](/docs/guides/architecture-and-monitoring/logging-and-metrics)
  </Card>
</CardGroup>
