diff --git a/mistune/util.py b/mistune/util.py
index <HASH>..<HASH> 100644
--- a/mistune/util.py
+++ b/mistune/util.py
@@ -20,7 +20,12 @@ def escape(s, quote=True):
 
 
 def escape_url(link):
-    safe = '/#:()*?=%@+,&'
+    safe = (
+        ':/?#@'           # gen-delims - '[]' (rfc3986)
+        '!$&()*+,;='      # sub-delims - "'" (rfc3986)
+        '%'               # leave already-encoded octets alone
+    )
+
     if html is None:
         return quote(link.encode('utf-8'), safe=safe)
     return html.escape(quote(html.unescape(link), safe=safe))
Make mistune.util.escape_url less aggressive

This adds ';', '!', and '$' to the set of characters which will be
passed unmolested by escape_url.  These are all in RFC <I> reserved
character list — that is to say: escaping these may change the meaning
of a URL.