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.5

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.5
File Size Uploaded
fast5ever-0.1.5.tar.gz 33.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for fast5ever 0.1.5
File
fast5ever-0.1.5-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.5-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
fast5ever-0.1.5-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.5-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
fast5ever-0.1.5-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.5-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
fast5ever-0.1.5-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.5-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.5.tar.gz

Download URL fast5ever-0.1.5.tar.gz
Size 33.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a4291fd7b5926d5447c78d8ff47612f33d034f50c0052d842a95041dfa2d9952
BLAKE2b-256 checksum
How to use checksums
2c2e0ba0ae99ba2754f0d198df7c2789d2ee8cc4e30e4a93974cc1ee0ab36925
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.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 545.5 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
1534b8fe0a0e781bf822a8427f45971e00c0d3d5a18b700c9ce2226951c8446f
BLAKE2b-256 checksum
How to use checksums
b3dad3a249f02f6dca8ae8f5f6ea3c6ed6d2d285b8ee59d662b62c8af6f8c674
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.5-cp313-cp313-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.5-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
e047b5973a93cd271fcd145af47eb78ef83d23b824bd93fa90fb029006c70708
BLAKE2b-256 checksum
How to use checksums
4d3e54449d1cdf767169e3cbd3e0da8f7f4458d4fe5380ac89dd185cb152bcf9
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.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 545.2 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
262344e816175c1c16a8320070a9c5cf37066b021af9fa70e9c84a680dfcfda1
BLAKE2b-256 checksum
How to use checksums
9a8bf6b5fbd29184216f35c8000afff8d0b7894dc250e983d8c00c18c8a8c87b
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.5-cp312-cp312-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.5-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
a5d584bb14b1659e165a9f2037bce422687bbabb84b56d2eb829288046597629
BLAKE2b-256 checksum
How to use checksums
f82d4deb4510f992fc3e27852da10c7ca443c859b1479d3c05ba88f95ca8ae68
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.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 546.4 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
e7140e816c2c38e804beb8fc9d243e447784a0eeb10ec8296715c0bac2da951c
BLAKE2b-256 checksum
How to use checksums
ad4177c78dd965e76c08ae8e73cb180cceee2efd969f053107d9dacd0fddbd0a
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.5-cp311-cp311-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.5-cp311-cp311-macosx_11_0_arm64.whl
Size 499.5 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
93f6da9b5facf7314a571a23adfe5d4cba2ee8444d834d38044f536169a2d58b
BLAKE2b-256 checksum
How to use checksums
5bd13176bdfdc2b68fbf3f03dadfcf42f8ff0ad6297aa39630b5cbddde7c6f6c
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.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 546.6 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
0f0662445a93b39aa0d579320b0105569ce7acb3ec4702bd9bc3203399b271ee
BLAKE2b-256 checksum
How to use checksums
4d20789c5adbc69418447a2e83cc9bc7b87b7550b334b362bc0f2f4634441c55
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.5-cp310-cp310-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.5-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
f68e8e61c46f767853433ebebe838efdc83f8d0dc72e58ed99b70b35da78d520
BLAKE2b-256 checksum
How to use checksums
3bd3c057aa92e75c74b64b23e0ce111e84444380efa6fe0a5b4fdc57407eb9aa
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

0.1.6

9 release files

This release

0.1.5 This release

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