diff --git a/briar-gtk/briar_gtk/containers/private_chat.py b/briar-gtk/briar_gtk/containers/private_chat.py
index dc5109f2dd731aeaec9879c86ddce0eb14679811..0600ca09fef883a6148709d796f6712817553479 100644
--- a/briar-gtk/briar_gtk/containers/private_chat.py
+++ b/briar-gtk/briar_gtk/containers/private_chat.py
@@ -99,6 +99,8 @@ class PrivateChatContainer(Container):
             # Abusing idle_add function here because otherwise the message box
             # is too small and scrolling cuts out messages
             GLib.idle_add(self._add_message, message)
+            if message.get("read", True) is False:
+                GLib.idle_add(private_chat.mark_read, message["id"])
         socket_listener = APP().api.socket_listener
         signal_id = socket_listener.connect("ConversationMessageReceivedEvent",
                                             self._add_message_async)
@@ -120,8 +122,12 @@ class PrivateChatContainer(Container):
         return "text" not in message
 
     def _add_message_async(self, message):
-        if message["data"]["contactId"] == self._contact_id:
-            GLib.idle_add(self._add_message_and_scroll, message["data"])
+        if message["data"]["contactId"] != self._contact_id:
+            return
+        GLib.idle_add(self._add_message_and_scroll, message["data"])
+        if message["data"].get("read", True) is False:
+            private_chat = PrivateChat(APP().api, self._contact_id)
+            GLib.idle_add(private_chat.mark_read, message["data"]["id"])
 
     def _add_message_and_scroll(self, message):
         self._add_message(message)
diff --git a/briar-gtk/briar_gtk/widgets/contact_row.py b/briar-gtk/briar_gtk/widgets/contact_row.py
index 41b4784ae5382571bf8b8c1b9bd3db9bf46adba8..75c8c527751efc491d6bdbb6855883aab958b6ad 100644
--- a/briar-gtk/briar_gtk/widgets/contact_row.py
+++ b/briar-gtk/briar_gtk/widgets/contact_row.py
@@ -17,6 +17,10 @@ class ContactRowWidget(Gtk.ListBoxRow):
     def _setup_view(self, contact):
         name = ContactRowWidget._get_contact_name(contact)
         contact_label = ContactRowWidget._create_contact_label(name)
+        unread_count = contact['unreadCount']
+        contact_unread_count = ContactRowWidget._create_unread_count(
+            unread_count
+        )
         connected = contact["connected"]
         contact_state = ContactRowWidget._create_contact_state(connected)
         contact_box = ContactRowWidget._create_contact_box()
@@ -24,6 +28,7 @@ class ContactRowWidget(Gtk.ListBoxRow):
 
         contact_box.pack_start(contact_label, True, True, 0)
         contact_box.pack_end(contact_state, False, False, 0)
+        contact_box.pack_end(contact_unread_count, False, False, 0)
         contact_event_box.add(contact_box)
         self.add(contact_event_box)
 
@@ -45,6 +50,14 @@ class ContactRowWidget(Gtk.ListBoxRow):
         contact_label.set_ellipsize(Pango.EllipsizeMode.END)
         return contact_label
 
+    @staticmethod
+    def _create_unread_count(unread_count):
+        if unread_count == 0:
+            return Gtk.EventBox()
+        return ContactRowWidget._create_contact_label(
+            f" ({unread_count})"
+        )
+
     @staticmethod
     def _create_contact_state(connected):
         file_name = "contact_disconnected"