diff --git a/libpurple/purplesavedpresence.h b/libpurple/purplesavedpresence.h
--- a/libpurple/purplesavedpresence.h
+++ b/libpurple/purplesavedpresence.h
@@ -122,6 +122,19 @@
 void purple_saved_presence_set_name(PurpleSavedPresence *presence, const char *name);
 
 /**
+ * purple_saved_presence_get_escaped_name:
+ * @presence: The instance.
+ *
+ * Gets the escaped version of [property@SavedPresence:name] of @presence. The
+ * escaped name is suitable for serialization.
+ *
+ * Returns: The escaped name.
+ *
+ * Since: 3.0.0
+ */
+const char *purple_saved_presence_get_escaped_name(PurpleSavedPresence *presence);
+
+/**
  * purple_saved_presence_get_primitive:
  * @presence: The instance.
  *
# HG changeset patch
# Node ID 20cc28fa108e
# Parent  f44497b3f5d9
diff --git a/libpurple/purplesavedpresence.c b/libpurple/purplesavedpresence.c
--- a/libpurple/purplesavedpresence.c
+++ b/libpurple/purplesavedpresence.c
@@ -33,6 +33,7 @@
 	guint use_count;
 
 	char *name;
+	char *escaped_name;
 
 	PurplePresencePrimitive primitive;
 	char *message;
@@ -44,6 +45,7 @@
 	PROP_LAST_USED,
 	PROP_USE_COUNT,
 	PROP_NAME,
+	PROP_ESCAPED_NAME,
 	PROP_PRIMITIVE,
 	PROP_MESSAGE,
 	PROP_EMOJI,
@@ -112,6 +114,10 @@
 			g_value_set_string(value,
 			                   purple_saved_presence_get_name(presence));
 			break;
+		case PROP_ESCAPED_NAME:
+			g_value_set_string(value,
+			                   purple_saved_presence_get_escaped_name(presence));
+			break;
 		case PROP_PRIMITIVE:
 			g_value_set_enum(value,
 			                 purple_saved_presence_get_primitive(presence));
@@ -141,6 +147,7 @@
 	g_clear_pointer(&presence->last_used, g_date_time_unref);
 
 	g_clear_pointer(&presence->name, g_free);
+	g_clear_pointer(&presence->escaped_name, g_free);
 	g_clear_pointer(&presence->message, g_free);
 	g_clear_pointer(&presence->emoji, g_free);
 
@@ -195,6 +202,20 @@
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
+	 * PurpleSavedPresence:escaped-name:
+	 *
+	 * An escaped version of [property@PurpleSavedPresence:name] that's
+	 * suitable for serialization.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_ESCAPED_NAME] = g_param_spec_string(
+		"escaped-name", "escaped-name",
+		"The escaped version of the name.",
+		NULL,
+		G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	/**
 	 * PurpleSavedPresence:primitive:
 	 *
 	 * The [enum@Purple.StatusPrimitive] for this saved presence.
@@ -304,13 +325,33 @@
 	g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence));
 
 	if(!purple_strequal(presence->name, name)) {
+		GObject *obj = G_OBJECT(presence);
+
 		g_free(presence->name);
 		presence->name = g_strdup(name);
 
-		g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_NAME]);
+		g_free(presence->escaped_name);
+		if(!purple_strempty(presence->name)) {
+			presence->escaped_name = g_uri_escape_string(presence->name, NULL,
+			                                             TRUE);
+		} else {
+			presence->escaped_name = NULL;
+		}
+
+		g_object_freeze_notify(obj);
+		g_object_notify_by_pspec(obj, properties[PROP_NAME]);
+		g_object_notify_by_pspec(obj, properties[PROP_ESCAPED_NAME]);
+		g_object_thaw_notify(obj);
 	}
 }
 
+const char *
+purple_saved_presence_get_escaped_name(PurpleSavedPresence *presence) {
+	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), NULL);
+
+	return presence->escaped_name;
+}
+
 PurplePresencePrimitive
 purple_saved_presence_get_primitive(PurpleSavedPresence *presence) {
 	g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence),
diff --git a/libpurple/tests/test_saved_presence.c b/libpurple/tests/test_saved_presence.c
--- a/libpurple/tests/test_saved_presence.c
+++ b/libpurple/tests/test_saved_presence.c
@@ -21,6 +21,19 @@
 #include <purple.h>
 
 /******************************************************************************
+ * Callback helpers
+ *****************************************************************************/
+static void
+test_purple_saved_presence_notify_called(G_GNUC_UNUSED GObject *obj,
+                                         G_GNUC_UNUSED GParamSpec *pspec,
+                                         gpointer data)
+{
+	guint *counter = data;
+
+	*counter = *counter + 1;
+}
+
+/******************************************************************************
  * Tests
  *****************************************************************************/
 static void
@@ -40,9 +53,10 @@
 	GDateTime *last_used = NULL;
 	GDateTime *last_used1 = NULL;
 	guint use_count;
-	char *name;
-	char *message;
-	char *emoji;
+	char *name = NULL;
+	char *escaped_name = NULL;
+	char *message = NULL;
+	char *emoji = NULL;
 
 	last_used = g_date_time_new_now_local();
 
@@ -66,6 +80,7 @@
 		"last-used", &last_used1,
 		"use-count", &use_count,
 		"name", &name,
+		"escaped-name", &escaped_name,
 		"primitive", &primitive,
 		"message", &message,
 		"emoji", &emoji,
@@ -81,6 +96,9 @@
 	g_assert_cmpstr(name, ==, "my saved status");
 	g_clear_pointer(&name, g_free);
 
+	g_assert_cmpstr(escaped_name, ==, "my%20saved%20status");
+	g_clear_pointer(&escaped_name, g_free);
+
 	g_assert_cmpint(primitive, ==, PURPLE_PRESENCE_PRIMITIVE_STREAMING);
 
 	g_assert_cmpstr(message, ==,
@@ -95,6 +113,34 @@
 }
 
 static void
+test_purple_saved_presence_escaped_name(void) {
+	PurpleSavedPresence *presence = NULL;
+	guint counter = 0;
+
+	presence = g_object_new(
+		PURPLE_TYPE_SAVED_PRESENCE,
+		"name", "{\"text/json\":null}",
+		NULL);
+
+	g_signal_connect(presence, "notify",
+	                 G_CALLBACK(test_purple_saved_presence_notify_called),
+	                 &counter);
+
+	g_assert_cmpstr(purple_saved_presence_get_name(presence), ==,
+	                "{\"text/json\":null}");
+	g_assert_cmpstr(purple_saved_presence_get_escaped_name(presence), ==,
+	                "%7B%22text%2Fjson%22%3Anull%7D");
+
+	purple_saved_presence_set_name(presence, "🐧🐶🐱");
+	g_assert_cmpstr(purple_saved_presence_get_escaped_name(presence), ==,
+	                "🐧🐶🐱");
+
+	g_assert_cmpuint(counter, ==, 2);
+
+	g_clear_object(&presence);
+}
+
+static void
 test_purple_saved_presence_equal_null_null(void) {
 	g_assert_true(purple_saved_presence_equal(NULL, NULL));
 }
@@ -283,6 +329,8 @@
 	                test_purple_saved_presence_new);
 	g_test_add_func("/saved-presence/properties",
 	                test_purple_saved_presence_properties);
+	g_test_add_func("/saved-presence/escaped-name",
+	                test_purple_saved_presence_escaped_name);
 
 	g_test_add_func("/saved-presence/equal/null_null",
 	                test_purple_saved_presence_equal_null_null);
