skip to navigation
skip to content

rfc3986 0.2.0

Validating URI References per RFC 3986

Latest Version: 0.4.1

A Python implementation of RFC 3986 including validation and authority parsing. Coming soon: Reference Resolution.


Simply use pip to install rfc3986 like so:

pip install rfc3986

Example Usage

To parse a URI into a convenient named tuple, you can simply:

from rfc3986 import uri_reference

example = uri_reference('')
email = uri_reference('')
ssh = uri_reference('ssh://')

With a parsed URI you can access data about the components:

print(example.scheme)  # => http
print(email.path)  # =>
print(ssh.userinfo)  # => user
print(  # =>
print(ssh.port)  # => 29418

It can also parse URIs with unicode present:

uni = uri_reference(b'\xe2\x98\x83')  # ☃
print(uni.query)  # utf8=%E2%98%83

With a parsed URI you can also validate it:

if ssh.is_valid():['git', 'clone', ssh.unsplit()])

You can also take a parsed URI and normalize it:

mangled = uri_reference('hTTp://exAMPLe.COM')
print(mangled.scheme)  # => hTTp
print(mangled.authority)  # => exAMPLe.COM

normal = mangled.normalize()
print(normal.scheme)  # => http
print(mangled.authority)  # =>

But these two URIs are (functionally) equivalent:

if normal == mangled:

Your paths, queries, and fragments are safe with us though:

mangled = uri_reference('hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth')
normal = mangled.normalize()
assert normal == 'hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth'
assert normal == ''
assert normal != ''

If you do not actually need a real reference object and just want to normalize your URI:

from rfc3986 import normalize_uri

assert (normalize_uri('hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth') ==

You can also very simply validate a URI:

from rfc3986 import is_valid_uri

assert is_valid_uri('hTTp://exAMPLe.COM/Some/reallY/biZZare/pAth')

Requiring Components

You can validate that a particular string is a valid URI and require independent components:

from rfc3986 import is_valid_uri

assert is_valid_uri('http://localhost:8774/v2/resource',

# Assert that a mailto URI is invalid if you require an authority
# component
assert is_valid_uri('', require_authority=True) is False

If you have an instance of a URIReference, you can pass the same arguments to URIReference#is_valid, e.g.,

from rfc3986 import uri_reference

http = uri_reference('http://localhost:8774/v2/resource')
assert uri.is_valid(require_scheme=True,

# Assert that a mailto URI is invalid if you require an authority
# component
mailto = uri_reference('')
assert uri.is_valid(require_authority=True) is False


  • rfc3987

    This is a direct competitor to this library, with extra features, licensed under the GPL.

  • uritools

    This can parse URIs in the manner of RFC 3986 but provides no validation and only recently added Python 3 support.

  • Standard library’s urlparse/urllib.parse

    The functions in these libraries can only split a URI (valid or not) and provide no validation.


This project follows and enforces the Python Software Foundation’s Code of Conduct.

If you would like to contribute but do not have a bug or feature in mind, feel free to email Ian and find out how you can help.

0.2.0 – 2014-06-30

  • Add support for requiring components during validation. This includes adding parameters require_scheme, require_authority, require_path, require_path, require_query, and require_fragment to rfc3986.is_valid_uri and URIReference#is_valid.

0.1.0 – 2014-06-27

  • Initial Release includes validation and normalization of URIs
File Type Py Version Uploaded on Size
rfc3986-0.2.0-py2-none-any.whl (md5) Python Wheel 2.7 2014-06-30 15KB
rfc3986-0.2.0.tar.gz (md5) Source 2014-06-30 14KB