diff --git a/src/test/url.c b/src/test/url.c
index 4c12809afa093ca981e61d52785cbfab4a8eb664..9351ce9ccc3bec2738a418467c324b0d2e60ce0a 100644
--- a/src/test/url.c
+++ b/src/test/url.c
@@ -277,6 +277,8 @@ int main (void)
                    "/", NULL);
     test_url_parse("http://[2001:db8::1]", "http", NULL, NULL, "2001:db8::1",
                    0, NULL, NULL);
+    test_url_parse("http://[fe80::1%25eth0]", "http", NULL, NULL, "fe80::1%eth0",
+                   0, NULL, NULL);
     test_url_parse("http://example.com:", "http", NULL, NULL, "example.com", 0,
                     NULL, NULL);
     test_url_parse("protocol://john:doe@1.2.3.4:567", "protocol", "john", "doe", "1.2.3.4", 567, NULL, NULL);
@@ -321,6 +323,7 @@ int main (void)
     test_url_parse("http://example.com:-18446744073709551615", NULL, NULL, NULL, NULL, 0, NULL, NULL );
     test_url_parse("http://user%/Oath", "http", NULL, NULL, NULL, 0, "/Oath",
                    NULL);
+    test_url_parse("http://[2001::1%25eth0]", NULL, NULL, NULL, NULL, 0, NULL, NULL);
 
     /* URIs to fixup */
     test_url_parse("smb://SERVER:445/SHARE/My file.mp3", "smb", NULL, NULL, "SERVER", 445, NULL, NULL);
diff --git a/src/text/url.c b/src/text/url.c
index 30c61b49552c220dc7cd58b1d1ef20f808dfc5e8..250e5be2538bd2e46bbc24f6277c31b086af9671 100644
--- a/src/text/url.c
+++ b/src/text/url.c
@@ -422,6 +422,11 @@ static bool vlc_uri_component_validate(const char *str, const char *extras)
 
 static bool vlc_uri_host_validate(const char *str)
 {
+    // Only link-Local IPv6 addresses can have a zone identifier
+    if (!strncasecmp(str, "fe80:", 5)) {
+        return vlc_uri_component_validate(str, ":%");
+    }
+
     return vlc_uri_component_validate(str, ":");
 }
 
@@ -524,7 +529,7 @@ static int vlc_UrlParseInner(vlc_url_t *restrict url, const char *str)
         if (*cur == '[' && (next = strrchr(cur, ']')) != NULL)
         {   /* Try IPv6 numeral within brackets */
             *(next++) = '\0';
-            url->psz_host = strdup(cur + 1);
+            url->psz_host = vlc_uri_decode_duplicate(cur + 1);
 
             if (*next == ':')
                 next++;