diff --git a/reader/sanitizer/sanitizer.go b/reader/sanitizer/sanitizer.go
index 642fedfd431f81e03065f6980fe77114eee56865..0092bedb54210bcf0e5a3896e96a49e56e97dfb6 100644
--- a/reader/sanitizer/sanitizer.go
+++ b/reader/sanitizer/sanitizer.go
@@ -111,7 +111,7 @@ func sanitizeAttributes(baseURL, tagName string, attributes []html.Attribute) ([
 					continue
 				}
 
-				if !hasValidScheme(value) || isBlacklistedResource(value) {
+				if !hasValidURIScheme(value) || isBlacklistedResource(value) {
 					continue
 				}
 			}
@@ -221,17 +221,19 @@ func hasRequiredAttributes(tagName string, attributes []string) bool {
 	return true
 }
 
-func hasValidScheme(src string) bool {
-	// See https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
+// See https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
+func hasValidURIScheme(src string) bool {
 	whitelist := []string{
-		"apt://",
-		"bitcoin://",
-		"callto://",
+		"apt:",
+		"bitcoin:",
+		"callto:",
+		"dav:",
+		"davs:",
 		"ed2k://",
 		"facetime://",
-		"feed://",
+		"feed:",
 		"ftp://",
-		"geo://",
+		"geo:",
 		"gopher://",
 		"git://",
 		"http://",
@@ -240,27 +242,24 @@ func hasValidScheme(src string) bool {
 		"irc6://",
 		"ircs://",
 		"itms://",
-		"jabber://",
-		"magnet://",
-		"mailto://",
-		"maps://",
-		"news://",
-		"nfs://",
-		"nntp://",
+		"itms-apps://",
+		"magnet:",
+		"mailto:",
+		"news:",
+		"nntp:",
 		"rtmp://",
-		"sip://",
-		"sips://",
-		"skype://",
-		"smb://",
-		"sms://",
-		"spotify://",
+		"sip:",
+		"sips:",
+		"skype:",
+		"spotify:",
 		"ssh://",
 		"sftp://",
 		"steam://",
 		"svn://",
-		"tel://",
+		"svn+ssh://",
+		"tel:",
 		"webcal://",
-		"xmpp://",
+		"xmpp:",
 	}
 
 	for _, prefix := range whitelist {
diff --git a/reader/sanitizer/sanitizer_test.go b/reader/sanitizer/sanitizer_test.go
index 649b7f0211fe6bb924843507167c2438be2cc5e7..1dfa10361fdaec2c9befa7b741e439669db82e29 100644
--- a/reader/sanitizer/sanitizer_test.go
+++ b/reader/sanitizer/sanitizer_test.go
@@ -123,6 +123,234 @@ func TestInvalidURLScheme(t *testing.T) {
 	}
 }
 
+func TestAPTURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="apt:some-package?channel=test">valid</a></p>`
+	expected := `<p>This link is <a href="apt:some-package?channel=test" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestBitcoinURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W">valid</a></p>`
+	expected := `<p>This link is <a href="bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestCallToURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="callto:12345679">valid</a></p>`
+	expected := `<p>This link is <a href="callto:12345679" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestFeedURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="feed://example.com/rss.xml">valid</a></p>`
+	expected := `<p>This link is <a href="feed://example.com/rss.xml" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+
+	input = `<p>This link is <a href="feed:https://example.com/rss.xml">valid</a></p>`
+	expected = `<p>This link is <a href="feed:https://example.com/rss.xml" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output = Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestGeoURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="geo:13.4125,103.8667">valid</a></p>`
+	expected := `<p>This link is <a href="geo:13.4125,103.8667" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestItunesURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="itms://itunes.com/apps/my-app-name">valid</a></p>`
+	expected := `<p>This link is <a href="itms://itunes.com/apps/my-app-name" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+
+	input = `<p>This link is <a href="itms-apps://itunes.com/apps/my-app-name">valid</a></p>`
+	expected = `<p>This link is <a href="itms-apps://itunes.com/apps/my-app-name" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output = Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestMagnetURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&amp;xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7">valid</a></p>`
+	expected := `<p>This link is <a href="magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&amp;xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestMailtoURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="mailto:jsmith@example.com?subject=A%20Test&amp;body=My%20idea%20is%3A%20%0A">valid</a></p>`
+	expected := `<p>This link is <a href="mailto:jsmith@example.com?subject=A%20Test&amp;body=My%20idea%20is%3A%20%0A" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestNewsURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="news://news.server.example/*">valid</a></p>`
+	expected := `<p>This link is <a href="news://news.server.example/*" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+
+	input = `<p>This link is <a href="news:example.group.this">valid</a></p>`
+	expected = `<p>This link is <a href="news:example.group.this" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output = Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+
+	input = `<p>This link is <a href="nntp://news.server.example/example.group.this">valid</a></p>`
+	expected = `<p>This link is <a href="nntp://news.server.example/example.group.this" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output = Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestRTMPURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="rtmp://mycompany.com/vod/mp4:mycoolvideo.mov">valid</a></p>`
+	expected := `<p>This link is <a href="rtmp://mycompany.com/vod/mp4:mycoolvideo.mov" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestSIPURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="sip:+1-212-555-1212:1234@gateway.com;user=phone">valid</a></p>`
+	expected := `<p>This link is <a href="sip:+1-212-555-1212:1234@gateway.com;user=phone" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+
+	input = `<p>This link is <a href="sips:alice@atlanta.com?subject=project%20x&amp;priority=urgent">valid</a></p>`
+	expected = `<p>This link is <a href="sips:alice@atlanta.com?subject=project%20x&amp;priority=urgent" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output = Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestSkypeURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="skype:echo123?call">valid</a></p>`
+	expected := `<p>This link is <a href="skype:echo123?call" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestSpotifyURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="spotify:track:2jCnn1QPQ3E8ExtLe6INsx">valid</a></p>`
+	expected := `<p>This link is <a href="spotify:track:2jCnn1QPQ3E8ExtLe6INsx" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestSteamURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="steam://settings/account">valid</a></p>`
+	expected := `<p>This link is <a href="steam://settings/account" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestSubversionURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="svn://example.org">valid</a></p>`
+	expected := `<p>This link is <a href="svn://example.org" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+
+	input = `<p>This link is <a href="svn+ssh://example.org">valid</a></p>`
+	expected = `<p>This link is <a href="svn+ssh://example.org" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output = Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestTelURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="tel:+1-201-555-0123">valid</a></p>`
+	expected := `<p>This link is <a href="tel:+1-201-555-0123" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestWebcalURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="webcal://example.com/calendar.ics">valid</a></p>`
+	expected := `<p>This link is <a href="webcal://example.com/calendar.ics" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
+func TestXMPPURIScheme(t *testing.T) {
+	input := `<p>This link is <a href="xmpp:user@host?subscribe&amp;type=subscribed">valid</a></p>`
+	expected := `<p>This link is <a href="xmpp:user@host?subscribe&amp;type=subscribed" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">valid</a></p>`
+	output := Sanitize("http://example.org/", input)
+
+	if expected != output {
+		t.Errorf(`Wrong output: "%s" != "%s"`, expected, output)
+	}
+}
+
 func TestBlacklistedLink(t *testing.T) {
 	input := `<p>This image is not valid <img src="https://stats.wordpress.com/some-tracker"></p>`
 	expected := `<p>This image is not valid </p>`
diff --git a/url/url_test.go b/url/url_test.go
index 54868a925d95809be288b9651103d774cc8ccfd7..56b6e13cd3364e7507d67527b6c64ab4809e293b 100644
--- a/url/url_test.go
+++ b/url/url_test.go
@@ -13,6 +13,8 @@ func TestAbsoluteURL(t *testing.T) {
 		[]string{"https://example.org/path/file.ext", "https://example.org/folder", "path/file.ext"},
 		[]string{"https://example.org/path/file.ext", "https://example.org/folder/", "https://example.org/path/file.ext"},
 		[]string{"https://static.example.org/path/file.ext", "https://www.example.org/", "//static.example.org/path/file.ext"},
+		[]string{"magnet:?xt=urn:btih:c12fe1c06bba254a9dc9f519b335aa7c1367a88a", "https://www.example.org/", "magnet:?xt=urn:btih:c12fe1c06bba254a9dc9f519b335aa7c1367a88a"},
+		[]string{"magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7", "https://www.example.org/", "magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C&xt.2=urn:sha1:TXGCZQTH26NL6OUQAJJPFALHG2LTGBC7"},
 	}
 
 	for _, scenario := range scenarios {