pywhatwgurl - Python WHATWG URL Parser
Pure Python implementation of the WHATWG URL Standard. The goal is a small, spec-faithful library for parsing, serializing, and manipulating URLs.
pywhatwgurl is listed as a complete Python implementation in the official WHATWG URL repository.
Status
- 100% WHATWG URL Standard conformance for core URL parsing
- Full
URLandURLSearchParamsAPI implementation - See Conformance for IDNA limitations
Installation
Requires Python 3.10+.
pip install pywhatwgurl
Quickstart
from pywhatwgurl import URL
url = URL("https://user:pass@example.com:8080/path?q=1#frag")
url.hostname # 'example.com'
url.port # '8080'
url.pathname # '/path'
url.search # '?q=1'
url.hash # '#frag'
str(url) # 'https://user:pass@example.com:8080/path?q=1#frag'
URLSearchParams works just like the browser API:
from pywhatwgurl import URLSearchParams
params = URLSearchParams("a=1&b=2&a=3")
params.get("a") # '1'
params.get_all("a") # ('1', '3')
params.set("b", "42")
str(params) # 'a=1&b=42&a=3'
For full API details, see the documentation.
Development
To set up a local development environment, use uv (recommended) or pip:
# Clone and install dev dependencies
uv sync --dev
# Run the test suite
uv run pytest
If you prefer pip:
python -m venv .venv && source .venv/bin/activate
pip install -e .
pip install pytest ruff mypy pre-commit interrogate pip-audit cyclonedx-bom
pytest
Conformance
This library targets 100% conformance with the WHATWG URL Standard for core URL parsing, validated against the official Web Platform Tests.
| Test Suite | Status |
|---|---|
| URL parsing (urltestdata) | ✅ 873/873 (100%) |
| URL setters | ✅ 274/274 (100%) |
| URL setters stripping | ✅ 144/144 (100%) |
| URLSearchParams | ✅ 139/139 (100%) |
| Percent-encoding | ✅ 7/7 (100%) |
| IDNA/ToASCII | ⚠️ xfail (see below) |
IDNA Limitations
IDNA tests are marked as expected failures (xfail) because the Python idna library follows stricter RFC 5891/5892 rules than the WHATWG URL Standard's lenient UTS46 processing.
Why not fix these?
- No Python WHATWG-compliant IDNA implementation exists
- Even non-Python implementations with custom IDNA handling still fall short of full compliance
- Real-world domains work correctly — failures are obscure edge cases
For details, see tests/conformance/README.md.
Supply Chain Security
- SBOM: A Software Bill of Materials (CycloneDX JSON) is automatically generated for every release and attached to the GitHub Release.
- Audit: All runtime dependencies are scanned for known vulnerabilities using
pip-auditin our CI pipeline.
Roadmap
- ✅ Implement URL parsing/serialization per WHATWG URL Standard
- ✅ Validate against the official URL test suite (100% conformance)
- Ship a minimal, typed API suitable for frameworks and tooling
WPT URL test data
To pull down the pinned WPT URL resources, use util/wpt_url_test_data.py:
python util/wpt_url_test_data.py download \
--dest_dir tests/conformance/data \
--commit <WPT_URL_COMMIT>
The script downloads the WPT URL JSON resources (including urltestdata, setters, percent-encoding, toascii, and IDNA fixtures), preserves comments, validates schemas, and writes a metadata file with the pinned commit. The scheduled workflow .github/workflows/fetch_test_data.yml runs the same script via the composite action and is keyed on the pinned commit; adjust WPT_URL_COMMIT/WPT_TEST_DATA_PATH in the workflow env if you need a different pin.
Updating the pinned WPT commit
- A helper workflow,
.github/workflows/update_wpt_url.yml, can be triggered manually (or waits for its weekly schedule) to fetch the latesturl/commit from WPT, bump all pins, refresh the fixtures, and open a PR. - To bump manually without the bot:
- Get the latest
url/commit:NEW_COMMIT=$(curl -s https://api.github.com/repos/web-platform-tests/wpt/commits?path=url&per_page=1 | jq -r '.[0].sha') - Set
WPT_URL_COMMITto that value in.github/workflows/main.ymland.github/workflows/fetch_test_data.yml, and update the defaults in.github/workflows/actions/fetch_wpt_url_test_data/action.ymlandutil/wpt_url_test_data.pyto match. - Refresh fixtures:
python util/wpt_url_test_data.py download --dest_dir tests/conformance/data --commit "$NEW_COMMIT" - Commit the workflow and data changes together.
- Get the latest
Building
To build the package distribution (wheel and sdist):
uv build
The artifacts will be generated in the dist/ directory.
Versioning is dynamic and derived from Git tags (e.g., 0.1.0 or 0.1.dev1+...).
Documentation
To build and serve the documentation locally:
# Install docs dependencies
uv sync --group docs
# Serve locally (with live reload)
uv run mkdocs serve
# Build static site
uv run mkdocs build
Documentation is automatically deployed to GitHub Pages when changes are pushed to master.
Metadata
Release files for pywhatwgurl 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pywhatwgurl-0.1.2.tar.gz | 155.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pywhatwgurl-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 182.4 kB
Release files / pywhatwgurl-0.1.2.tar.gz
| Download URL | pywhatwgurl-0.1.2.tar.gz |
|---|---|
| Size | 155.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
762078828fd7df601b5fcc03800080f6b5d8f88e797e9bb210636d46e929a672
|
|
BLAKE2b-256 checksum How to use checksums |
994e7f49c07dc3975cbc575d8318e746f8d727b27af22646d469d683915541c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency logRelease files / pywhatwgurl-0.1.2-py3-none-any.whl
| Download URL | pywhatwgurl-0.1.2-py3-none-any.whl |
|---|---|
| Size | 26.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
13f50da9fe2ea7317ae9a18473badbcfe9eb7048214534168cbaf29a0cbc53b3
|
|
BLAKE2b-256 checksum How to use checksums |
7a881bf5fa63fa9f2e69946ed47a786f78e2f446b279d84492ba431386c4af51
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.
Transparency log