diff --git a/src/core/lib/client_config/uri_parser.c b/src/core/lib/client_config/uri_parser.c
index d3228dec5fa4d6b1a9385734a1dd91b993620489..d818d4c4d1a91dd7baea54f4b120374f949e6422 100644
--- a/src/core/lib/client_config/uri_parser.c
+++ b/src/core/lib/client_config/uri_parser.c
@@ -38,8 +38,12 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/port_platform.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/lib/support/string.h"
+
 /** a size_t default value... maps to all 1's */
 #define NOT_SET (~(size_t)0)
 
@@ -133,6 +137,51 @@ static int parse_fragment_or_query(const char *uri_text, size_t *i) {
   return 1;
 }
 
+static void do_nothing(void *ignored) {}
+static void parse_query_parts(grpc_uri *uri) {
+  static const char *QUERY_PARTS_SEPARATOR = "&";
+  static const char *QUERY_PARTS_VALUE_SEPARATOR = "=";
+  GPR_ASSERT(uri->query != NULL);
+  if (uri->query[0] == '\0') {
+    uri->query_parts = NULL;
+    uri->query_parts_values = NULL;
+    uri->num_query_parts = 0;
+    return;
+  }
+  gpr_slice query_slice =
+      gpr_slice_new(uri->query, strlen(uri->query), do_nothing);
+  gpr_slice_buffer query_parts; /* the &-separated elements of the query */
+  gpr_slice_buffer query_param_parts; /* the =-separated subelements */
+
+  gpr_slice_buffer_init(&query_parts);
+  gpr_slice_buffer_init(&query_param_parts);
+
+  gpr_slice_split(query_slice, QUERY_PARTS_SEPARATOR, &query_parts);
+  uri->query_parts = gpr_malloc(query_parts.count * sizeof(char *));
+  uri->query_parts_values = gpr_malloc(query_parts.count * sizeof(char *));
+  uri->num_query_parts = query_parts.count;
+  for (size_t i = 0; i < query_parts.count; i++) {
+    gpr_slice_split(query_parts.slices[i], QUERY_PARTS_VALUE_SEPARATOR,
+                    &query_param_parts);
+    GPR_ASSERT(query_param_parts.count > 0);
+    uri->query_parts[i] =
+        gpr_dump_slice(query_param_parts.slices[0], GPR_DUMP_ASCII);
+    if (query_param_parts.count > 1) {
+      /* TODO(dgq): only the first value after the separator is considered.
+       * Perhaps all chars after the first separator for the query part should
+       * be included, even if they include the separator. */
+      uri->query_parts_values[i] =
+          gpr_dump_slice(query_param_parts.slices[1], GPR_DUMP_ASCII);
+    } else {
+      uri->query_parts_values[i] = NULL;
+    }
+    gpr_slice_buffer_reset_and_unref(&query_param_parts);
+  }
+  gpr_slice_buffer_destroy(&query_parts);
+  gpr_slice_buffer_destroy(&query_param_parts);
+  gpr_slice_unref(query_slice);
+}
+
 grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
   grpc_uri *uri;
   size_t scheme_begin = 0;
@@ -227,6 +276,7 @@ grpc_uri *grpc_uri_parse(const char *uri_text, int suppress_errors) {
   uri->path = copy_component(uri_text, path_begin, path_end);
   uri->query = copy_component(uri_text, query_begin, query_end);
   uri->fragment = copy_component(uri_text, fragment_begin, fragment_end);
+  parse_query_parts(uri);
 
   return uri;
 }
@@ -237,6 +287,12 @@ void grpc_uri_destroy(grpc_uri *uri) {
   gpr_free(uri->authority);
   gpr_free(uri->path);
   gpr_free(uri->query);
+  for (size_t i = 0; i < uri->num_query_parts; ++i) {
+    gpr_free(uri->query_parts[i]);
+    gpr_free(uri->query_parts_values[i]);
+  }
+  gpr_free(uri->query_parts);
+  gpr_free(uri->query_parts_values);
   gpr_free(uri->fragment);
   gpr_free(uri);
 }
