Skip to main content

fast5ever

fast5ever parses HTML into a mutable DOM for Python programs. You can inspect and edit nodes, construct elements, and serialize the result as HTML. It uses Servo's html5ever for WHATWG-compliant parsing and serialization.

html5ever implements the specification's algorithms and requires a separate tree implementation. fast5ever supplies an arena-based DOM and Python bindings. Parsing, error recovery, and serialization follow the same algorithms and produce the same results as a browser's innerHTML.

from fast5ever import parse, parse_fragment

frag = parse_fragment('<p>one<p>two')
frag.to_html()                        # '<p>one</p><p>two</p>'
[c.name for c in frag.children]       # ['p', 'p']
frag.children[0].attrs['class'] = 'lead'   # attrs is live: writes go straight to the tree

from fast5ever import Span
frag.children[0].replace(Span('replacement', cls='lead'))

doc = parse('<!DOCTYPE html><title>t</title>hello')
doc.to_html()                         # '<!DOCTYPE html><html><head><title>t'...

API

parse(html) parses a complete document. parse_fragment(html, context='body') parses a fragment in a context element. For example, use context='tbody' to parse table rows. Both functions return a Document node.

Nodes and attributes

Every node is a Document, Element, Text, Comment, or Doctype. These classes inherit from Node. Use isinstance(c, Text) to check a node's type.

All nodes provide .name, .children, .parent, to_html(), and to_text(). An element's .name is its tag name. Other node names are #document, #text, #comment, and #doctype. Assigning el.name = 'details' renames an element in place and preserves its attributes and children.

For element queries:

  • .element_children returns direct element children in order, including SVG/MathML elements but excluding text and comments. It does not enter template contents; use template.content.element_children for those.
  • el.is_tag('a') matches an HTML anchor, not an SVG anchor. Pass a namespace URL explicitly for foreign elements: el.is_tag('a', namespace='http://www.w3.org/2000/svg'). Names are case-sensitive; .name remains the local name regardless of namespace.
  • el.has_class('lead') checks a complete, case-sensitive class token, separated by HTML's ASCII whitespace. Non-elements return False for both predicates.

An undefined Python property reads the corresponding HTML attribute, with underscores converted to hyphens. For example, el.data_op reads data-op. An absent attribute raises AttributeError. Write attributes through .attrs.

el.attrs is a live mapping in source order. It supports the following operations:

  • Read, set, and delete entries with attrs['k'], attrs['k'] = v, and del attrs['k'].
  • Use in, len, and iteration as with a dictionary.
  • Call get, keys, values, items, update, and pop.
  • Compare with any mapping using ==, or take a snapshot with dict(attrs).

On non-element nodes, .attrs reads as an empty mapping and rejects writes.

.text contains a text or comment node's own content. Assign to it with t.text = 'new'. template.content returns a <template> element's contents as a Document.

Constructing elements

Element(name, attrs=None), Text(text), and Comment(text) construct detached nodes for insertion.

Undefined capitalized module attributes create element factories using fastcore.xml naming conventions. For example, from fast5ever import CustomTag provides a factory for <custom-tag>. Calling CustomTag('text', cls='x', data_kind='demo') constructs <custom-tag class="x" data-kind="demo">text</custom-tag>.

Positional strings become escaped Text nodes. Positional nodes remain nodes. fastcore.xml.Safe and fastcore.basics.NotStr values contain trusted markup. The constructor parses these as fragments in the new element's context, including the context required for table children.

Changing the tree

Use these methods to insert, replace, or remove nodes:

  • append_child(child) appends a child.
  • insert_before(child, reference) inserts a child before a reference node.
  • replace_child(new, old) replaces a child.
  • old.replace(new) is shorthand for old.parent.replace_child(new, old).
  • el.unwrap() replaces an element with its contents.
  • detach() removes a node from its parent.

Inserting a Document inserts its children, following DocumentFragment semantics. For example, old.replace(parse_fragment(markup)) replaces old with the parsed markup. Inserting a node from another tree deep-copies it. Node handles stay valid across all mutations.

The API uses WHATWG DOM terminology. Its Python node classes, live attribute mapping, to_html(), and to_text() are modeled on Emil Stenström's JustHTML.

Serialization and nesting

fast5ever uses html5ever's implementation of the WHATWG serialization algorithm. Its output matches Chrome's innerHTML byte for byte. The output conventions include:

  • Boolean attributes have empty values, such as open="".
  • Attribute values use double quotes.
  • Void elements have no closing /.
  • Text inside script and style remains unescaped.

fast5ever provides no serialization formatting options or compatibility shims for other serializers.

Parsing flattens element nesting beyond 512 levels, matching Chromium's limit. This keeps parsing linear-time for deeply nested input. html5ever's tree builder alone takes quadratic time for that input.

The Rust API

The Python API binds to the fast5ever Rust crate. Add the crate as a dependency with fast5ever = { git = "https://github.com/AnswerDotAI/fast5ever" }.

Both APIs provide the same tree operations. In Rust, you hold a Dom containing a Vec-indexed arena and address its nodes by NodeId. There are no separate node objects. Node 0 (DOCUMENT) is always the document. Every id stays valid for the life of the Dom, including after tree mutations.

use fast5ever::{parse_fragment, DOCUMENT};

