diff --git a/src/util/UriExtract.cxx b/src/util/UriExtract.cxx
index 72ac284d9..c71019bcb 100644
--- a/src/util/UriExtract.cxx
+++ b/src/util/UriExtract.cxx
@@ -138,3 +138,13 @@ uri_get_suffix(const char *uri, UriSuffixBuffer &buffer) noexcept
 
 	return suffix;
 }
+
+const char *
+uri_get_fragment(const char *uri) noexcept
+{
+	const char *fragment = strchr(uri, '#');
+	if (fragment == nullptr)
+		return nullptr;
+
+	return fragment + 1;
+}
diff --git a/src/util/UriExtract.hxx b/src/util/UriExtract.hxx
index 23ed2c12a..628fe6f90 100644
--- a/src/util/UriExtract.hxx
+++ b/src/util/UriExtract.hxx
@@ -72,4 +72,14 @@ gcc_pure
 const char *
 uri_get_suffix(const char *uri, UriSuffixBuffer &buffer) noexcept;
 
+/**
+ * Returns the URI fragment, i.e. the portion after the '#', but
+ * without the '#'.  If there is no '#', this function returns
+ * nullptr; if there is a '#' but no fragment text, it returns an
+ * empty StringView.
+ */
+gcc_pure gcc_nonnull_all
+const char *
+uri_get_fragment(const char *uri) noexcept;
+
 #endif