Registry / web-framework / htpy
library26.5.1pypypi✓ verified 84d ago

htpy is a Python library designed for generating HTML in plain Python code, eliminating the need for separate templating languages. It aims to make writing HTML fun and efficient, leveraging Python's features like static typing and debugging. The current version is 25.12.0, and it follows a frequent release cadence, often monthly.

pip install htpy
INSTALL
IMPORT
SIG · HTPY
H
htpy
web-frameworkpythonv26.5.1
Install
1.6s avg
Import
189ms
Disk
16MB
Pass rate
8/ 10
Env Coverage8 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v26.5.1 · 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
musl
glibc
py 3.10
✓ —
✓ 1.73s
py 3.11
✓ —
✓ 1.73s
py 3.12
✓ —
✓ 1.55s
py 3.13
✓ —
✓ 1.58s
py 3.9
✕ build_error
✕ build_error
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

html, body, div, p, ul, li
from htpy import html, body, div, p, ul, li
Commonly imported HTML elements for building pages.
htpy
import htpy as h
Alternative import style, allowing access to elements via 'h.div', 'h.html', etc.
HtpyResponse
from htpy.starlette import HtpyResponse
Helper class for integrating with Starlette/FastAPI applications.
Context
from htpy import Context
For creating and managing context for data passing between components.
with_children
from htpy import with_children
Decorator for defining custom components that accept children nodes.
Renderable
from htpy import Renderable
Protocol for consistent API to render htpy objects as HTML or iterate over them.

This quickstart demonstrates creating a simple HTML page with a head, title, body, heading, and an unordered list dynamically generated from a Python list. The `print(page)` call renders the entire structure to an HTML string.

from htpy import body, h1, head, html, li, title, ul menu = ["egg+bacon", "bacon+spam", "eggs+spam"] page = html[ head[title["Today's menu"]], body[ h1["Menu"], ul(".menu")[(li[item] for item in menu)], ], ] print(page)
Debug
Known issues
breakingSpecifying multiple CSS classes using whitespace in the shorthand syntax (e.g., `div(".foo bar")`) will now raise a `ValueError`.
fix
Use dot notation to separate multiple classes: `div(".foo.bar")`.
affects: >=25.10.0
breakingRendering a generator (e.g., a generator comprehension used as children) more than once will now raise an exception, as generators are single-use iterators.
fix
Ensure generators are consumed only once. If content needs to be rendered multiple times, convert the generator to a list or tuple: `ul[list(li[item] for item in my_list)]`.
affects: >=25.7.0
deprecatedThe methods `render_node()` and `iter_node()` are deprecated, along with direct iteration over `htpy` elements.
fix
To render an element to a string, use `str(element)`. For streaming or iterating over chunks, use `element.iter_chunks()`. The `Renderable` protocol provides a consistent API.
affects: >=25.4.1
gotchaAsynchronous rendering capabilities were added, impacting how `htpy` can be used with ASGI frameworks like Starlette and FastAPI.
fix
When using ASGI frameworks, leverage `htpy.starlette.HtpyResponse` for returning async-rendered content. Refer to the async documentation for details.
affects: >=25.12.0
Errors
Common errors & fixes
ValueError: Invalid whitespace in class shorthand. Expected '.foo.bar', not '.foo bar'
Attempting to specify multiple CSS classes using spaces instead of dots in the shorthand syntax.
fix
Replace spaces with dots for multiple classes: `div(".class1.class2")` instead of `div(".class1 class2")`.
RuntimeError: Generator was already consumed.
An `htpy` element with a generator as a child was rendered or iterated over more than once.
fix
If the content needs to be processed multiple times, ensure the generator is converted to a list or tuple (e.g., `ul[tuple(li[item] for item in items)]`) or recreate the generator for each use.
AttributeError: 'Element' object has no attribute 'render_node' OR TypeError: 'Element' object is not iterable
Using deprecated methods `render_node()` or `iter_node()`, or directly iterating over `htpy` elements in newer versions.
fix
Use `str(element)` to get the full HTML string, or `element.iter_chunks()` for iterable streaming output.
NameError: name 'div' is not defined
An HTML element (like `div`, `p`, `html`) was used without being imported from the `htpy` module.
fix
Add the missing element to your imports: `from htpy import div` (or `from htpy import html, body, div` for multiple elements).
Upgrade
Version history
26.5.1latest on PyPI · released May 22, 2026
Audit
Dependencies
pythonrequiredRequired for execution
Agent activity
4 hits · last 30 days
node
4
Resources