Install & Compatibility
Where this runs
tested against v2.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.096s · 17.9MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.5s · import 0.092s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Document
✓ from html5tagger import Document
Primary class for generating full HTML5 documents with a DOCTYPE declaration.
E
✓ from html5tagger import E
An empty builder for creating HTML snippets.
HTML
✓ from html5tagger import HTML
Used to wrap preformatted HTML strings to prevent automatic escaping, especially for known safe content.
This quickstart demonstrates how to create a basic HTML5 document using `html5tagger`. It shows how to initialize a `Document` object, add standard HTML elements using attribute access (e.g., `doc.h1`), pass attributes as keyword arguments, nest elements using `with` statements, and utilize template variables for dynamic content. Finally, it shows how to render the complete HTML string.
from html5tagger import Document, E
# Create a full HTML document
doc = Document(
E.TitleText_,
lang="en", # HTML tag attributes as keyword arguments
_urls=["style.css", "script.js"], # Special argument for linking resources
)
# Add elements directly or with context managers
with doc.body:
doc.h1("Welcome to html5tagger!")
with doc.p("This is an example of creating HTML content in Python. It's ") as p:
p.strong("easy")
p(" and ")
p.em("intuitive")
p(".")
# Nesting elements
with doc.ul:
doc.li("No manual closing tags for most elements.")
doc.li("Attributes are passed as keyword arguments.")
doc.li.a(href="https://github.com/sanic-org/html5tagger")("Check out the GitHub repo!")
# Add a paragraph with a dynamic title using template variables
doc.p(doc.IntroText_, id="intro-paragraph")
# Fill in template variables (optional)
doc.TitleText = "My Dynamic Page"
doc.IntroText = "Here's some dynamic content."
# Render the document to an HTML string
html_output = doc.render()
print(html_output)
Debug
Known issues
gotchaAutomatic Tag Closing and Empty Elements: Tags are automatically closed when new content or another tag is added. Setting attributes alone does not close an element. For self-closing or empty elements (e.g., `<script src='...'></script>`) where subsequent content should not be nested, explicitly close with `(None)`.fixTo close an empty element (e.g., `<script>`) or prevent further nesting into an empty tag after setting attributes, pass `None` as the first argument: `doc.script(None, src='path/to/script.js')`.
affects: All versions
gotchaSecurity: Unsafe use of `html5tagger.HTML()` with untrusted input can lead to Cross-Site Scripting (XSS). While content is generally auto-escaped, `html5tagger.HTML(string)` explicitly marks `string` as safe HTML, bypassing escaping.fixNEVER use `html5tagger.HTML()` to wrap user-generated or untrusted content. Only use it for HTML strings that you have explicitly verified as safe. All other content should be passed directly to HTML5Tagger elements for automatic escaping.
affects: All versions
gotchaTemplating behavior: When using template variables, `doc.TemplateName_` does NOT close the preceding tag but inserts the variable's content *inside* any currently open element. This differs from how new tag calls (`doc.p(...)`) close prior tags.fixBe mindful of the current nesting context when inserting template variables. If the variable should be at a different level, ensure the preceding elements are correctly closed by adding content or explicit `(None)` calls before inserting the template.
affects: All versions supporting templating (v1.2.0+)
deprecatedPotential deprecation of non-underscored `_script` and `_style` methods: The introduction of `_script` and `_style` special methods in 2023 suggests a potential future shift to primarily use underscored versions for special element handling, with the non-underscored versions potentially being deprecated or changed.fixWhile not yet deprecated, consider using `_script` and `_style` for clarity and future compatibility if explicitly handling script/style blocks. Consult the latest documentation for definitive guidance on these methods.
affects: v1.2.0+
Errors
Common errors & fixes
AttributeError: 'Builder' object has no attribute 'class'
Python reserved keywords like 'class' cannot be directly used as HTML attribute names; they need to be escaped.
fixAppend an underscore to the reserved keyword to use it as an attribute, e.g., `E.div(class_='my-class')` instead of `E.div(class='my-class')`.
NameError: name 'E' is not defined
The 'E' object, which is the main entry point for creating HTML snippets, was not imported from the html5tagger library.
fixAdd `from html5tagger import E` at the beginning of your Python file to import the builder object.
ModuleNotFoundError: No module named 'html5tagger'
The 'html5tagger' library is not installed in your Python environment.
fixInstall the library using pip: `pip install html5tagger`
TypeError: 'Builder' object is not callable
This error occurs if you try to call a method on a Builder object without providing content, or if you attempt to use an attribute as a method when it's meant to be an attribute setter.
fixEnsure you are correctly chaining calls for content or attributes. For example, `E.p('Some text')` for content, or `E.img(src='image.jpg')` for attributes. If no content is needed and you want to close an empty element for subsequent content to *not* go inside it, use `E.tag(None)`. Upgrade
Version history
2.0.0latest on PyPI · released Jul 10, 2026
Audit
Dependencies
PythonrequiredRequired for execution.