Skip to main content
Every person (or bot) in a Daily room is represented as a DailyParticipant object. Daily keeps these objects up to date as media states, permissions, and network conditions change.

The DailyParticipant Object

interface DailyParticipant {
  // Identity
  user_id: string;
  user_name: string;
  userData?: unknown;
  session_id: string;
  joined_at?: Date;
  local: boolean;
  owner: boolean;
  record: boolean;
  participantType?: DailyParticipantTypeValues;

  // Media tracks
  tracks: DailyParticipantTracks;

  // Network
  networkQualityState?: 'good' | 'warning' | 'bad' | 'unknown';

  // Permissions
  permissions: DailyParticipantPermissions;
  will_eject_at: Date;
}
See the DailyParticipant type reference for the full field listing with types and descriptions.

Listing Participants

participants()

Returns a DailyParticipantsObject — a flat map of all participants currently visible to the local client.
interface DailyParticipantsObject {
  local: DailyParticipant;
  [sessionId: string]: DailyParticipant;
}
const { local, ...remotes } = call.participants();

console.log('My session:', local.session_id);

for (const [sessionId, participant] of Object.entries(remotes)) {
  console.log(participant.user_name, sessionId);
}
The local key is always present. Remote participants are keyed by their session_id.

participantCounts()

Returns aggregate counts without full participant data — more accurate than counting participants manually as participant data can come in delayed on join, whereas the counts are provided immediately. Also, hidden participants are not included in participants(), but are included in the counts returned by participantCounts().
interface DailyParticipantCounts {
  present: number; // participants visible via participants()
  hidden: number;  // participants with hasPresence: false
}
const { present, hidden } = call.participantCounts();
console.log(`${present} visible, ${hidden} hidden`);
Listen for participant-counts-updated to keep this value current.

waitingParticipants()

call object mode only Returns a map of participants waiting in a knock-to-join lobby, keyed by their id. Use updateWaitingParticipant() to admit or deny them.
const waiting = call.waitingParticipants();
console.log(`${Object.keys(waiting).length} participants waiting`);
See the Waiting room guide for a full walkthrough including room configuration, event handling, and a complete example.

Updating Participants

updateParticipant(sessionId, options)

Send a change request for a single participant. Returns the DailyCall instance for chaining.
call.updateParticipant(
  sessionId: string,
  options: DailyParticipantUpdateOptions
): DailyCall
setAudio
boolean
Mute (false) or unmute (true) for the participant’s microphone. Only admins can mute remote participants’ audio. Note: while you can use this to mute/unmute the local participant, setLocalAudio() is the preferred method.
setVideo
boolean
Mute (false) or unmute (true) for the participant’s camera. Only admins can mute remote participants’ video. Note: while you can use this to mute/unmute the local participant, setLocalVideo() is the preferred method.
setScreenShare
false
Stop a remote participant’s screen share. Can only be set to false (you can only stop, not start, a remote screen share). Requires admin permissions.
setSubscribedTracks
DailyTrackSubscriptionOptions
Control which of this participant’s tracks the local client receives. See Track Subscription.
eject
true
Remove the participant from the call. Can only be set to true. Requires admin permissions.
updatePermissions
DailyParticipantPermissionsUpdate
Change the participant’s hasPresence, canSend, canReceive, or canAdmin permissions. Requires admin permissions.
styles
DailyParticipantCss
Prebuilt only Apply CSS overrides to this participant’s video tiles.

updateParticipants(updates)

Apply updates to multiple participants in a single call. This method takes the same options as updateParticipant() but in a map keyed by session_id. You can use '*' as a wildcard key to apply the same update to all remote participants.
call.updateParticipants({
  [sessionId: string]: DailyParticipantUpdateOptions;
}): DailyCall

Code Examples

// Mute a specific participant's mic (owner only)
call.updateParticipant(sessionId, { setAudio: false });

Participant Events

React to participant state changes by subscribing to these events:
EventFires when
participant-joinedA remote participant enters the room
participant-updatedAny field on a participant changes (mute, network quality, etc.)
participant-leftA remote participant leaves or is ejected
participant-counts-updatedThe aggregate counts returned by participantCounts() change
waiting-participant-addedA participant enters the knock-to-join lobby
waiting-participant-updatedA waiting participant’s state changes
waiting-participant-removedA waiting participant leaves the lobby or is admitted
call.on('participant-joined', ({ participant }) => {
  console.log(`${participant.user_name} joined`);
});

call.on('participant-updated', ({ participant }) => {
  const audioState = participant.tracks.audio.state;
  console.log(`${participant.user_name} audio is ${audioState}`);
});

call.on('participant-left', ({ participant, reason }) => {
  console.log(`${participant.user_name} left`, reason ?? 'normally');
});