diff --git a/libempathy-gtk/empathy-cell-renderer-text.c b/libempathy-gtk/empathy-cell-renderer-text.c
index f64ee6b..910b5ab 100644
--- a/libempathy-gtk/empathy-cell-renderer-text.c
+++ b/libempathy-gtk/empathy-cell-renderer-text.c
@@ -38,6 +38,8 @@ typedef struct {
 	gboolean  is_valid;
 	gboolean  is_selected;
 
+	gchar   **types;
+
 	gboolean  compact;
 } EmpathyCellRendererTextPriv;
 
@@ -67,7 +69,8 @@ enum {
 	PROP_PRESENCE_TYPE,
 	PROP_STATUS,
 	PROP_IS_GROUP,
-	PROP_COMPACT
+	PROP_COMPACT,
+	PROP_CLIENT_TYPES
 };
 
 G_DEFINE_TYPE (EmpathyCellRendererText, empathy_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT);
@@ -137,6 +140,11 @@ empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass *klass)
 		FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 	g_object_class_install_property (object_class, PROP_COMPACT, spec);
 
+	spec = g_param_spec_boxed ("client-types", "Contact client types",
+		"Client types of the contact",
+		G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+	g_object_class_install_property (object_class, PROP_CLIENT_TYPES, spec);
+
 	g_type_class_add_private (object_class, sizeof (EmpathyCellRendererTextPriv));
 }
 
@@ -167,6 +175,7 @@ cell_renderer_text_finalize (GObject *object)
 
 	g_free (priv->name);
 	g_free (priv->status);
+	g_strfreev (priv->types);
 
 	(G_OBJECT_CLASS (empathy_cell_renderer_text_parent_class)->finalize) (object);
 }