diff --git a/src/core/lib/client_config/uri_parser.h b/src/core/lib/client_config/uri_parser.h
index d70d451e60f1336fccf2a3cbf18f9f4ef386635e..115dd5a2f6cddd7632cfa176bffa7f0e110b585f 100644
--- a/src/core/lib/client_config/uri_parser.h
+++ b/src/core/lib/client_config/uri_parser.h
@@ -34,11 +34,19 @@
 #ifndef GRPC_CORE_LIB_CLIENT_CONFIG_URI_PARSER_H
 #define GRPC_CORE_LIB_CLIENT_CONFIG_URI_PARSER_H
 
+#include <stddef.h>
+
 typedef struct {
   char *scheme;
   char *authority;
   char *path;
   char *query;
+  /** Query substrings separated by '&' */
+  char **query_parts;
+  /** Number of elements in \a query_parts and \a query_parts_values */
+  size_t num_query_parts;
+  /** Split each query part by '='. NULL if not present. */
+  char **query_parts_values;
   char *fragment;
 } grpc_uri;
 
diff --git a/test/core/client_config/uri_parser_test.c b/test/core/client_config/uri_parser_test.c
index c7f7726380433e4c6d994cccccf9dc2a2bf7e3de..bc3e01c90ab258efe3cfa4421ab61aca5d373ec1 100644
--- a/test/core/client_config/uri_parser_test.c
+++ b/test/core/client_config/uri_parser_test.c
@@ -56,6 +56,51 @@ static void test_fails(const char *uri_text) {
   GPR_ASSERT(NULL == grpc_uri_parse(uri_text, 0));
 }
 
+static void test_query_parts() {
+  {
+    const char *uri_text = "http://foo/path?a&b=B&c=&#frag";
+    grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+    GPR_ASSERT(uri);
+
+    GPR_ASSERT(0 == strcmp("http", uri->scheme));
+    GPR_ASSERT(0 == strcmp("foo", uri->authority));
+    GPR_ASSERT(0 == strcmp("/path", uri->path));
+    GPR_ASSERT(0 == strcmp("a&b=B&c=&", uri->query));
+    GPR_ASSERT(4 == uri->num_query_parts);
+
+    GPR_ASSERT(0 == strcmp("a", uri->query_parts[0]));
+    GPR_ASSERT(NULL == uri->query_parts_values[0]);
+
+    GPR_ASSERT(0 == strcmp("b", uri->query_parts[1]));
+    GPR_ASSERT(0 == strcmp("B", uri->query_parts_values[1]));
+
+    GPR_ASSERT(0 == strcmp("c", uri->query_parts[2]));
+    GPR_ASSERT(0 == strcmp("", uri->query_parts_values[2]));
+
+    GPR_ASSERT(0 == strcmp("", uri->query_parts[3]));
+    GPR_ASSERT(NULL == uri->query_parts_values[3]);
+
+    GPR_ASSERT(0 == strcmp("frag", uri->fragment));
+    grpc_uri_destroy(uri);
+  }
+  {
+    /* empty query */
+    const char *uri_text = "http://foo/path";
+    grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+    GPR_ASSERT(uri);
+
+    GPR_ASSERT(0 == strcmp("http", uri->scheme));
+    GPR_ASSERT(0 == strcmp("foo", uri->authority));
+    GPR_ASSERT(0 == strcmp("/path", uri->path));
+    GPR_ASSERT(0 == strcmp("", uri->query));
+    GPR_ASSERT(0 == uri->num_query_parts);
+    GPR_ASSERT(NULL == uri->query_parts);
+    GPR_ASSERT(NULL == uri->query_parts_values);
+    GPR_ASSERT(0 == strcmp("", uri->fragment));
+    grpc_uri_destroy(uri);
+  }
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_succeeds("http://www.google.com", "http", "www.google.com", "", "", "");
@@ -82,5 +127,6 @@ int main(int argc, char **argv) {
   test_fails("http://foo?x[bar]");
   test_fails("http://foo?bar#lol#");
 
+  test_query_parts();
   return 0;
 }