Skip to main content
The urllib package provides modules for working with URLs.

Module Import

from urllib import request, parse, error
from urllib.request import urlopen
from urllib.parse import urlparse, urlencode

Making Requests

urlopen() - Open URL

from urllib.request import urlopen

# GET request
with urlopen('http://example.com') as response:
    html = response.read()
    print(html.decode('utf-8'))

# With timeout
with urlopen('http://example.com', timeout=10) as response:
    data = response.read()

Request with Headers

from urllib.request import Request, urlopen

# Create request with headers
req = Request('http://example.com')
req.add_header('User-Agent', 'MyApp/1.0')
req.add_header('Accept', 'application/json')

with urlopen(req) as response:
    data = response.read()

POST Request

from urllib.request import Request, urlopen
from urllib.parse import urlencode

# Prepare POST data
data = urlencode({'key': 'value', 'name': 'Alice'})
data = data.encode('utf-8')

# Create POST request
req = Request('http://example.com/api', data=data)
req.add_header('Content-Type', 'application/x-www-form-urlencoded')

with urlopen(req) as response:
    result = response.read()

URL Parsing

urlparse() - Parse URL

from urllib.parse import urlparse

url = 'https://example.com:8080/path/to/page?key=value&foo=bar#section'
parsed = urlparse(url)

print(parsed.scheme)    # 'https'
print(parsed.netloc)    # 'example.com:8080'
print(parsed.path)      # '/path/to/page'
print(parsed.query)     # 'key=value&foo=bar'
print(parsed.fragment)  # 'section'

urlencode() - Encode Parameters

from urllib.parse import urlencode, quote, unquote

# Encode dictionary to query string
params = {'name': 'Alice', 'age': 30, 'city': 'New York'}
query_string = urlencode(params)
print(query_string)  # 'name=Alice&age=30&city=New+York'

# URL encode/decode
encoded = quote('Hello World!')  # 'Hello%20World%21'
decoded = unquote('Hello%20World%21')  # 'Hello World!'

urljoin() - Join URLs

from urllib.parse import urljoin

base = 'http://example.com/path/page.html'

print(urljoin(base, 'other.html'))  
# 'http://example.com/path/other.html'

print(urljoin(base, '/absolute/path'))  
# 'http://example.com/absolute/path'

print(urljoin(base, 'http://other.com/page'))  
# 'http://other.com/page'

Error Handling

from urllib.request import urlopen
from urllib.error import URLError, HTTPError

try:
    with urlopen('http://example.com/nonexistent') as response:
        data = response.read()
except HTTPError as e:
    print(f"HTTP Error: {e.code} {e.reason}")
except URLError as e:
    print(f"URL Error: {e.reason}")

Downloading Files

from urllib.request import urlretrieve

# Download file
url = 'http://example.com/file.pdf'
local_file, headers = urlretrieve(url, 'downloaded_file.pdf')
print(f"Downloaded to {local_file}")

Query String Parsing

from urllib.parse import parse_qs, parse_qsl

query = 'name=Alice&age=30&hobby=reading&hobby=coding'

# Parse as dictionary
params = parse_qs(query)
print(params)  
# {'name': ['Alice'], 'age': ['30'], 'hobby': ['reading', 'coding']}

# Parse as list of tuples
params = parse_qsl(query)
print(params)  
# [('name', 'Alice'), ('age', '30'), ('hobby', 'reading'), ('hobby', 'coding')]

Practical Examples

Simple API Client

from urllib.request import Request, urlopen
from urllib.parse import urlencode
import json

def api_get(url, params=None):
    if params:
        url = f"{url}?{urlencode(params)}"
    
    req = Request(url)
    req.add_header('Accept', 'application/json')
    
    with urlopen(req) as response:
        return json.loads(response.read())

def api_post(url, data):
    req = Request(url)
    req.add_header('Content-Type', 'application/json')
    req.data = json.dumps(data).encode('utf-8')
    
    with urlopen(req) as response:
        return json.loads(response.read())

# Usage
result = api_get('http://api.example.com/users', {'page': 1})

Download with Progress

from urllib.request import urlopen

def download_file(url, filename):
    with urlopen(url) as response:
        total_size = int(response.headers.get('Content-Length', 0))
        downloaded = 0
        
        with open(filename, 'wb') as f:
            while True:
                chunk = response.read(8192)
                if not chunk:
                    break
                
                f.write(chunk)
                downloaded += len(chunk)
                
                if total_size:
                    percent = (downloaded / total_size) * 100
                    print(f"\rDownloading: {percent:.1f}%", end='')
        
        print("\nDownload complete!")

download_file('http://example.com/file.zip', 'file.zip')
For modern HTTP client functionality, consider using the requests library instead of urllib.

http

HTTP modules

socket

Low-level networking

json

JSON encoding/decoding

Build docs developers (and LLMs) love