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 authenticationpassword: Password for authenticationhostname: Domain name or IP addressport: Port number as stringpathname: Path portion of URLsearch: Query string including "?"hash: Fragment identifier including "#"search_params: URLSearchParams instance for query manipulationhost: hostname:port combinationorigin: protocol + "//" + hosthref: Complete URL string
Methods
URL(url): Constructor accepting string or URL instanceurl / path: Join path components using/operator
URLSearchParams Class
Methods
URLSearchParams.from_string(query): Create from query stringget(key): Get first value for keyget_all(key): Get all values for key as listset(key, value): Set single value (replaces existing)append(key, value): Add value (preserves existing)delete(key): Remove all values for keykey in params: Check if key existsparams[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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.