diff --git a/resources/icons/hand_black_24dp.svg b/resources/icons/hand_black_24dp.svg
new file mode 100644
index 0000000000000000000000000000000000000000..17cdd02814eba7728d547497de8b9d70523ada8a
--- /dev/null
+++ b/resources/icons/hand_black_24dp.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
+<path d="M18,6.7L18,6.7c-0.2,0-0.7,0.1-0.8,0.2V5.5c0-1-0.5-1.9-1.5-1.9c-0.2,0-0.7,0-0.8,0.1C15,2.9,14.3,2,13.4,2l0,0
+	c-0.7,0-1.3,0.4-1.6,0.9C11,2.6,10,2.8,9.5,3.6c-0.2,0.3-0.3,0.6-0.3,1v9.8l-1-1c-0.8-0.8-2-1.1-3.1-0.7c-0.4,0.1-0.6,0.4-0.8,0.7
+	c-0.2,0.3-0.2,0.7-0.1,1.1c0,0.1,0.1,0.2,0.2,0.3l2.3,4c0.4,0.6,0.9,1.1,1.4,1.6c1,1.1,2.8,1.6,4.3,1.6l0,0h2c2.3,0,3.8-1.4,4.7-3.5
+	c0.2-0.6,0.4-1.2,0.4-1.9V8.5C19.5,7.8,19.2,6.9,18,6.7z M12.2,11.5c0.3,0,0.6-0.3,0.6-0.6v-7c0-0.3,0.2-0.5,0.5-0.5
+	s0.5,0.2,0.5,0.5v7.4c0,0.3,0.3,0.6,0.6,0.6s0.6-0.3,0.6-0.6V5.4c0-0.3,0.2-0.5,0.5-0.5S16,5.1,16,5.4V12c0,0.3,0.3,0.6,0.6,0.6
+	c0.3,0,0.6-0.3,0.6-0.6V8.5c0-0.3,0.2-0.5,0.5-0.5s0.5,0.2,0.5,0.5v8.1c0,0.5-0.1,0.9-0.3,1.4c-0.7,1.7-2.2,2.7-4,2.7l0,0H12
+	c-1.1,0-2.3-0.5-3.1-1.3c-0.5-0.5-0.9-1-1.2-1.6L5.5,14v-0.1c0,0,0-0.1,0.1-0.1c0.2-0.1,0.4-0.1,0.5-0.1c0.5,0,0.9,0.2,1.2,0.5
+	l1.2,1.2c0.4,0.4,1.2,0.4,1.6,0c0.2-0.2,0.3-0.5,0.3-0.8v-10C10.5,4.3,10.7,4,11,4s0.5,0.2,0.5,0.5v6.2
+	C11.5,11.2,11.8,11.5,12.2,11.5z M18,6.9L18,6.9L18,6.9L18,6.9z"/>
+</svg>
diff --git a/src/calladapter.cpp b/src/calladapter.cpp
index 42b2cc4aaca9843f3063ff996e9611c2b47abadf..73547d4551c3aca7108c1743e0fc3834b98fa6ad 100644
--- a/src/calladapter.cpp
+++ b/src/calladapter.cpp
@@ -842,6 +842,32 @@ CallAdapter::isModerator(const QString& uri) const
     return false;
 }
 