@@ -199,6 +208,9 @@ cell_renderer_text_get_property (GObject    *object,
 	case PROP_COMPACT:
 		g_value_set_boolean (value, priv->compact);
 		break;
+	case PROP_CLIENT_TYPES:
+		g_value_set_boxed (value, priv->types);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
@@ -245,6 +257,10 @@ cell_renderer_text_set_property (GObject      *object,
 		priv->compact = g_value_get_boolean (value);
 		priv->is_valid = FALSE;
 		break;
+	case PROP_CLIENT_TYPES:
+		priv->types = g_value_dup_boxed (value);
+		priv->is_valid = FALSE;
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
@@ -282,7 +298,7 @@ cell_renderer_text_update_text (EmpathyCellRendererText *cell,
 {
 	EmpathyCellRendererTextPriv *priv;
 	PangoAttrList              *attr_list;
-	PangoAttribute             *attr_color, *attr_size;
+	PangoAttribute             *attr_color = NULL, *attr_size;
 	GtkStyle                   *style;
 	gchar                      *str;
 
@@ -335,15 +351,27 @@ cell_renderer_text_update_text (EmpathyCellRendererText *cell,
 		}
 	} else {
 		const gchar *status = priv->status;
+		gboolean on_a_phone = FALSE;
 
 		if (EMP_STR_EMPTY (priv->status)) {
 			status = empathy_presence_get_default_message (priv->presence_type);
 		}
 
+		if (!priv->is_group && priv->types != NULL && g_strv_length (priv->types) > 0
+		    // FIXME: why don't we check the whole array?
+		    && !tp_strdiff (priv->types[0], "phone")) {
+			on_a_phone = TRUE;
+			/* We want the phone black. */
+			if (attr_color)
+				attr_color->start_index += 3;
+		}
+
 		if (status == NULL)
 			str = g_strdup (priv->name);
 		else
-			str = g_strdup_printf ("%s\n%s", priv->name, status);
+			str = g_strdup_printf ("%s\n%s%s", priv->name,
+					       on_a_phone ? "☎  " : "",
+					       status);
 	}
 
 	g_object_set (cell,
diff --git a/libempathy-gtk/empathy-contact-list-store.h b/libempathy-gtk/empathy-contact-list-store.h
index 1760a00..b68a274 100644
--- a/libempathy-gtk/empathy-contact-list-store.h
+++ b/libempathy-gtk/empathy-contact-list-store.h
@@ -65,6 +65,7 @@ typedef enum {
 	EMPATHY_CONTACT_LIST_STORE_COL_CAN_VIDEO_CALL,
 	EMPATHY_CONTACT_LIST_STORE_COL_FLAGS,
 	EMPATHY_CONTACT_LIST_STORE_COL_IS_FAKE_GROUP,
+	EMPATHY_CONTACT_LIST_STORE_COL_CLIENT_TYPES,
 	EMPATHY_CONTACT_LIST_STORE_COL_COUNT,
 } EmpathyContactListStoreCol;
 
diff --git a/libempathy-gtk/empathy-individual-store.c b/libempathy-gtk/empathy-individual-store.c
index 807afb2..ce2eacf 100644
--- a/libempathy-gtk/empathy-individual-store.c
+++ b/libempathy-gtk/empathy-individual-store.c
@@ -154,6 +154,39 @@ individual_can_audio_video_call (FolksIndividual *individual,
   *can_video_call = can_video;
 }
 
+static const gchar * const *
+individual_get_client_types (FolksIndividual *individual)
+{
+  GList *personas, *l;
+  const gchar * const *types = NULL;
+  FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET;
+
+  personas = folks_individual_get_personas (individual);
+  for (l = personas; l != NULL; l = l->next)
+    {
+      FolksPresence *presence;
+
+      /* We only want personas which implement FolksPresence */
+      if (!FOLKS_IS_PRESENCE (l->data))
+        continue;
+
+      presence = FOLKS_PRESENCE (l->data);
+
+      if (folks_presence_typecmp (folks_presence_get_presence_type (presence),
+              presence_type) > 0)
+        {
+          TpContact *tp_contact;
+
+          presence_type = folks_presence_get_presence_type (presence);
+
+          tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
+          types = tp_contact_get_client_types (tp_contact);
+        }
+    }
+
+  return types;
+}
+
 static void
 add_individual_to_store (GtkTreeStore *self,
     GtkTreeIter *iter,
@@ -161,10 +194,13 @@ add_individual_to_store (GtkTreeStore *self,
     FolksIndividual *individual)
 {
   gboolean can_audio_call, can_video_call;
+  const gchar * const *types;
 
   individual_can_audio_video_call (individual, &can_audio_call,
       &can_video_call);
 
+  types = individual_get_client_types (individual);
+
   gtk_tree_store_insert_with_values (self, iter, parent, 0,
       EMPATHY_INDIVIDUAL_STORE_COL_NAME,
       folks_aliasable_get_alias (FOLKS_ALIASABLE (individual)),
@@ -173,6 +209,7 @@ add_individual_to_store (GtkTreeStore *self,
       EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE,
       EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL, can_audio_call,
       EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL, can_video_call,
+      EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES, types,
       -1);
 }
 
@@ -738,10 +775,13 @@ individual_store_contact_update (EmpathyIndividualStore *self,
   for (l = iters; l && set_model; l = l->next)
     {
       gboolean can_audio_call, can_video_call;
+      const gchar * const *types;
 
       individual_can_audio_video_call (individual, &can_audio_call,
           &can_video_call);
 
+      types = individual_get_client_types (individual);
+
       gtk_tree_store_set (GTK_TREE_STORE (self), l->data,
           EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS, pixbuf_status,
           EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
@@ -757,6 +797,7 @@ individual_store_contact_update (EmpathyIndividualStore *self,
           EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE,
           EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL, can_audio_call,
           EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL, can_video_call,
+          EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES, types,
           -1);
     }
 
@@ -859,6 +900,8 @@ individual_personas_changed_cb (FolksIndividual *individual,
       g_object_set_data (G_OBJECT (contact), "individual", individual);
       g_signal_connect (contact, "notify::capabilities",
           (GCallback) individual_store_contact_updated_cb, self);
+      g_signal_connect (contact, "notify::client-types",
+          (GCallback) individual_store_contact_updated_cb, self);
 
       g_object_unref (contact);
     }
@@ -1494,6 +1537,7 @@ individual_store_setup (EmpathyIndividualStore *self)
     G_TYPE_BOOLEAN,             /* Can make audio calls */
     G_TYPE_BOOLEAN,             /* Can make video calls */
     G_TYPE_BOOLEAN,             /* Is a fake group */
+    G_TYPE_STRV,                /* Client types */
   };
 
   priv = GET_PRIV (self);
diff --git a/libempathy-gtk/empathy-individual-store.h b/libempathy-gtk/empathy-individual-store.h
index debb218..246c73b 100644
--- a/libempathy-gtk/empathy-individual-store.h
+++ b/libempathy-gtk/empathy-individual-store.h
@@ -64,6 +64,7 @@ typedef enum
   EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL,
   EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL,
   EMPATHY_INDIVIDUAL_STORE_COL_IS_FAKE_GROUP,
+  EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES,
   EMPATHY_INDIVIDUAL_STORE_COL_COUNT,
 } EmpathyIndividualStoreCol;
 
diff --git a/libempathy-gtk/empathy-individual-view.c b/libempathy-gtk/empathy-individual-view.c
index 6eb301d..a046825 100644
--- a/libempathy-gtk/empathy-individual-view.c
+++ b/libempathy-gtk/empathy-individual-view.c
@@ -214,7 +214,8 @@ individual_view_query_tooltip_cb (EmpathyIndividualView *view,
     {
       priv->tooltip_widget = empathy_individual_widget_new (individual,
           EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP |
-          EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION);
+          EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION |
+          EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES);
       gtk_container_set_border_width (GTK_CONTAINER (priv->tooltip_widget), 8);
       g_object_ref (priv->tooltip_widget);
       g_signal_connect (priv->tooltip_widget, "destroy",
@@ -1832,6 +1833,8 @@ individual_view_constructed (GObject *object)
       "is_group", EMPATHY_INDIVIDUAL_STORE_COL_IS_GROUP);
   gtk_tree_view_column_add_attribute (col, cell,
       "compact", EMPATHY_INDIVIDUAL_STORE_COL_COMPACT);
+  gtk_tree_view_column_add_attribute (col, cell,
+      "client-types", EMPATHY_INDIVIDUAL_STORE_COL_CLIENT_TYPES);
 
   /* Audio Call Icon */
   cell = empathy_cell_renderer_activatable_new ();
diff --git a/libempathy-gtk/empathy-individual-widget.c b/libempathy-gtk/empathy-individual-widget.c
index 5f180c0..863ce02 100644
--- a/libempathy-gtk/empathy-individual-widget.c
+++ b/libempathy-gtk/empathy-individual-widget.c
@@ -78,7 +78,7 @@ typedef struct {
   EmpathyIndividualWidgetFlags flags;
 
   /* weak pointer to the contact whose contact details we're displaying */
-  TpContact *contact_info_contact;
+  TpContact *contact;
 
   /* unowned Persona (borrowed from priv->individual) -> GtkTable child */
   GHashTable *persona_tables;
@@ -106,6 +106,9 @@ typedef struct {
   /* Groups */
   GtkWidget *groups_widget;
 
+  /* Client types */
+  GtkWidget *hbox_client_types;
+
   /* Details */
   GtkWidget *vbox_details;
   GtkWidget *table_details;
@@ -122,6 +125,9 @@ enum {
   PROP_FLAGS
 };
 
+static void client_types_update (EmpathyIndividualWidget *self);
+static void remove_weak_contact (EmpathyIndividualWidget *self);
+
 static void
 details_set_up (EmpathyIndividualWidget *self)
 {
@@ -193,6 +199,53 @@ contact_info_field_cmp (TpContactInfoField *field1,
   return contact_info_field_name_cmp (field1->field_name, field2->field_name);
 }
 
+static void
+update_weak_contact (EmpathyIndividualWidget *self)
+{
+  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+  TpContact *tp_contact = NULL;
+
+  remove_weak_contact (self);
+
+  if (priv->individual != NULL)
+    {
+      /* FIXME: We take the most available TpContact we find and only
+       * use its details. It would be a lot better if we would get the
+       * details for every TpContact in the Individual and merge them
+       * all, but that requires vCard support in libfolks for it to
+       * not be hideously complex.  (bgo#627399) */
+      GList *personas, *l;
+      FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET;
+
+      personas = folks_individual_get_personas (priv->individual);
+      for (l = personas; l != NULL; l = l->next)
+        {
+          FolksPresence *presence;
+
+          /* We only want personas which implement FolksPresence */
+          if (!FOLKS_IS_PRESENCE (l->data))
+            continue;
+
+          presence = FOLKS_PRESENCE (l->data);
+
+          if (folks_presence_typecmp (folks_presence_get_presence_type (presence),
+                  presence_type) > 0
+              && TPF_IS_PERSONA (presence))
+            {
+              presence_type = folks_presence_get_presence_type (presence);
+              tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
+            }
+        }
+    }
+
+  if (tp_contact != NULL)
+    {
+      priv->contact = tp_contact;
+      g_object_add_weak_pointer (G_OBJECT (tp_contact),
+          (gpointer *) &priv->contact);
+    }
+}
+
 typedef struct {
   EmpathyIndividualWidget *widget; /* weak */
   TpContact *contact; /* owned */
@@ -324,18 +377,6 @@ details_request_cb (TpContact *contact,
 
       tp_clear_object (&priv->details_cancellable);
 
-      /* We need a (weak) pointer to the contact so that we can disconnect the
-       * signal handler on deconstruction. */
-      if (priv->contact_info_contact != NULL)
-        {
-          g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact),
-            (gpointer *) &priv->contact_info_contact);
-        }
-
-      priv->contact_info_contact = contact;
-      g_object_add_weak_pointer (G_OBJECT (contact),
-          (gpointer *) &priv->contact_info_contact);
-
       g_signal_connect (contact, "notify::contact-info",
           (GCallback) details_notify_cb, self);
     }
@@ -387,28 +428,10 @@ details_update (EmpathyIndividualWidget *self)
 
   gtk_widget_hide (priv->vbox_details);
 
-  if (priv->individual != NULL)
-    {
-      /* FIXME: We take the first TpContact we find and only use its details.
-       * It would be a lot better if we would get the details for every
-       * TpContact in the Individual and merge them all, but that requires
-       * vCard support in libfolks for it to not be hideously complex.
-       * (bgo#627399) */
-      GList *personas, *l;
+  if (priv->contact == NULL)
+    update_weak_contact (self);
 
-      personas = folks_individual_get_personas (priv->individual);
-      for (l = personas; l != NULL; l = l->next)
-        {
-          if (TPF_IS_PERSONA (l->data))
-            {
-              tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
-              if (tp_contact != NULL)
-                break;
-            }
-        }
-    }
-
-  if (tp_contact != NULL)
+  if (priv->contact != NULL)
     {
       GQuark features[] = { TP_CONNECTION_FEATURE_CONTACT_INFO, 0 };
       TpConnection *connection;
@@ -417,7 +440,7 @@ details_update (EmpathyIndividualWidget *self)
       data = g_slice_new (DetailsData);
       data->widget = self;
       g_object_add_weak_pointer (G_OBJECT (self), (gpointer *) &data->widget);
-      data->contact = g_object_ref (tp_contact);
+      data->contact = g_object_ref (priv->contact);
 
       /* First, make sure the CONTACT_INFO feature is ready on the connection */
       connection = tp_contact_get_connection (tp_contact);
@@ -785,6 +808,64 @@ location_update (EmpathyIndividualWidget *self)
     gtk_widget_show (priv->vbox_location);
 }
 
+static void
+client_types_notify_cb (TpContact *contact,
+    GParamSpec *pspec,
+    EmpathyIndividualWidget *self)
+{
+  client_types_update (self);
+}
+
+static void
+client_types_update (EmpathyIndividualWidget *self)
+{
+  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+  const gchar * const *types;
+
+  if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES) ||
+      priv->individual == NULL)
+    {
+      gtk_widget_hide (priv->hbox_client_types);
+      return;
+    }
+
+  if (priv->contact == NULL)
+    update_weak_contact (self);
+
+  /* let's try that again... */
+  if (priv->contact == NULL)
+    return;
+
+  types = tp_contact_get_client_types (priv->contact);
+
+  if (types != NULL
+      && g_strv_length ((gchar **) types) > 0
+      && !tp_strdiff (types[0], "phone"))
+    {
+      gtk_widget_show (priv->hbox_client_types);
+    }
+  else
+    {
+      gtk_widget_hide (priv->hbox_client_types);
+    }
+
+  g_signal_connect (priv->contact, "notify::client-types",
+      (GCallback) client_types_notify_cb, self);
+}
+
+static void
+remove_weak_contact (EmpathyIndividualWidget *self)
+{
+  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+
+  if (priv->contact == NULL)
+    return;
+
+  g_object_remove_weak_pointer (G_OBJECT (priv->contact),
+      (gpointer *) &priv->contact);
+  priv->contact = NULL;
+}
+
 static EmpathyAvatar *
 persona_dup_avatar (FolksPersona *persona)
 {
@@ -1741,14 +1822,8 @@ remove_individual (EmpathyIndividualWidget *self)
         remove_persona (self, FOLKS_PERSONA (l->data));
       individual_table_destroy (self);
 
-      if (priv->contact_info_contact != NULL)
-        {
-          g_signal_handlers_disconnect_by_func (priv->contact_info_contact,
-              details_notify_cb, self);
-          g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact),
-              (gpointer *) &priv->contact_info_contact);
-          priv->contact_info_contact = NULL;
-        }
+      if (priv->contact != NULL)
+        remove_weak_contact (self);
 
       tp_clear_object (&priv->individual);
     }
@@ -1847,6 +1922,7 @@ empathy_individual_widget_init (EmpathyIndividualWidget *self)
       "vbox_details", &priv->vbox_details,
       "table_details", &priv->table_details,
       "hbox_details_requested", &priv->hbox_details_requested,
+      "hbox_client_types", &priv->hbox_client_types,
       NULL);
   g_free (filename);
 
@@ -2080,4 +2156,5 @@ empathy_individual_widget_set_individual (EmpathyIndividualWidget *self,
   groups_update (self);
   details_update (self);
   location_update (self);
+  client_types_update (self);
 }
diff --git a/libempathy-gtk/empathy-individual-widget.h b/libempathy-gtk/empathy-individual-widget.h
index a968d14..24a7f3d 100644
--- a/libempathy-gtk/empathy-individual-widget.h
+++ b/libempathy-gtk/empathy-individual-widget.h
@@ -63,6 +63,7 @@ typedef enum
   EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION  = 1 << 4,
   EMPATHY_INDIVIDUAL_WIDGET_SHOW_DETAILS = 1 << 5,
   EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS = 1 << 6,
+  EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES = 1 << 7,
 } EmpathyIndividualWidgetFlags;
 
 #define EMPATHY_TYPE_INDIVIDUAL_WIDGET (empathy_individual_widget_get_type ())
diff --git a/libempathy-gtk/empathy-individual-widget.ui b/libempathy-gtk/empathy-individual-widget.ui
index 5fb3823..dcfc83a 100644
--- a/libempathy-gtk/empathy-individual-widget.ui
+++ b/libempathy-gtk/empathy-individual-widget.ui
@@ -88,6 +88,35 @@
       </packing>
     </child>
     <child>
+      <object class="GtkHBox" id="hbox_client_types">
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkImage" id="image_phone">
+            <property name="visible">True</property>
+            <property name="icon_name">phone</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="label1">
+            <property name="visible">True</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">Online from a phone or mobile device</property>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">2</property>
+      </packing>
+    </child>
+    <child>
       <object class="EmpathyGroupsWidget" id="groups_widget"/>
       <packing>
         <property name="position">2</property>
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index 4db37f6..5383187 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -70,6 +70,7 @@ typedef struct {
    */
   GHashTable *location;
   GHashTable *groups;
+  gchar **client_types;
 } EmpathyContactPriv;
 
 static void contact_finalize (GObject *object);
@@ -85,6 +86,9 @@ static void update_geocode (EmpathyContact *contact);
 static void empathy_contact_set_location (EmpathyContact *contact,
     GHashTable *location);
 
+static void contact_set_client_types (EmpathyContact *contact,
+    const gchar * const *types);
+
 static void set_capabilities_from_tp_caps (EmpathyContact *self,
     TpCapabilities *caps);
 
@@ -110,7 +114,8 @@ enum
   PROP_HANDLE,
   PROP_CAPABILITIES,
   PROP_IS_USER,
-  PROP_LOCATION
+  PROP_LOCATION,
+  PROP_CLIENT_TYPES
 };
 
 enum {
@@ -163,6 +168,11 @@ tp_contact_notify_cb (TpContact *tp_contact,
     {
       contact_set_avatar_from_tp_contact (EMPATHY_CONTACT (contact));
     }
+  else if (!tp_strdiff (param->name, "client-types"))
+    {
+      contact_set_client_types (EMPATHY_CONTACT (contact),
+          tp_contact_get_client_types (tp_contact));
+    }
 }
 
 static void
@@ -223,6 +233,7 @@ contact_constructed (GObject *object)
   GHashTable *location;
   TpHandle self_handle;
   TpHandle handle;
+  const gchar * const *client_types;
 
   if (priv->tp_contact == NULL)
     return;
@@ -233,6 +244,10 @@ contact_constructed (GObject *object)
   if (location != NULL)
     empathy_contact_set_location (contact, location);
 
+  client_types = tp_contact_get_client_types (priv->tp_contact);
+  if (client_types != NULL)
+    contact_set_client_types (contact, client_types);
+
   set_capabilities_from_tp_caps (contact,
       tp_contact_get_capabilities (priv->tp_contact));
 
@@ -365,6 +380,14 @@ empathy_contact_class_init (EmpathyContactClass *class)
         G_TYPE_HASH_TABLE,
         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (object_class,
+      PROP_CLIENT_TYPES,
+      g_param_spec_boxed ("client-types",
+        "Contact client types",
+        "Client types of the contact",
+        G_TYPE_STRV,
+        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   signals[PRESENCE_CHANGED] =
     g_signal_new ("presence-changed",
                   G_TYPE_FROM_CLASS (class),
@@ -388,6 +411,7 @@ empathy_contact_init (EmpathyContact *contact)
   contact->priv = priv;
 
   priv->location = NULL;
+  priv->client_types = NULL;
   priv->groups = NULL;
 }
 
@@ -404,6 +428,7 @@ contact_finalize (GObject *object)
     g_hash_table_destroy (priv->groups);
   g_free (priv->alias);
   g_free (priv->id);
+  g_strfreev (priv->client_types);
 
   G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
 }
@@ -1396,6 +1421,31 @@ empathy_contact_set_location (EmpathyContact *contact,
   g_object_notify (G_OBJECT (contact), "location");
 }
 
+const gchar * const *
+empathy_contact_get_client_types (EmpathyContact *contact)
+{
+  EmpathyContactPriv *priv;
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  priv = GET_PRIV (contact);
+
+  return (const gchar * const *) priv->client_types;
+}
+
+static void
+contact_set_client_types (EmpathyContact *contact,
+    const gchar * const *client_types)
+{
+  EmpathyContactPriv *priv = GET_PRIV (contact);
+
+  if (priv->client_types != NULL)
+    g_strfreev (priv->client_types);
+
+  priv->client_types = g_strdupv ((gchar **) client_types);
+  g_object_notify (G_OBJECT (contact), "client-types");
+}
+
 /**
  * empathy_contact_equal:
  * @contact1: an #EmpathyContact
diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h
index 005cf1e..f9217c1 100644
--- a/libempathy/empathy-contact.h
+++ b/libempathy/empathy-contact.h
@@ -125,6 +125,7 @@ gboolean empathy_avatar_save_to_file (EmpathyAvatar *avatar,
     const gchar *filename, GError **error);
 
 GHashTable * empathy_contact_get_location (EmpathyContact *contact);
+const gchar * const * empathy_contact_get_client_types (EmpathyContact *contact);
 gboolean empathy_contact_equal (gconstpointer contact1,
     gconstpointer contact2);
 
diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c
index ff572cc..87c6538 100644
--- a/libempathy/empathy-tp-contact-factory.c
+++ b/libempathy/empathy-tp-contact-factory.c
@@ -31,6 +31,7 @@ static TpContactFeature contact_features[] = {
 	TP_CONTACT_FEATURE_PRESENCE,
 	TP_CONTACT_FEATURE_LOCATION,
 	TP_CONTACT_FEATURE_CAPABILITIES,
+	TP_CONTACT_FEATURE_CLIENT_TYPES,
 };
 
 typedef union {
