diff --git a/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js b/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js
index d6cec7522514f00983440519f9f50ab37cb6825b..b573f8d4b0a1cb835e43f3d4681a431fba8bb91d 100755
--- a/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js
+++ b/bigbluebutton-html5/imports/api/audio/client/bridge/sip.js
@@ -1,4 +1,4 @@
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import BaseAudioBridge from './base';
 import logger from '/imports/startup/client/logger';
 import {
@@ -1007,9 +1007,7 @@ class SIPSession {
       const matchConstraints = this.filterSupportedConstraints(constraints);
 
       //Chromium bug - see: https://bugs.chromium.org/p/chromium/issues/detail?id=796964&q=applyConstraints&can=2
-      const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-
-      if (BROWSER_RESULTS.browser.name === 'Chrome') {
+      if (browser().name === 'chrome') {
         matchConstraints.deviceId = this.inputDeviceId;
 
         const stream = await navigator.mediaDevices.getUserMedia(
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx
index f92d6ab4ade256d17585126e3ef9c41d56b4e31d..bd336850491e17d239e62fe4cdc89e24ce7847ec 100755
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/create-breakout-room/component.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
 import _ from 'lodash';
 import cx from 'classnames';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import Button from '/imports/ui/components/button/component';
 import { Session } from 'meteor/session';
 import Modal from '/imports/ui/components/modal/fullscreen/component';
@@ -807,8 +807,8 @@ class BreakoutRoom extends PureComponent {
       numberOfRoomsIsValid,
     } = this.state;
 
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-    const isMobileBrowser = BROWSER_RESULTS.platform.type === 'mobile' || BROWSER_RESULTS.os.name.includes('Android');
+    const BROWSER_RESULTS = browser();
+    const isMobileBrowser = BROWSER_RESULTS.mobile || BROWSER_RESULTS.os.includes('Android');
 
     return (
       <Modal
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/screenshare/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/screenshare/component.jsx
index fbb975d891e969cf6695602bc68aafff9754f414..64dc749da3acd1d22649ee19fe1e38035063c73f 100755
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/screenshare/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/screenshare/component.jsx
@@ -1,7 +1,7 @@
 import React, { memo } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import Button from '/imports/ui/components/button/component';
 import logger from '/imports/startup/client/logger';
 import { notify } from '/imports/ui/services/notification';
@@ -19,9 +19,12 @@ import {
 } from '/imports/ui/components/screenshare/service';
 import { SCREENSHARING_ERRORS } from '/imports/api/screenshare/client/bridge/errors';
 
-const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-const isMobileBrowser = BROWSER_RESULTS.platform.type === 'mobile' || BROWSER_RESULTS.os.name.includes('Android');
-const IS_SAFARI = BROWSER_RESULTS.browser.name === 'Safari';
+const BROWSER_RESULTS = browser();
+const isMobileBrowser = (BROWSER_RESULTS ? BROWSER_RESULTS.mobile : false)
+  || (BROWSER_RESULTS && BROWSER_RESULTS.os
+    ? BROWSER_RESULTS.os.includes('Android') // mobile flag doesn't always work
+    : false);
+const IS_SAFARI = BROWSER_RESULTS.name === 'safari';
 
 const propTypes = {
   intl: PropTypes.objectOf(Object).isRequired,
diff --git a/bigbluebutton-html5/imports/ui/components/app/component.jsx b/bigbluebutton-html5/imports/ui/components/app/component.jsx
index 61dcfa8cfb350c0098b957ee0dc0a64ec76e2508..890d75a857dcc36b44530afbbb3decbb6fd73132 100755
--- a/bigbluebutton-html5/imports/ui/components/app/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/app/component.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import { throttle } from 'lodash';
 import { defineMessages, injectIntl } from 'react-intl';
 import Modal from 'react-modal';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import PanelManager from '/imports/ui/components/panel-manager/component';
 import PollingContainer from '/imports/ui/components/polling/container';
 import logger from '/imports/startup/client/logger';
@@ -124,8 +124,8 @@ class App extends Component {
     const {
       locale, notify, intl, validIOSVersion, startBandwidthMonitoring, handleNetworkConnection,
     } = this.props;
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-    const isMobileBrowser = BROWSER_RESULTS.platform.type === 'mobile' || BROWSER_RESULTS.os.name.includes('Android');
+    const BROWSER_RESULTS = browser();
+    const isMobileBrowser = BROWSER_RESULTS.mobile || BROWSER_RESULTS.os.includes('Android');
 
     MediaService.setSwapLayout();
     Modal.setAppElement('#app');
@@ -133,11 +133,11 @@ class App extends Component {
     document.getElementsByTagName('html')[0].style.fontSize = isMobileBrowser ? MOBILE_FONT_SIZE : DESKTOP_FONT_SIZE;
 
     const body = document.getElementsByTagName('body')[0];
-    if (BROWSER_RESULTS && BROWSER_RESULTS.browser.name) {
-      body.classList.add(`browser-${BROWSER_RESULTS.browser.name.toLowerCase()}`);
+    if (BROWSER_RESULTS && BROWSER_RESULTS.name) {
+      body.classList.add(`browser-${BROWSER_RESULTS.name}`);
     }
-    if (BROWSER_RESULTS && BROWSER_RESULTS.os.name) {
-      body.classList.add(`os-${BROWSER_RESULTS.os.name.split(' ').shift().toLowerCase()}`);
+    if (BROWSER_RESULTS && BROWSER_RESULTS.os) {
+      body.classList.add(`os-${BROWSER_RESULTS.os.split(' ').shift().toLowerCase()}`);
     }
 
     if (!validIOSVersion()) {
diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx
index 10e8f137a13faf2f234f3b2ab0a563eb13fb15d5..7c6e2c8f3bd0f5695e995ddcb07f4376f5353e8e 100755
--- a/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import { withTracker } from 'meteor/react-meteor-data';
 import { withModalMounter } from '/imports/ui/components/modal/service';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import getFromUserSettings from '/imports/ui/services/users-settings';
 import AudioModal from './component';
 import Meetings from '/imports/api/meetings';
@@ -55,7 +55,6 @@ export default lockContextContainer(withModalMounter(withTracker(({ userLocks })
     || (skipCheck || skipCheckOnJoin && !getEchoTest);
 
   const forceListenOnlyAttendee = forceListenOnly && !Service.isUserModerator();
-  const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
 
   return ({
     joinedAudio,
@@ -81,9 +80,9 @@ export default lockContextContainer(withModalMounter(withTracker(({ userLocks })
     audioLocked: userLocks.userMic,
     joinFullAudioImmediately,
     forceListenOnlyAttendee,
-    isIOSChrome: BROWSER_RESULTS.os.name.includes('iOS') && BROWSER_RESULTS.browser.name === 'Chrome',
+    isIOSChrome: browser().name === 'crios',
     isMobileNative: navigator.userAgent.toLowerCase().includes('bbbnative'),
-    isIEOrEdge: BROWSER_RESULTS.browser.name === 'Microsoft Edge' || BROWSER_RESULTS.browser.name === 'Internet Explorer',
+    isIEOrEdge: browser().name === 'edge' || browser().name === 'ie',
     autoplayBlocked: Service.autoplayBlocked(),
     handleAllowAutoplay: () => Service.handleAllowAutoplay(),
     isRTL,
diff --git a/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx
index ff1b4b21851b23698a3016f9c31e0d079da4dfec..152a71794e4411011ff2a01e411805916c7ca1c3 100644
--- a/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/audio/device-selector/component.jsx
@@ -3,7 +3,7 @@ import _ from 'lodash';
 import PropTypes from 'prop-types';
 import cx from 'classnames';
 import logger from '/imports/startup/client/logger';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import { styles } from '../audio-modal/styles';
 
 const propTypes = {
@@ -82,7 +82,6 @@ class DeviceSelector extends Component {
     } = this.props;
 
     const { options, value } = this.state;
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
 
     return (
       <select
@@ -103,7 +102,7 @@ class DeviceSelector extends Component {
               </option>
             ))
             : (
-              (kind === 'audiooutput' && BROWSER_RESULTS.browser.name === 'Safari')
+              (kind === 'audiooutput' && browser().name === 'safari')
                 ? <option value="not-found">Default</option>
                 : <option value="not-found">{`no ${kind} found`}</option>
             )
diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx
index 5d41e8194b2434dde1fe0cfac52ab06fc5dac2e6..662ebce99b7df10287ce8af3480d5af1725126cb 100755
--- a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx
@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
 import { defineMessages, injectIntl } from 'react-intl';
 import cx from 'classnames';
 import TextareaAutosize from 'react-autosize-textarea';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import PropTypes from 'prop-types';
 import _ from 'lodash';
 import TypingIndicatorContainer from './typing-indicator/container';
@@ -80,7 +80,7 @@ class MessageForm extends PureComponent {
       hasErrors: false,
     };
 
-    this.BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
+    this.BROWSER_RESULTS = browser();
 
     this.handleMessageChange = this.handleMessageChange.bind(this);
     this.handleMessageKeyDown = this.handleMessageKeyDown.bind(this);
@@ -91,7 +91,7 @@ class MessageForm extends PureComponent {
   }
 
   componentDidMount() {
-    const mobile = this.BROWSER_RESULTS.platform.type === 'mobile';
+    const { mobile } = this.BROWSER_RESULTS;
     this.setMessageState();
     this.setMessageHint();
 
@@ -108,7 +108,7 @@ class MessageForm extends PureComponent {
       partnerIsLoggedOut,
     } = this.props;
     const { message } = this.state;
-    const mobile = this.BROWSER_RESULTS.platform.type === 'mobile';
+    const { mobile } = this.BROWSER_RESULTS;
 
     if (prevProps.chatId !== chatId && !mobile) {
       if (this.textarea) this.textarea.focus();
diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx
index 08024cbaac08f00a7cb62392d17d0cd14a70d4f4..b379f75af8054046c04c615b2ebfc0391047c809 100644
--- a/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/typing-indicator/component.jsx
@@ -2,6 +2,7 @@ import React, { PureComponent } from 'react';
 import {
   defineMessages, injectIntl, FormattedMessage,
 } from 'react-intl';
+import browser from 'browser-detect';
 import PropTypes from 'prop-types';
 import cx from 'classnames';
 import { styles } from '../styles.scss';
@@ -22,6 +23,8 @@ class TypingIndicator extends PureComponent {
   constructor(props) {
     super(props);
 
+    this.BROWSER_RESULTS = browser();
+
     this.renderTypingElement = this.renderTypingElement.bind(this);
   }
 
diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx
index 1c2a03b181c1be8ec964c2ff92e0acff8c2c8dd5..e21f0ccf0c8b305eddf49080ff6ccb0afb7c625b 100755
--- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx
@@ -1,18 +1,14 @@
 import React from 'react';
 import { withTracker } from 'meteor/react-meteor-data';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import SettingsDropdown from './component';
 import FullscreenService from '../../fullscreen-button/service';
 import { meetingIsBreakout } from '/imports/ui/components/app/service';
 
-const BROWSER_RESULTS = Bowser.getParser(window.navigator.userAgent);
-const isSafari = BROWSER_RESULTS.getBrowserName() === 'Safari';
-const isIphone = !!(navigator.userAgent.match(/iPhone/i));
-const isValidBrowserVersion = BROWSER_RESULTS.satisfies({
-  safari: '>12',
-});
-
-const noIOSFullscreen = !!(((isSafari && !isValidBrowserVersion) || isIphone));
+const BROWSER_RESULTS = browser();
+const isSafari = BROWSER_RESULTS.name === 'safari';
+const isIphone = (navigator.userAgent.match(/iPhone/i)) ? true : false;
+const noIOSFullscreen = ((isSafari && BROWSER_RESULTS.versionNumber < 12) || isIphone) ? true : false;
 
 const SettingsDropdownContainer = props => (
   <SettingsDropdown {...props} />
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx
index 3e6940c0f49da3365b9841b24113622c03e2d0d4..473ec85b88e13e09fcf1fed2b239c7b19a8f43e7 100755
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-toolbar/component.jsx
@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
 import Button from '/imports/ui/components/button/component';
 import { HUNDRED_PERCENT, MAX_PERCENT, STEP } from '/imports/utils/slideCalcUtils';
@@ -225,8 +225,9 @@ class PresentationToolbar extends PureComponent {
       currentSlide,
     } = this.props;
 
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-    const isMobileBrowser = BROWSER_RESULTS.platform.type === 'mobile' || BROWSER_RESULTS.os.name.includes('Android');
+    const BROWSER_RESULTS = browser();
+    const isMobileBrowser = BROWSER_RESULTS.mobile
+      || BROWSER_RESULTS.os.includes('Android');
 
     const startOfSlides = !(currentSlideNum > 1);
     const endOfSlides = !(currentSlideNum < numberOfSlides);
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
index c84164a1451dda642f1c2b74904f8e7181dd18e5..d36e1f784743893380dca3ae10a633db8b11c3f6 100755
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
@@ -10,12 +10,15 @@ import update from 'immutability-helper';
 import logger from '/imports/startup/client/logger';
 import { notify } from '/imports/ui/services/notification';
 import { toast } from 'react-toastify';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import _ from 'lodash';
 import { styles } from './styles';
 
-const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-const isMobileBrowser = BROWSER_RESULTS.platform.type === 'mobile' || BROWSER_RESULTS.os.name.includes('Android');
+const BROWSER_RESULTS = browser();
+const isMobileBrowser = (BROWSER_RESULTS ? BROWSER_RESULTS.mobile : false)
+  || (BROWSER_RESULTS && BROWSER_RESULTS.os
+    ? BROWSER_RESULTS.os.includes('Android') // mobile flag doesn't always work
+    : false);
 
 const propTypes = {
   intl: PropTypes.object.isRequired,
diff --git a/bigbluebutton-html5/imports/ui/components/shortcut-help/component.jsx b/bigbluebutton-html5/imports/ui/components/shortcut-help/component.jsx
index f443c1ab0b416bd9165b78f15ee0950562ba74f3..a55b0c8417c270abecebd39f97bce1065a73f05e 100644
--- a/bigbluebutton-html5/imports/ui/components/shortcut-help/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/shortcut-help/component.jsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import Modal from '/imports/ui/components/modal/simple/component';
 import _ from 'lodash';
 import { styles } from './styles';
@@ -103,10 +103,7 @@ const CHAT_ENABLED = CHAT_CONFIG.enabled;
 
 const ShortcutHelpComponent = (props) => {
   const { intl, shortcuts } = props;
-
-  const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-  const name = BROWSER_RESULTS.browser.name;
-  const os = BROWSER_RESULTS.os.name;
+  const { name, os } = browser();
 
   let accessMod = null;
 
@@ -114,24 +111,24 @@ const ShortcutHelpComponent = (props) => {
   // on different systems when using accessKey property.
   // Overview how different browsers behave: https://www.w3schools.com/jsref/prop_html_accesskey.asp
   switch (name) {
-    case 'Chrome':
-    case 'Microsoft Edge':
+    case 'chrome':
+    case 'edge':
       accessMod = 'Alt';
       break;
-    case 'Firefox':
+    case 'firefox':
       accessMod = 'Alt + Shift';
       break;
+    case 'safari':
+    case 'crios':
+    case 'fxios':
+      accessMod = 'Control + Alt';
+      break;
     default:
       break;
   }
 
-  // all Browsers on iOS are using Control + Alt as access modifier
-  if (os.includes('iOS')) {
-    accessMod = 'Control + Alt';
-  }
-
   // all Browsers on MacOS are using Control + Option as access modifier
-  if (os.includes('MacOS')) {
+  if (os.includes('OS X 10')) {
     accessMod = 'Control + Option';
   }
 
diff --git a/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx b/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx
index 28be431f96a655df989c6fceb6368f6d640ec149..fed89b40d6957a069acfb81d6c3a3a7236a5d0c7 100755
--- a/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx
@@ -4,9 +4,10 @@ import {
   defineMessages, injectIntl, FormattedMessage,
 } from 'react-intl';
 import Button from '/imports/ui/components/button/component';
+// import { notify } from '/imports/ui/services/notification';
 import logger from '/imports/startup/client/logger';
 import Modal from '/imports/ui/components/modal/simple/component';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import cx from 'classnames';
 import Service from './service';
 import VideoService from '../video-provider/service';
@@ -650,11 +651,10 @@ class VideoPreview extends Component {
     const shouldDisableButtons = this.skipVideoPreview && !(deviceError || previewError);
 
     const shared = sharedDevices.includes(webcamDeviceId);
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
 
     return (
       <div>
-        {BROWSER_RESULTS.browser.name === 'Microsoft Edge' || BROWSER_RESULTS.browser.name === 'Internet Explorer' ? (
+        {browser().name === 'edge' || browser().name === 'ie' ? (
           <p className={styles.browserWarning}>
             <FormattedMessage
               id="app.audioModal.unsupportedBrowserLabel"
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/service.js b/bigbluebutton-html5/imports/ui/components/video-provider/service.js
index 63ad5db884f16cdce476d66f174e64db88c931ae..05e0196d817ede7a0453919c9f7f54289e631200 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/service.js
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/service.js
@@ -9,7 +9,7 @@ import UserListService from '/imports/ui/components/user-list/service';
 import { makeCall } from '/imports/ui/services/api';
 import { notify } from '/imports/ui/services/notification';
 import { monitorVideoConnection } from '/imports/utils/stats';
-import Bowser from "bowser";
+import browser from 'browser-detect';
 import getFromUserSettings from '/imports/ui/services/users-settings';
 import VideoPreviewService from '../video-preview/service';
 import Storage from '/imports/ui/services/storage/session';
@@ -70,9 +70,9 @@ class VideoService {
       pageSize: 0,
     });
     this.userParameterProfile = null;
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-    this.isMobile = BROWSER_RESULTS.platform.type === "mobile" || BROWSER_RESULTS.os.name.includes('Android');
-    this.isSafari = BROWSER_RESULTS.browser.name === 'Safari';
+    const BROWSER_RESULTS = browser();
+    this.isMobile = BROWSER_RESULTS.mobile || BROWSER_RESULTS.os.includes('Android');
+    this.isSafari = BROWSER_RESULTS.name === 'safari';
     this.numberOfDevices = 0;
 
     this.record = null;
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
index 75f42212f72e82105f5245713f20ca3894dac758..21bb8333bdd9683277a297479f1ba7b4685cf3db 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
@@ -1,5 +1,5 @@
 import React, { Component } from 'react';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import { Meteor } from 'meteor/meteor';
 import PropTypes from 'prop-types';
 import _ from 'lodash';
@@ -179,8 +179,8 @@ class VideoListItem extends Component {
     const enableVideoMenu = Meteor.settings.public.kurento.enableVideoMenu || false;
     const shouldRenderReconnect = !isStreamHealthy && videoIsReady;
 
-    const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-    const isFirefox = BROWSER_RESULTS.browser.name.includes('Firefox');
+    const result = browser();
+    const isFirefox = (result && result.name) ? result.name.includes('firefox') : false;
 
     return (
       <div data-test={voiceUser.talking ? 'webcamItemTalkingUser' : 'webcamItem'} className={cx({
diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx
index b0e7f0c57c8db23bf8040c540f1c597cc4ece783..f776cc807be11d89199614684374b80706406e4e 100755
--- a/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/whiteboard/whiteboard-toolbar/component.jsx
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import cx from 'classnames';
 import { HEXToINTColor, INTToHEXColor } from '/imports/utils/hexInt';
 import { defineMessages, injectIntl } from 'react-intl';
-import Bowser from 'bowser';
+import browser from 'browser-detect';
 import { noop } from 'lodash';
 import KEY_CODES from '/imports/utils/keyCodes';
 import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
@@ -64,9 +64,7 @@ const intlMessages = defineMessages({
   },
 });
 
-const BROWSER_RESULTS = Bowser.parse(window.navigator.userAgent);
-const isEdge = BROWSER_RESULTS.browser.name === 'Microsoft Edge';
-
+const isEdge = browser().name === 'edge';
 const runExceptInEdge = fn => (isEdge ? noop : fn);
 
 class WhiteboardToolbar extends Component {
diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json
index 554c525d2afd38f2051b81e9ac4284f169498403..af01ac900518db48e3fcb84f2f0b244e1c94ac9e 100644
--- a/bigbluebutton-html5/package-lock.json
+++ b/bigbluebutton-html5/package-lock.json
@@ -2015,11 +2015,6 @@
         "inherits": "~2.0.0"
       }
     },
-    "bowser": {
-      "version": "2.11.0",
-      "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
-      "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
-    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -2049,6 +2044,14 @@
         "@browser-bunyan/levels": "^1.6.0"
       }
     },
+    "browser-detect": {
+      "version": "0.2.28",
+      "resolved": "https://registry.npmjs.org/browser-detect/-/browser-detect-0.2.28.tgz",
+      "integrity": "sha512-KeWGHqYQmHDkCFG2dIiX/2wFUgqevbw/rd6wNi9N6rZbaSJFtG5kel0HtprRwCGp8sqpQP79LzDJXf/WCx4WAw==",
+      "requires": {
+        "core-js": "^2.5.7"
+      }
+    },
     "browser-or-node": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz",
diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json
index 6102ddb69bb45883d88c1cad3d30bf1095af31d1..257e4063c26cc83f75cc3fbaba9bb24ad1f46868 100755
--- a/bigbluebutton-html5/package.json
+++ b/bigbluebutton-html5/package.json
@@ -35,8 +35,8 @@
     "autoprefixer": "~9.3.1",
     "axios": "^0.21.1",
     "babel-runtime": "~6.26.0",
-    "bowser": "^2.11.0",
     "browser-bunyan": "^1.6.3",
+    "browser-detect": "^0.2.28",
     "classnames": "^2.2.6",
     "clipboard": "^2.0.8",
     "crypto-js": "^4.0.0",