+bool
+CallAdapter::isHandRaised(const QString& uri) const
+{
+    auto* callModel = lrcInstance_->getAccountInfo(accountId_).callModel.get();
+    const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid_);
+    auto confId = convInfo.confId;
+
+    if (confId.isEmpty())
+        confId = convInfo.callId;
+    return callModel->isHandRaised(confId, uri);
+}
+
+void
+CallAdapter::setHandRaised(const QString& uri, bool state)
+{
+    auto* callModel = lrcInstance_->getAccountInfo(accountId_).callModel.get();
+    const auto& convInfo = lrcInstance_->getConversationFromConvUid(convUid_);
+    auto confId = convInfo.confId;
+    if (confId.isEmpty())
+        confId = convInfo.callId;
+    try {
+        callModel->setHandRaised(accountId_, confId, uri, state);
+    } catch (...) {
+    }
+}
+
 bool
 CallAdapter::isCurrentModerator() const
 {
diff --git a/src/calladapter.h b/src/calladapter.h
index 1187ef6c8af8a86615bbfd5d452a91ad8438db31..804e0dab3b4cdb9af000506cb62375675d0af317 100644
--- a/src/calladapter.h
+++ b/src/calladapter.h
@@ -67,6 +67,8 @@ public:
     Q_INVOKABLE bool participantIsHost(const QString& uri) const;
     Q_INVOKABLE void setModerator(const QString& uri, const bool state);
     Q_INVOKABLE bool isModerator(const QString& uri = {}) const;
+    Q_INVOKABLE bool isHandRaised(const QString& uri = {}) const;
+    Q_INVOKABLE void setHandRaised(const QString& uri, bool state);
     Q_INVOKABLE bool isCurrentModerator() const;
     Q_INVOKABLE void holdThisCallToggle();
     Q_INVOKABLE void muteThisCallToggle(bool mute);
diff --git a/src/constant/JamiStrings.qml b/src/constant/JamiStrings.qml
index 5e6cb5bd4631b97fab9c63fffbd8951571df36f3..a54d991f11c751335c39a020c012d57a398dded6 100644
--- a/src/constant/JamiStrings.qml
+++ b/src/constant/JamiStrings.qml
@@ -247,6 +247,8 @@ Item {
     property string viewPlugin: qsTr("View plugin")
     property string noVideoDevice: qsTr("No video device")
     property string notAvailable: qsTr("N/A")
+    property string lowerHand: qsTr("Lower hand")
+    property string raiseHand: qsTr("Raise hand")
 
     // Chatview header
     property string hideChatView: qsTr("Hide chat view")
diff --git a/src/mainview/components/CallActionBar.qml b/src/mainview/components/CallActionBar.qml
index 4d3e565350aaee1ce643ba35cd21c910882b54e7..3dcece67347c0911453e45efb04eb44d844ccf56 100644
--- a/src/mainview/components/CallActionBar.qml
+++ b/src/mainview/components/CallActionBar.qml
@@ -253,6 +253,17 @@ Control {
             property real size: 34
             property var menuAction: shareMenuAction
         },
+        Action {
+            id: raiseHandAction
+            onTriggered: CallAdapter.setHandRaised("", !CallAdapter.isHandRaised())
+            checkable: true
+            icon.source: JamiResources.hand_black_24dp_svg
+            icon.color: checked ? "red" : "white"
+            text: checked ?
+                      JamiStrings.lowerHand :
+                      JamiStrings.raiseHand
+            property real size: 34
+        },
         Action {
             id: recordAction
             onTriggered: CallAdapter.recordThisCallToggle()
@@ -288,6 +299,8 @@ Control {
         function onIsAudioMutedChanged() { reset() }
         function onIsVideoMutedChanged() { reset() }
         function onIsRecordingChanged() { reset() }
+        function onLocalHandRaisedChanged() { reset() }
+        function onIsConferenceCallChanged() { reset() }
     }
 
     function reset() {
@@ -300,6 +313,10 @@ Control {
 
         // overflow controls
         CallOverlayModel.addSecondaryControl(audioOutputAction)
+        if (isConferenceCall) {
+            CallOverlayModel.addSecondaryControl(raiseHandAction)
+            raiseHandAction.checked = CallAdapter.isHandRaised()
+        }
         if (isModerator && !isSIP)
             CallOverlayModel.addSecondaryControl(addPersonAction)
         if (isSIP) {
diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml
index f5334aa5db2d0ad9226794742079a02eae3633de..5ffec761e9c27e8e691408af209a51f9e28590a3 100644
--- a/src/mainview/components/CallOverlay.qml
+++ b/src/mainview/components/CallOverlay.qml
@@ -45,6 +45,7 @@ Item {
     property bool isModerator
     property bool isConferenceCall
     property bool isGrid
+    property bool localHandRaised
 
     signal chatButtonClicked
 
@@ -73,6 +74,7 @@ Item {
             root.isConferenceCall = isConferenceCall
             root.isGrid = isGrid
             mainOverlay.recordingVisible = isRecording
+            root.localHandRaised = CallAdapter.isHandRaised()
         }
         root.isModerator = CallAdapter.isCurrentModerator()
     }
diff --git a/src/mainview/components/ParticipantControlLayout.qml b/src/mainview/components/ParticipantControlLayout.qml
index e88061257d5caf90434d99932a201c5336bdb809..c88b092dee7e5a34ab0bd1c3787278aa584d1da3 100644
--- a/src/mainview/components/ParticipantControlLayout.qml
+++ b/src/mainview/components/ParticipantControlLayout.qml
@@ -84,6 +84,18 @@ RowLayout {
         toolTipText: JamiStrings.minimizeParticipant
     }
 
+    ParticipantOverlayButton {
+        id: lowerHandParticipant
+
+        visible: showLowerHand
+        preferredSize: iconButtonPreferredSize
+        Layout.preferredHeight: buttonPreferredSize
+        Layout.preferredWidth: buttonPreferredSize
+        source: JamiResources.hand_black_24dp_svg
+        onClicked: CallAdapter.setHandRaised(uri, false)
+        toolTipText: JamiStrings.lowerHand
+    }
+
     ParticipantOverlayButton {
         id: hangupParticipant
 
diff --git a/src/mainview/components/ParticipantOverlay.qml b/src/mainview/components/ParticipantOverlay.qml
index dd6ea64a2755d35c8c50e6ed38090532446b807c..42bd9e0bc10e10687883de00096f2ce4cf012416 100644
--- a/src/mainview/components/ParticipantOverlay.qml
+++ b/src/mainview/components/ParticipantOverlay.qml
@@ -46,6 +46,7 @@ Item {
     property bool participantIsModerator: false
     property bool participantIsMuted: false
     property bool participantIsModeratorMuted: false
+    property bool participantHandIsRaised: false
 
     z: 1
 
@@ -69,6 +70,7 @@ Item {
         participantIsHost = CallAdapter.participantIsHost(overlayMenu.uri)
         participantIsModerator = CallAdapter.isModerator(overlayMenu.uri)
         participantIsActive = isActive
+        participantHandIsRaised = CallAdapter.isHandRaised(overlayMenu.uri)
         overlayMenu.showSetModerator = isHost && !isLocal && !participantIsModerator
         overlayMenu.showUnsetModerator = isHost && !isLocal && participantIsModerator
 
@@ -85,6 +87,7 @@ Item {
         overlayMenu.showMaximize = isModerator && showMax
         overlayMenu.showMinimize = isModerator && participantIsActive
         overlayMenu.showHangup = isModerator && !isLocal && !participantIsHost
+        overlayMenu.showLowerHand = isModerator && participantHandIsRaised
     }
 
     // Participant header with host, moderator and mute indicators
@@ -156,6 +159,21 @@ Item {
                 source: JamiResources.mic_off_24dp_svg
                 color: JamiTheme.whiteColor
             }
+
+            ResponsiveImage {
+                id: isHandRaisedIndicator
+
+                Layout.alignment: Qt.AlignVCenter
+                Layout.leftMargin: 6
+
+                containerHeight: 12
+                containerWidth: 12
+
+                visible: participantHandIsRaised
+
+                source: JamiResources.hand_black_24dp_svg
+                color: JamiTheme.whiteColor
+            }
         }
     }
 
diff --git a/src/mainview/components/ParticipantOverlayMenu.qml b/src/mainview/components/ParticipantOverlayMenu.qml
index c72aeee519c47618bb48e20e4dd1be57ed6b7ee0..a69608716ce1d04998f76791a84c88ac49cdd429 100644
--- a/src/mainview/components/ParticipantOverlayMenu.qml
+++ b/src/mainview/components/ParticipantOverlayMenu.qml
@@ -40,6 +40,7 @@ Item {
     property bool showMaximize: false
     property bool showMinimize: false
     property bool showHangup: false
+    property bool showLowerHand: false
 
     property int shapeHeight: 30
     property int shapeRadius: 8