Skip to main content

jsurl

A Python implementation of the JavaScript URL and URLSearchParams APIs, bringing familiar web development patterns to Python.

Features

  • JavaScript-compatible API: Use the same URL manipulation patterns you know from JavaScript
  • Full URL parsing: Support for all URL components including protocol, hostname, port, pathname, search, and hash
  • URLSearchParams: Complete implementation of the URLSearchParams interface for query string manipulation
  • Type hints: Full type annotation support for better IDE integration
  • Immutable-friendly: Clean API design that supports both mutable and immutable usage patterns
  • Pure Python: No external dependencies, pure Python implementation for maximum compatibility

Installation

pip install jsurl

Quick Start

Basic URL Parsing

from jsurl import URL

# Parse a URL
url = URL("https://example.com:8080/path?query=value#section")

print(url.protocol)  # "https:"
print(url.hostname)  # "example.com"
print(url.port)      # "8080"
print(url.pathname)  # "/path"
print(url.search)    # "?query=value"
print(url.hash)      # "#section"

URL Manipulation

from jsurl import URL

url = URL("https://example.com/api")

# Modify components
url.pathname = "/v2/users"
url.search = "?limit=10&page=1"

print(url.href)  # "https://example.com/v2/users?limit=10&page=1"

# Path joining with / operator
api_url = URL("https://api.example.com/v1")
users_url = api_url / "users"
user_url = users_url / "123"

print(user_url.href)  # "https://api.example.com/v1/users/123"

Working with Query Parameters

from jsurl import URL, URLSearchParams

# Using URLSearchParams directly
params = URLSearchParams.from_string("name=John&age=30&city=Tokyo")

print(params.get("name"))     # "John"
print(params.get_all("tag"))  # []

params.append("tag", "python")
params.append("tag", "web")
print(params.get_all("tag"))  # ["python", "web"]

# Using search_params on URL
url = URL("https://example.com/search")
url.search_params.set("q", "python url parsing")
url.search_params.set("limit", "50")

print(url.href)  # "https://example.com/search?q=python%20url%20parsing&limit=50"

Authentication URLs

from jsurl import URL

url = URL("https://user:password@api.example.com/secure")

print(url.username)  # "user"
print(url.password)  # "password"
print(url.host)      # "api.example.com"
print(url.origin)    # "https://api.example.com"

IPv6 Support

from jsurl import URL

# IPv6 addresses are properly handled
url = URL("https://[2001:db8::1]:8080/path")

print(url.hostname)  # "[2001:db8::1]"
print(url.port)      # "8080"
print(url.host)      # "[2001:db8::1]:8080"

API Reference

URL Class

Properties

  • protocol: URL scheme (e.g., "https:")
  • username: Username for authentication
  • password: Password for authentication
  • hostname: Domain name or IP address
  • port: Port number as string
  • pathname: Path portion of URL
  • search: Query string including "?"
  • hash: Fragment identifier including "#"
  • search_params: URLSearchParams instance for query manipulation
  • host: hostname:port combination
  • origin: protocol + "//" + host
  • href: Complete URL string

Methods

  • URL(url): Constructor accepting string or URL instance
  • url / path: Join path components using / operator

URLSearchParams Class

Methods

  • URLSearchParams.from_string(query): Create from query string
  • get(key): Get first value for key
  • get_all(key): Get all values for key as list
  • set(key, value): Set single value (replaces existing)
  • append(key, value): Add value (preserves existing)
  • delete(key): Remove all values for key
  • key in params: Check if key exists
  • params[key]: Get all values (same as get_all)
  • params[key] = value: Set value (same as set)

Use Cases

Web Scraping

from jsurl import URL

base_url = URL("https://api.example.com/v1")

# Build API endpoints
users_endpoint = base_url / "users"
users_endpoint.search_params.set("page", "1")
users_endpoint.search_params.set("limit", "100")

response = requests.get(str(users_endpoint))

Configuration Management

from jsurl import URL

# Parse database URLs
db_url = URL("postgresql://user:pass@localhost:5432/mydb")

DATABASE_CONFIG = {
    'host': db_url.hostname,
    'port': int(db_url.port) if db_url.port else 5432,
    'username': db_url.username,
    'password': db_url.password,
    'database': db_url.pathname.lstrip('/')
}

URL Validation and Normalization

from jsurl import URL

def normalize_api_url(url_string):
    """Normalize API URL format"""
    url = URL(url_string)
    
    # Ensure HTTPS
    if url.protocol == "http:":
        url.protocol = "https"
    
    # Remove default ports
    if url.port == "443" and url.protocol == "https:":
        url.port = None
    elif url.port == "80" and url.protocol == "http:":
        url.port = None
    
    # Ensure trailing slash for API endpoints
    if not url.pathname.endswith('/'):
        url.pathname += '/'
    
    return str(url)

Why jsurl?

If you're coming from JavaScript/TypeScript development, you'll feel right at home with jsurl. Instead of learning Python-specific URL libraries, you can use the same patterns you already know:

# Instead of urllib.parse
from urllib.parse import urlparse, parse_qs
parsed = urlparse(url_string)
query_params = parse_qs(parsed.query)

# Use familiar JavaScript patterns
from jsurl import URL
url = URL(url_string)
url.search_params.get('param_name')

Requirements

  • Python 3.10 or higher
  • No external dependencies

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Metadata

Release files for jsurl 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jsurl 0.1.3
File Size Uploaded Provenance Actions
jsurl-0.1.3.tar.gz 18.2 kB Without provenance Details for jsurl-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for jsurl 0.1.3
File Interpreter ABI Platform Actions
jsurl-0.1.3-py3-none-any.whl Python 3 none any Details for jsurl-0.1.3-py3-none-any.whl

Total release size: 25.3 kB

Release files / jsurl-0.1.3.tar.gz

Download URL jsurl-0.1.3.tar.gz
Size 18.2 kB
Tags Source
SHA-256 checksum
How to use checksums
4f2a01d8dfbabb695751ee0f2d9adbf0cfdfe5ffc3a15ce53eaa13f6e4a576ed
BLAKE2b-256 checksum
How to use checksums
dcc59d13b43a9ce3ceba358664df33ec34b7c2aba8581034287e3e47710f529c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.0

Release files / jsurl-0.1.3-py3-none-any.whl

Download URL jsurl-0.1.3-py3-none-any.whl
Size 7.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e507b23e5508e874509ac1d8f1c50a3fca7f8cb61a71a0506016d66425ff8b4
BLAKE2b-256 checksum
How to use checksums
e9851dab74f0d69b7837296ec4bd6f305ae48d743d212aec92440fd215ef46a2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.6.0

Security for jsurl 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page