Skip to main content

PyPI version Supported Python Wheel

Important note

  • Since 2026.02.16:

    • Partial support of ty type checker
    • Supports type checking under PyPy 3.11
  • Since 2026.01.01:

  • Since 2025.11.25:

    • PEP 800 support, thus only compatible with newest type checkers as of Oct 2025
    • Declare and make use of Python 3.14 support; drops Python 3.8 support
  • Since 2025.08.25:

    • Supports lxml 6.0 and 5.4, while lxml 4.9 will not be tested anymore
  • Since 2025.03.04:

    • BeautifulSoup4 package is added as dependency to utilise its inline annotation, thus dropping types-beautifulsoup4 dependency.
    • Fixes compatibility with older versions of type checkers, as well as mypy 1.14+.

Introduction

This repository contains external type annotations for lxml. It can be used by type-checking tools to check code that uses lxml, or used within IDEs like Visual Studio Code to facilitate development.

Goal ① : Completion

Implementation is complete since 1Q 2003, thus no more considered as partial. Following submodules intentionally not implemented due to irrelevance to type checking or other reasons:

  • lxml.etree.Schematron (obsolete and superseded by lxml.isoschematron)
  • lxml.usedoctest (for testing only)
  • lxml.html.usedoctest (for testing only)
  • lxml.html.formfill (shouldn't have existed, this would belong to HTTP libraries like requests or httpx)

Goal ② : Support multiple type checkers

Currently the annotations are validated for following type checkers:

Name Version
basedpyright ≥ 1.31.6
mypy ≥ 1.18.1
pyrefly ≥ 0.46.3
pyright ≥ 1.1.406
ty ≥ 0.0.7

pyright and basedpyright are recommended for their greater flexibility, maturity and early adoption of newer type checking features. In the future, there is plan to bring even more type checker support (such as ty or zuban).

Goal ③: Review and test suite

  • All prior lxml-stubs contributions are reviewed thoroughly, bringing coherency of annotation across the whole package
  • Perform runtime check, and compare against static type checker result; this guarantees annotations are indeed working in real world, not just within some cooked up test suite
  • Existing static test suite already vastly expanded, and is under progress of migrating to runtime test
  • Modernize package building infrastructure

Goal ④ : Geared towards users

Docstring

This package tries to bring type annotation specific docstrings for some classes and functions, explaining how they can be used. Following screenshot demonstrates annotation specific docstring in Visual Studio Code:

Stub docstring in VSCode mouseover tooltip

Warnings for exception and wrong code

image showing deprecation warning

pyright and basedpyright users receive additional benefit of being forewarned when their lxml code will likely cause undesirable runtime behavior or outright exception.

  • #64 covers one such example where such warnings are warrented.
  • Another example is html.html5parser submodule functions causing exception when str input and guess_charset parameter are used together.

Similarly their corresponding Visual Studio Code extensions would display visual cue when such problematic usage is encountered, as shown in above screenshot.

[!NOTE] This feature makes use of @deprecated decorator from Python 3.13. mypy disables such warnings by default, and need to be turned on explicitly.

Class inheritance change

Current annotations are geared towards convenience for programmers' convenience instead of absolute logical 'correctness'. The deviation of class inheritance for HtmlComment and friends is one prominent example.


Installation

The normal choice for most people is to fetch package from PyPI, like:

uv pip install -U types-lxml  # using uv
pip install -U types-lxml  # using pip

In the unlikely case PyPI is down, one can directly download wheel from latest release in GitHub, and then perform installation as local file.

As convenience, it is possible to pull development related packages. This helps when you want to submit PR on bugs or features:

uv pip install -U types-lxml[dev]
pip install -U types-lxml[dev]

The stub package supports all Python versions since 3.9. But if you want to create PR and test your changes, Python 3.10 is needed.

Mypy plugin usage

Mypy plugin bundled with this stub package needs to be explicitly turned on from config. Add these two lines under [mypy] global section if you're using INI file:

plugins =
    mypy_plugin_lxml.main

Alternatively, add this under [tool.mypy] section for pyproject.toml:

plugins = ["mypy_plugin_lxml.main"]

Choosing the build

Since 2024.08.07 release, there will be two versions of types-lxml. First one is the default one; if there's no problem using it, there's no need to switch.

The second version, types-lxml-multi-subclass, is intended for specific need, namely creation of multiple lxml element subclasses. For example:

  graph TD;
      etree.ElementBase-->MyBaseElement;
      MyBaseElement-->MySubElement1;
      MyBaseElement-->MySubElement2;

If a parsed or constructed element tree consists of single type of element nodes, it is safe to assume the children or parent of a node are of the same type too. But this assumption does not hold for multiple subclasses. Using diagram above as example, calling .iter() method from MyBaseElement node may produce element of any subelement or even MyBaseElement itself. Therefore output type should be simply MyBaseElement only.

Such scenario is already in effect for lxml.html. <form> element (FormElement) is supposed to contain other form related tags like <input>, <select> etc. But we can't possibly pinpoint single subelement type, so <form> children can only possibly be of type HtmlElement. The multiple subelement scenario is already hardcoded for HtmlElement and ObjectifiedElement within this annotation package, but users may choose to have their own overridden element subclasses (inherit from ElementBase) too.

The 2 paradigms can't coexist within a single type annotation package. See bug #51 that illustrated why multiple build is necessary.

[!IMPORTANT] Users can only choose to install either build, not both. pip would arbitrarily overwrite conflicting files with one another. If in doubt, removing existing package first, then install the one you needed.

Release file attestation

[!TIP] For those haven't heard of it, this is sort of like gnupg or minisign signatures, but with GitHub backed infrastructure.

Since 2024.11.08 users can download types-lxml release files and verify that they indeed do originate from GitHub. After downloading release wheel file (say pip download types-lxml, or browser access to PyPI directly), one can use GitHub cli to verify it comes from this GitHub repository without being altered:

gh at verify types_lxml-2024.11.8-py3-none-any.whl --repo abelcheung/types-lxml

Should generate following result:

Loaded digest sha256:4b4fa7f9e2f1d5f58b98ac9852a75927e4e0f69363249f9cebc78db095c046e0 for file://types_lxml-2024.11.8-py3-none-any.whl
Loaded 1 attestation from GitHub API
✓ Verification succeeded!

sha256:4b4fa7f9e2f1d5f58b98ac9852a75927e4e0f69363249f9cebc78db095c046e0 was attested by:
REPO                   PREDICATE_TYPE                  WORKFLOW
abelcheung/types-lxml  https://slsa.dev/provenance/v1  .github/workflows/release.yml@refs/tags/2024.11.08

History

Type annotations for lxml were initially included in typeshed, but as it was still incomplete at that time, the stubs are ripped out as a separate project. The code was since then under governance of lxml, until 2022 when this fork intended to revamp lxml-stubs completely and emerge into separate project.

types-lxml is a fork of lxml-stubs that strives for the goals described above, so that most people would find it more useful.

Metadata

Release files for types-lxml 2026.2.16

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

Source distribution (sdist)

Source distribution for types-lxml 2026.2.16
File Size Uploaded
types_lxml-2026.2.16.tar.gz 161.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for types-lxml 2026.2.16
File Interpreter ABI Platform
types_lxml-2026.2.16-py3-none-any.whl Python 3 none any Details

Total release size: 258.2 kB

Release files / types_lxml-2026.2.16.tar.gz

Download URL types_lxml-2026.2.16.tar.gz
Size 161.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b3a1340cc06db98d541c785732f6f68bea438daff4e2b7809ef748d545d01406
BLAKE2b-256 checksum
How to use checksums
ddadc70ac8cbdc28eb58a17301c69b4925af54b614e47f9b2ebc9de5cc10f786
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / types_lxml-2026.2.16-py3-none-any.whl

Download URL types_lxml-2026.2.16-py3-none-any.whl
Size 97.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5dd81ffa54830e5f361988737c5f1d6a0ae48b2742790637ec560df790ea0401
BLAKE2b-256 checksum
How to use checksums
5f5c03ec9befbf4bb5309bfd576c6a5ac1c75633f78f6b64cf1f594e97cd3d23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2
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