let mut dom = parse_fragment("<p>one<p>two", "body");
let p = dom.children(DOCUMENT)[0];
dom.set_attr(p, "class", "lead").unwrap();
let extra = parse_fragment("<b>!</b>", "body");
let extra = dom.import(&extra, DOCUMENT);   // cross-tree moves go through an explicit import
dom.append_child(p, extra).unwrap();        // a document node splices its children, as in Python
assert_eq!(dom.to_html(DOCUMENT), r#"<p class="lead">one<b>!</b></p><p>two</p>"#);

Read methods use the Python names: children, parent, attr, to_html, and to_text. Mutation methods return Result where Python raises an exception. These include set_attr, set_text, append_child, insert_before, replace_child, and detach.

Element queries are dom.element_children(id), dom.tag(id) (the local name, or None for non-elements), dom.is_tag(id, "a", None) (None selects HTML; Some(url) selects another namespace), and dom.has_class(id, "lead").

Construct nodes with create_element, create_text, and create_comment, corresponding to Python's Element, Text, and Comment. Rust also provides NodeData matching for direct tree inspection.

Development

pip install -e .[dev]
maturin develop && pytest -q

All tests use pytest. cargo check and cargo clippy run without warnings and do not need Python. The python feature enables pyo3.

Release

ship-release pushes a tag for CI to publish, then bumps the version.

maturin develop && pytest -q
ship-release

The GitHub workflow builds wheels on tags matching v* and publishes them to GitHub Releases and PyPI.

Release files for fast5ever 0.1.6

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

Source distribution (sdist)

Source distribution for fast5ever 0.1.6
File Size Uploaded
fast5ever-0.1.6.tar.gz 32.9 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for fast5ever 0.1.6
File
fast5ever-0.1.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.6-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
fast5ever-0.1.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.6-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
fast5ever-0.1.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.6-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
fast5ever-0.1.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.6-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details

Total release size: 4.2 MB

Release files / fast5ever-0.1.6.tar.gz

Download URL fast5ever-0.1.6.tar.gz
Size 32.9 kB
Tags Source
SHA-256 checksum
How to use checksums
e3338378a432ed3e792202d92fd5625a79e92a7bdb0001a8ee781724e85dffb2
BLAKE2b-256 checksum
How to use checksums
9bdef1a3314bfd62eb85af23a7ddc0af95aa8b1be8f4e7aadd6ae0e302c9c354
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 545.4 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
96a642354a19855f006584579e60230de67022c0fc05e2057250b88e7a821b06
BLAKE2b-256 checksum
How to use checksums
590a5dc98f9901c92cc8ec422403266277642db55b1077d9fa013a29becc8aac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp313-cp313-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.6-cp313-cp313-macosx_11_0_arm64.whl
Size 498.2 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9c656fca77e77ee1c4a60ca6e8c1c26509371bf8aaf7eda01f5685865e7d331d
BLAKE2b-256 checksum
How to use checksums
b4994cf96bd0da18dbfcb65d1c6a1718ed64adc8938800ac3a7adb826bd30bf4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 545.1 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
7f8f2eeccf63a53fa2ef16a55712ac4b931b757400bd2e2fc84482351833539e
BLAKE2b-256 checksum
How to use checksums
d9c36138dd85f738fafc4a77b10ebcbfde7d0acc0ff0890d64d0fee984f836a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp312-cp312-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.6-cp312-cp312-macosx_11_0_arm64.whl
Size 498.1 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f8352ea2fc568828c9082734df389d1ea57770e88ac95b529d77217b9d37c4fd
BLAKE2b-256 checksum
How to use checksums
83729eec34122c5b276345c305c7575e72ae0474dda53e7f52cb69ee7ba0f365
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 546.2 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
55d1817f6b509a206318cff09de90e0e8b6eefd7b041001a34253beb4867b292
BLAKE2b-256 checksum
How to use checksums
d51a5b60de328e12ceceada3b8fbbbbbc1eccccfa8acbe7b931238702666ade1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp311-cp311-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.6-cp311-cp311-macosx_11_0_arm64.whl
Size 499.4 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e64d97233d9bb444beba7246c8257e24bf78128b1eeb04d01058521dee35bf17
BLAKE2b-256 checksum
How to use checksums
5e146a379fac9146bf7c9b675d9ef1547ddf9f91cc9db50712555b2c9c5cc3ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 546.4 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
f8e491eaed6eceed18c9cbe39cc62693f61eebea47fa16071c482ba3db7720e5
BLAKE2b-256 checksum
How to use checksums
0066f181b40e5baeb87420a7eda53a273fc0bf6b6901641b13069ea08261f205
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release files / fast5ever-0.1.6-cp310-cp310-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.6-cp310-cp310-macosx_11_0_arm64.whl
Size 499.6 kB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
793f05f9efe9f3e7ab139e31126ff760ac6fe150549b4fd5df44d17cf43299c0
BLAKE2b-256 checksum
How to use checksums
e23df35e2ecb0455495d2bc32c625a96c96c17a7a70591e3a2c8b2d7c75ebab5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.6 This release

9 release files

0.1.5

9 release files

0.1.4

9 release files

0.1.3

9 release files

0.1.2

9 release files

0.1.1

9 release files

0.1.0

9 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