Handling device permissions
Accessing media input devices — cams, mics, and screens — can involve many and sometimes conflicting permissions layers. Browsers, operating systems, devices, and participants are all factors that can complicate whether audio or video is shared or hidden as desired.
This guide walks through common media device errors and how to help call participants resolve them, and then covers general best practices for handling media devices.
Daily accesses participant media input devices through the
If something goes wrong, the browser throws an
and Daily emits a
event. Browsers are inconsistent in their implementations of these exceptions for any
given root issue. For example, if there is no camera plugged in, Chrome and
Firefox will throw a
NotFoundError, but Safari will throw an
OverconstrainedError. For this reason, we handle these inconsistencies for you
and categorize the errors into basic types to ensure that the same issue will
generate the same error no matter which browser or OS the user is on. The most
common device errors are detailed below and include recommendations for how to handle each
type of error. For full details about all the categories of device errors, see the
This is most common on Windows when another app is using the participant's camera.
camera-error event object's
error.type value will specify one of the following:
cam-mic-in-use. For example:
To handle this error, alert participants that another application is using their device. Daily Prebuilt, for example, instructs participants to quit the other application and reload the Daily call.
This happens when the call is not granted permissions to access the user's media
device. Either a participant has denied access (e.g. clicked "Block" in the
permissions pop-up) or the browser itself has not been granted access in the OS
settings. This is one of the most common
error.type value will be set to
'permissions'. Whether the
permissions were blocked by a user action or due to OS level permissions will be
specified in the
error.blockedBy field. There is also an
field to indicate which media is blocked due to permissions. For example:
Whether the participant denied access on purpose or by accident, it is important that the call UI reflects that the device is blocked. In Daily Prebuilt, the media icons are displayed in red with the text "Allow" underneath. When clicked, the participant sees instructions for how to unblock their devices.
How to unblock a device can depend on the device's manufacturer and the browser that the participant is using. On some devices, such as iOS, a page refresh is enough to re-trigger the browser prompt asking for device access. On other devices, such as some Android phones, participants may need to go into their device's settings to allow camera and microphone permissions. Testing on multiple devices and browsers is recommended.
If the browser can't find any input devices for a given type of media, the Daily
error.type value will be
"not-found". It will also include an
error.missingMedia field detailing which devices were not found. For example:
Prompting the participants to check their devices and reload the call can help solve this issue; that is how Daily Prebuilt handles it.
It is critical to ask call participants for microphone and camera access at the same time. These device permissions are closely related at a low level in
daily-js. Blocking one can unintentionally block the other. Prompting for both cam and mic permissions simultaneously not only prevents this error, but also is a better user experience because participants only have to answer one prompt.
Device manufacturers and browsers don't always handle device permissions in the same way. For example, allowing device access after the browser has thrown a permissions error can differ per OS, device, and browser. For the best user experience, the call UI should reflect how to handle the error given the participant's device and browser. Daily Prebuilt, for example, shows a different access prompt on iOS and Android after a permissions error:
You can use user agent detection to display information based on the user's device. At Daily, we use ua-parser-js to detect the user's browser and OS, so we can adjust our messaging accordingly.
A test call page, lobby, "green room" or a space by any other name where participants can set up their devices before joining a call provides a safe space for callers to read all prompts, accept or deny them, and configure their devices without the pressure of being live in a call. This also gives them the chance to resolve any unintended mistakes before entering the call.
To enable Daily Prebuilt's prejoin UI, set the
enable_prejoin_ui property to
true at either the room or the domain level. This can be done either through an API request, or from the "Create room" page of the Daily dashboard.
There are lots of ways to go about building a lobby in a custom application. The
startCamera() method is a good place to start.
daily-js assumes that calls start with microphones and cameras turned on, and automatically asks for permissions to both.
If a participant blocks the request, the event emitter fires a
camera-error event. Access to both devices is denied, so for the duration of the session, neither the microphone nor the camera will be accessible. This might not be what a participant wants. They might want to join the call with audio-only access (granting microphone permissions), for example, but block the camera entirely. To enable a participant to join a call with mic access granted but camera blocked:
- Turn off Daily's default automatic permissions request by setting the
trueat the room or the token level.
daily-jsto access participants' media streams.
- Pass the streams to Daily. This can be done either via
join(), using the
videoSourceproperties, or after join through
These permissions should never be blocked, as that can lead to deadlocks. An API that was intended to be synchronous and blocking may have to be changed to be async with a callback block when adapted for iOS.