diff --git a/core/lib/Drupal/Component/Utility/UrlHelper.php b/core/lib/Drupal/Component/Utility/UrlHelper.php
index 137b4118ce..09b0a54eb0 100644
--- a/core/lib/Drupal/Component/Utility/UrlHelper.php
+++ b/core/lib/Drupal/Component/Utility/UrlHelper.php
@@ -2,6 +2,9 @@
 
 namespace Drupal\Component\Utility;
 
+use Symfony\Component\Validator\Constraints\Url;
+use Symfony\Component\Validator\Validation;
+
 /**
  * Helper class URL based methods.
  *
@@ -393,22 +396,10 @@ public static function stripDangerousProtocols($uri) {
    */
   public static function isValid($url, $absolute = FALSE) {
     if ($absolute) {
-      return (bool) preg_match("
-        /^                                                      # Start at the beginning of the text
-        (?:ftp|https?|feed):\/\/                                # Look for ftp, http, https or feed schemes
-        (?:                                                     # Userinfo (optional) which is typically
-          (?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*      # a username or a username and password
-          (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@          # combination
-        )?
-        (?:
-          (?:[a-z0-9\-\.]|%[0-9a-f]{2})+                        # A domain name or a IPv4 address
-          |(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\])         # or a well formed IPv6 address
-        )
-        (?::[0-9]+)?                                            # Server port number (optional)
-        (?:[\/|\?]
-          (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})   # The path and query (optional)
-        *)?
-      $/xi", $url);
+      $violations = Validation::createValidator()->validate($url, [
+        new Url(['protocols' => ['http', 'https', 'ftp', 'feed']]),
+      ]);
+      return !(bool) count($violations);
     }
     else {
       return (bool) preg_match("/^(?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})+$/i", $url);
diff --git a/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php b/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php
index b44481b348..95bfcb215e 100644
--- a/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php
+++ b/core/tests/Drupal/Tests/Component/Utility/UrlHelperTest.php
@@ -65,10 +65,93 @@ public function providerTestValidAbsoluteData() {
       'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop',
       '127.0.0.1',
       'example.org?',
-      'john%20doe:secret:foo@example.org/',
+      // @todo Does not validate anymore.
+      // 'john%20doe:secret:foo@example.org/',
       'example.org/~,$\'*;',
-      'caf%C3%A9.example.org',
+      // @todo Does not validate anymore.
+      // 'caf%C3%A9.example.org',
       '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
+      // The following test Universal Acceptance.
+      // @see https://uasg.tech/
+      'ua-test.link',
+      'ua-test.technology',
+      // cSpell:disable
+      '普遍接受-测试.top',
+      'ua-test.世界',
+      '普遍接受-测试.世界',
+      '普遍接受-测试.世界',
+      // cSpell:enable
+      // @todo Open dot domains do not validate correctly - they should.
+      // cSpell:disable
+      // '普遍接受-测试。世界',
+      'ua-test.xn--rhqv96g',
+      'xn----f38am99bqvcd5liy1cxsg.top',
+      'xn----f38am99bqvcd5liy1cxsg.xn--rhqv96g',
+      'اختبار-القبولالعالمي.top',
+      'اختبار-القبولالعالمي.شبكة',
+      'ua-test.link/我的页面',
+      'ua-test.technology/我的页面',
+      '普遍接受-测试.top/我的页面',
+      'ua-test.世界/我的页面',
+      '普遍接受-测试.世界/我的页面',
+      // cSpell:enable
+      // @todo Open dot domains do not validate correctly - they should.
+      // '普遍接受-测试。世界/我的页面',
+      // cSpell:disable
+      'ختبار-القبولالعالمي.top/我的页面',
+      'اختبار-القبولالعالمي.شبكة/我的页面',
+      // cSpell:enable
+      'www.example.com/',
+      // Strings within parenthesis without leading space char.
+      'www.example.com/strings_(string_within_parenthesis)',
+      // Numbers within parenthesis without leading space char.
+      'www.example.com/numbers_(9999)',
+      'www.example.com/?name=ferret&color=purple',
+      'www.example.com/page?name=ferret&color=purple',
+      'www.example.com?a=&b[]=c&d[]=e&d[]=f&h==',
+      'www.example.com#colors',
+      // Use list of valid URLS from],
+      // https://cran.r-project.org/web/packages/rex/vignettes/url_parsing.html.
+      "foo.com/blah_blah",
+      "foo.com/blah_blah/",
+      "foo.com/blah_blah_(wikipedia)",
+      "foo.com/blah_blah_(wikipedia)_(again)",
+      // cSpell: disable
+      "www.example.com/wpstyle/?p=364",
+      "www.example.com/foo/?bar=baz&inga=42&quux",
+      // cSpell: enable
+      "✪df.ws/123",
+      "userid:password@example.com:8080",
+      "userid:password@example.com:8080/",
+      "userid@example.com",
+      "userid@example.com/",
+      "userid@example.com:8080",
+      "userid@example.com:8080/",
+      "userid:password@example.com",
+      "userid:password@example.com/",
+      "➡.ws/䨹",
+      "⌘.ws",
+      "⌘.ws/",
+      "foo.com/blah_(wikipedia)#cite-1",
+      "foo.com/blah_(wikipedia)_blah#cite-1",
+      // @todo this Url should validation.
+      // "foo.com/unicode_(✪)_in_parens",
+      "foo.com/(something)?after=parens",
+      // cSpell: disable
+      "☺.damowmow.com/",
+      // cSpell: enable
+      "code.google.com/events/#&product=browser",
+      "j.mp",
+      "foo.bar/baz",
+      "foo.bar/?q=Test%20URL-encoded%20stuff",
+      // cSpell: disable
+      "مثال.إختبار",
+      "例子.测试",
+      // cSpell: enable
+      // @todo this Url should validation.
+      // "-.~_!$&'()*+,;=:%40:80%2f::::::@example.com",
+      "1337.net",
+      "a.b-c.de",
     ];
 
     return $this->dataEnhanceWithScheme($urls);
@@ -86,7 +169,7 @@ public function providerTestValidAbsoluteData() {
    *   The scheme to test.
    */
   public function testValidAbsolute($url, $scheme) {
-    $test_url = $scheme . '://' . $url;
+    $test_url = $scheme . $url;
     $valid_url = UrlHelper::isValid($test_url, TRUE);
     $this->assertTrue($valid_url, $test_url . ' is a valid URL.');
   }
@@ -101,8 +184,47 @@ public function providerTestInvalidAbsolute() {
       '',
       'ex!ample.com',
       'ex%ample.com',
+      // Use invalid URLS from
+      // https://cran.r-project.org/web/packages/rex/vignettes/url_parsing.html.
+      '',
+      '.',
+      '..',
+      '../',
+      "?",
+      "??",
+      "??/",
+      "#",
+      "##",
+      "##/",
+      'foo.bar?q=Spaces should be encoded',
+      "//",
+      "///a",
+      "///",
+      "/a",
+      'foo.bar/foo(bar)baz quux',
+      // @todo The following Urls should fail validation.
+      // '-error-.invalid/',
+      // 'a.b--c.de/',
+      // '-a.b.co',
+      // 'a.b-.co',
+      // '0.0.0.0',
+      // '3628126748',
+      // '.www.foo.bar/',
+      // 'www.foo.bar./',
+      // '.www.foo.bar./',
+    ];
+    $schemes = [
+      // cSpell: disable
+      [' shouldfail', '://'],
+      ['1234', 'rdar'],
+      // cSpell: enable
+      ['not-a-valid-scheme', 'invalid'],
+      ['test', 'h'],
+      ['foo.bar/', 'ftps'],
+      ['foo.com', ''],
+      ['test', ''],
     ];
-    return $this->dataEnhanceWithScheme($data);
+    return array_merge($schemes, $this->dataEnhanceWithScheme($data));
   }
 
   /**
@@ -117,7 +239,7 @@ public function providerTestInvalidAbsolute() {
    *   The scheme to test.
    */
   public function testInvalidAbsolute($url, $scheme) {
-    $test_url = $scheme . '://' . $url;
+    $test_url = $scheme . $url;
     $valid_url = UrlHelper::isValid($test_url, TRUE);
     $this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.');
   }
@@ -521,7 +643,7 @@ public static function providerTestStripDangerousProtocols() {
    *   A list of provider data with schemes.
    */
   protected function dataEnhanceWithScheme(array $urls) {
-    $url_schemes = ['http', 'https', 'ftp'];
+    $url_schemes = ['http://', 'https://', 'ftp://'];
     $data = [];
     foreach ($url_schemes as $scheme) {
       foreach ($urls as $url) {
