Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

soup5ever

A BeautifulSoup 4 tree builder backed by Rust's html5ever. Same HTML5 trees as BeautifulSoup(html, "html5lib"), 6–14x faster.

from bs4 import BeautifulSoup
import soup5ever

soup = BeautifulSoup(html, "html5ever")

Installation

pip install soup5ever

Wheels for Linux (x86_64, aarch64; glibc and musl) and macOS (arm64), one abi3 wheel per platform for CPython 3.10+. The only dependency is beautifulsoup4>=4.13; no Rust, libxml2 or html5lib needed.

Usage

Importing soup5ever registers the "html5ever" parser (also "soup5ever"). The generic features "html5" and "html" are registered at the lowest priority, so importing it doesn't change what BeautifulSoup(markup, "html5") or BeautifulSoup(markup) select.

The usual options work (from_encoding, element_classes, multi_valued_attributes, store_line_numbers, attribute_dict_class). Like html5lib, parse_only isn't supported.

Compatibility

The target is BeautifulSoup(html, "html5lib"); where html5lib and the HTML standard disagree, soup5ever follows the standard.

  • BS4's own tests for its html5lib builder: 93/93 pass.
  • html5lib-tests tree construction: 1,588/1,592 match the spec. Against html5lib the trees are identical in 1,417 cases; the other 175 are classified automatically (167 html5lib behind the spec, 4 BS4 html5lib-adapter bugs, 4 <selectedcontent> misses both share).
  • 182 targeted differential cases and ~23k fuzz inputs (triaged with Chromium): every remaining difference is an html5lib bug or listed below.

Differences from html5lib:

  • Current HTML standard where html5lib 1.1 (2020) is behind: the 2025 <select> rules, <template> in <head>, </p> in SVG/MathML, <main>/<summary>, <search>, <dialog>, ruby. See tests/corpus.py for each case.
  • BS4's html5lib adapter never applies the Noah's Ark clause (AttrList has no __eq__); soup5ever does.
  • Undeclared, valid UTF-8 bytes are decoded as UTF-8 (html5lib guesses windows-1252 without chardet). Decoding follows the WHATWG Encoding Standard, not Python's codecs.
  • Lone surrogates in a str become U+FFFD.
  • sourceline/sourcepos match html5lib for ~98.5% of elements.

Shared with html5lib: no parse_only, no Script/Stylesheet string subclasses, no <selectedcontent> cloning.

Benchmarks

BeautifulSoup(markup, parser) on an in-memory str, median of 7 rounds, 4-vCPU Linux VM, CPython 3.11:

document html5lib html5ever speedup
small page (3 KiB) 2.4 ms 250 µs 9.6x
large page (1.2 MiB) 888 ms 101 ms 8.8x
malformed tag soup 483 ms 34 ms 14.2x
deeply nested 243 ms 26 ms 9.3x
table-heavy 507 ms 69 ms 7.3x
SVG/MathML-heavy 323 ms 51 ms 6.4x

Parsing in Rust is 14–32% of soup5ever's time; the rest is BeautifulSoup's own object constructors. To reproduce:

uv pip install -e .[dev]
python benchmarks/run.py

Development

uv venv venv && source venv/bin/activate
uv pip install -e .[dev]                # builds the Rust extension
python scripts/fetch_upstream_tests.py  # BS4's builder tests + html5lib-tests
pytest

Re-run uv pip install -e .[dev] after changing Rust code.

edwh fmt && edwh lint                   # Python (ruff)
cargo fmt && cargo clippy               # Rust (lint levels in Cargo.toml)

pytest includes a 3000-input differential fuzz run; pytest --fuzz 20000 --fuzz-seed 7 runs a bigger one.

License

MIT

Metadata

Release files for soup5ever 0.0.1b1

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

Source distribution (sdist)

Source distribution for soup5ever 0.0.1b1
File Size Uploaded
soup5ever-0.0.1b1.tar.gz 74.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for soup5ever 0.0.1b1
File Interpreter ABI Platform
soup5ever-0.0.1b1-cp310-abi3-manylinux_2_34_x86_64.whl CPython 3.10 abi3 Linux glibc 2.34+ x86-64 Details

Total release size: 683.8 kB

Release files / soup5ever-0.0.1b1.tar.gz

Download URL soup5ever-0.0.1b1.tar.gz
Size 74.6 kB
Tags Source
SHA-256 checksum
How to use checksums
b3c40bee09a2962899305e6e5bd5771dbcf4ba522cea5cdbced76aac7b1e38ec
BLAKE2b-256 checksum
How to use checksums
cef26e975d6ae829b1837414b32b1ce435443e3873e7e6938543aa3b363da9da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / soup5ever-0.0.1b1-cp310-abi3-manylinux_2_34_x86_64.whl

Download URL soup5ever-0.0.1b1-cp310-abi3-manylinux_2_34_x86_64.whl
Size 609.2 kB
Tags CPython 3.10 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
1fa42fbde028f8382d8b4df4dbb1a135c46eb31715757007199f8787719f02bf
BLAKE2b-256 checksum
How to use checksums
51f8e3f0db8571e7a64e548ea5beda321b7923b63b3b9ceedac8ce7a1002a537
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release history Release notifications | RSS feed

0.2.0

6 release files

0.1.0

6 release files

This release

0.0.1b1 This release

2 release files

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