types-lxml
types-lxml, version 2026.2.16, provides comprehensive external type annotations (stubs) for the `lxml` library, enabling static type checking with tools like MyPy and Pyright, and improving IDE support. It is actively maintained with frequent updates, often releasing multiple versions per month, and is a more complete fork of the original `lxml-stubs` project. It aims to cover major lxml submodules like `lxml.etree`, `lxml.html`, and `lxml.objectify` for Python 3.9 and newer.
Warnings
- breaking Python 3.8 support was dropped since the 2025.11.25 release. Ensure your project uses Python 3.9 or newer.
- gotcha Pyright is generally the preferred type checker for lxml code over MyPy. lxml's attribute normalization can be too restrictive for MyPy, leading to potential false positives or difficulties.
- breaking Since the 2025.08.25 release, `types-lxml` officially supports `lxml` versions 6.0 and 5.4, and no longer tests against `lxml` 4.9.
- gotcha When using specific lxml types, particularly internal ones like `_Element` or `_ElementTree` in type annotations in your own code, it's best practice to import them from `lxml` directly, not `types_lxml`. Also, use `from __future__ import annotations` or quote the type hints to avoid forward reference issues.
- gotcha Since the 2024.08.07 release, there are two versions of `types-lxml`: the default and `types-lxml-multi-subclass`. The latter is intended for specific needs involving the creation of multiple lxml element subclasses.
Install
-
pip install types-lxml
Imports
- etree
from lxml import etree
- html
from lxml import html
Quickstart
from lxml import etree
# Example XML string
xml_string: str = '<root><item id="1">Apple</item><item id="2">Banana</item></root>'
# Parse the XML string
root: etree._Element = etree.fromstring(xml_string)
# Find an element by tag name
item: etree._Element | None = root.find('item')
if item is not None:
print(f"First item: {item.text}")
# Find all elements with a specific tag
all_items: list[etree._Element] = root.findall('item')
for i, element in enumerate(all_items):
item_id: str | None = element.get('id')
print(f"Item {i+1} (ID: {item_id}): {element.text}")
# Create a new element and append it
new_element: etree._Element = etree.SubElement(root, 'item', id='3')
new_element.text = 'Cherry'
# Print the modified XML
print("\nModified XML:")
print(etree.tostring(root, pretty_print=True).decode())