diff --git a/lib/wp/core.c b/lib/wp/core.c
index 486016fe46aa92e3866ee0c754193d453c5c1519..c114936b01ba594068fa5c68e3e879b1dd3a1ccb 100644
--- a/lib/wp/core.c
+++ b/lib/wp/core.c
@@ -77,6 +77,9 @@ struct _WpCore
   /* main loop integration */
   GMainContext *context;
 
+  /* extra properties */
+  WpProperties *properties;
+
   /* pipewire main objects */
   struct pw_core *pw_core;
   struct pw_remote *pw_remote;
@@ -107,6 +110,7 @@ struct global_object
 enum {
   PROP_0,
   PROP_CONTEXT,
+  PROP_PROPERTIES,
   PROP_PW_CORE,
   PROP_PW_REMOTE,
   PROP_REMOTE_STATE,
@@ -245,12 +249,16 @@ wp_core_constructed (GObject *object)
 {
   WpCore *self = WP_CORE (object);
   g_autoptr (GSource) source = NULL;
+  struct pw_properties *p;
 
   source = wp_loop_source_new ();
   g_source_attach (source, self->context);
 
-  self->pw_core = pw_core_new (WP_LOOP_SOURCE (source)->loop, NULL, 0);
-  self->pw_remote = pw_remote_new (self->pw_core, NULL, 0);
+  p = self->properties ? wp_properties_to_pw_properties (self->properties) : NULL;
+  self->pw_core = pw_core_new (WP_LOOP_SOURCE (source)->loop, p, 0);
+
+  p = self->properties ? wp_properties_to_pw_properties (self->properties) : NULL;
+  self->pw_remote = pw_remote_new (self->pw_core, p, 0);
   pw_remote_add_listener (self->pw_remote, &self->remote_listener,
       &remote_events, self);
 
@@ -289,6 +297,7 @@ wp_core_finalize (GObject * obj)
   self->core_proxy= NULL;
   self->registry_proxy = NULL;
   g_clear_pointer (&self->pw_core, pw_core_destroy);
+  g_clear_pointer (&self->properties, wp_properties_unref);
   g_clear_pointer (&self->context, g_main_context_unref);
 
   g_debug ("WpCore destroyed");
@@ -306,6 +315,9 @@ wp_core_get_property (GObject * object, guint property_id,
   case PROP_CONTEXT:
     g_value_set_boxed (value, self->context);
     break;
+  case PROP_PROPERTIES:
+    g_value_set_boxed (value, self->properties);
+    break;
   case PROP_PW_CORE:
     g_value_set_pointer (value, self->pw_core);
     break;
@@ -331,6 +343,9 @@ wp_core_set_property (GObject * object, guint property_id,
   case PROP_CONTEXT:
     self->context = g_value_dup_boxed (value);
     break;
+  case PROP_PROPERTIES:
+    self->properties = g_value_dup_boxed (value);
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     break;
@@ -355,6 +370,11 @@ wp_core_class_init (WpCoreClass * klass)
           G_TYPE_MAIN_CONTEXT,
           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (object_class, PROP_PROPERTIES,
+      g_param_spec_boxed ("properties", "properties", "Extra properties",
+          WP_TYPE_PROPERTIES,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_property (object_class, PROP_PW_CORE,
       g_param_spec_pointer ("pw-core", "pw-core", "The pipewire core",
           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
@@ -392,9 +412,12 @@ wp_core_class_init (WpCoreClass * klass)
 }
 
 WpCore *
-wp_core_new (GMainContext *context)
+wp_core_new (GMainContext *context, WpProperties * properties)
 {
-  return g_object_new (WP_TYPE_CORE, "context", context, NULL);
+  return g_object_new (WP_TYPE_CORE,
+      "context", context,
+      "properties", properties,
+      NULL);
 }
 
 GMainContext *
diff --git a/lib/wp/core.h b/lib/wp/core.h
index 8f80ed05e7db4830b9282fb7807de334163e67c9..46f62d7040850001026a1a38e4d27c1cd0229f6c 100644
--- a/lib/wp/core.h
+++ b/lib/wp/core.h
@@ -36,7 +36,7 @@ typedef enum {
 #define WP_TYPE_CORE (wp_core_get_type ())
 G_DECLARE_FINAL_TYPE (WpCore, wp_core, WP, CORE, GObject)
 
-WpCore * wp_core_new (GMainContext *context);
+WpCore * wp_core_new (GMainContext *context, WpProperties * properties);
 
 GMainContext * wp_core_get_context (WpCore * self);
 struct pw_core * wp_core_get_pw_core (WpCore * self);
diff --git a/src/main.c b/src/main.c
index 494bc01434e7182f5c9012a2133119163d3e35c8..b50a3ffc24c833e961a708e4bac4bc793854a4dd 100644
--- a/src/main.c
+++ b/src/main.c
@@ -263,7 +263,7 @@ main (gint argc, gchar **argv)
 
   /* init wireplumber */
 
-  data.core = core = wp_core_new (NULL);
+  data.core = core = wp_core_new (NULL, NULL);
   g_signal_connect (core, "remote-state-changed",
       (GCallback) remote_state_changed, &data);
 
diff --git a/tests/proxy.c b/tests/proxy.c
index 6e3173592732781b519583aea79568925a618163..e3f4b65b7626fe3f2a931ee2e9808838cda4b6f9 100644
--- a/tests/proxy.c
+++ b/tests/proxy.c
@@ -56,11 +56,14 @@ test_proxy_remote_state_changed (WpCore *core, WpRemoteState state,
 static void
 test_proxy_setup (TestProxyFixture *self, gconstpointer user_data)
 {
+  g_autoptr (WpProperties) props = NULL;
+
   wp_test_server_setup (&self->server);
-  g_setenv ("PIPEWIRE_REMOTE", self->server.name, TRUE);
+
+  props = wp_properties_new (PW_KEY_REMOTE_NAME, self->server.name, NULL);
   self->context = g_main_context_new ();
   self->loop = g_main_loop_new (self->context, FALSE);
-  self->core = wp_core_new (self->context);
+  self->core = wp_core_new (self->context, props);
 
   g_main_context_push_thread_default (self->context);
 
@@ -83,7 +86,6 @@ test_proxy_teardown (TestProxyFixture *self, gconstpointer user_data)
   g_clear_pointer (&self->timeout_source, g_source_unref);
   g_clear_pointer (&self->loop, g_main_loop_unref);
   g_clear_pointer (&self->context, g_main_context_unref);
-  g_unsetenv ("PIPEWIRE_REMOTE");
   wp_test_server_teardown (&self->server);
 }