# h2 is the HTTP/2 stack that refuses to own your socket

> The python-hyper h2 package is a pure-Python HTTP/2 implementation that stops at the frame layer: it does not parse URLs, it does not open sockets, and it has no opinion about concurrency. You feed it bytes and it hands you events, which is why it drops into asyncio, Twisted, Tornado, gevent, curio and eventlet alike.

**python-hyper/h2** — Pure-Python HTTP/2 protocol implementation

- Repository: https://github.com/python-hyper/h2
- Website: https://python-hyper.org/
- Stars: 1,043 · Forks: 198
- Language: Python
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/python-hyper-h2

## One building block, not a client

The library's scope is stated as a limitation and a feature. This repository contains a pure-Python implementation of an HTTP/2 protocol stack, written from the ground up to be embeddable in whatever program you choose to use, ensuring that you can speak HTTP/2 regardless of your programming paradigm. The README then says what it does not do: this repository does not provide a parsing layer, a network layer, or any rules about concurrency. Instead it is a purely in-memory solution, defined in terms of data actions and HTTP/2 frames, and it is described as one building block of a full Python HTTP implementation. That framing is what makes the library usable in places where a normal HTTP client would be awkward, such as a proxy that needs to inspect frames, a test harness, or a server implementation for a framework that does not have one.

## The API is send frames, receive events

The usage example is short enough to take in at once, and the shape of it explains the whole design:

```python
import h2.connection
import h2.config

config = h2.config.H2Configuration()
conn = h2.connection.H2Connection(config=config)
conn.send_headers(stream_id=stream_id, headers=headers)
conn.send_data(stream_id, data)
socket.sendall(conn.data_to_send())
events = conn.receive_data(socket_data)
```

The pattern is: configure a connection, tell it to send headers and data for a stream, ask it for the bytes to write with `data_to_send()`, and hand it the bytes you read with `receive_data()`, which returns events. The connection object is the state machine, the stream identifiers are yours to manage, and the socket is yours to own. Note that the configuration object is a separate type you construct and pass in, which is where a client can set the settings that a server and a client must not disagree about, such as the frame sizes and the initial window sizes.

## Two dependencies do the compression work

The package metadata lists exactly two runtime dependencies, hyperframe at version 6.1 or later but below 7, and hpack at 4.2 or later but below 5. That split is the architecture in miniature. hpack is the header compression layer, implementing HPACK with the static table, the dynamic table and the Huffman coding, and it is the part that has to interoperate with other HTTP/2 implementations byte for byte, because a header that decodes differently on the other side of the connection is a broken connection. hyperframe is the frame layer, so the framing and the state machine for each frame type live in a separate, independently tested package. The version constraints are both narrow ranges with an upper bound, which is the right shape for a protocol implementation where a major version of a dependency means a wire behaviour change rather than an API change.

## The examples are the argument for the design

The examples directory is the strongest argument the project makes, because it shows the same library driven by eight different concurrency models: asyncio, curio, eventlet, gevent, plain sockets, tornado, twisted, and a fragments directory for the pieces that do not fit any of them. Each example is a working client and server pair built on that framework, with the framework doing the I/O and h2 doing the protocol. If the library had hardcoded a particular event loop, seven of those directories would not exist. The plain_sockets example is the purest statement of the contract, since it shows the library working with nothing but a socket object and a loop you wrote yourself. There is also a visualizer directory at the repository root, which suggests a tool for inspecting frame exchanges.

## A mature package with a long history of care

The metadata records the project as Development Status 5 - Production/Stable, with Python 3.10 through 3.14 supported, and the build system is setuptools with a wheel requirement, which tells you the packaging has been modernised without being rewritten. The dependency groups are organised by purpose, with testing, linting, packaging and docs groups, and the testing group includes pytest with coverage, xdist for parallel runs, and hypothesis, which is a property-based testing library and is the right tool for a state machine that has to survive whatever bytes a peer sends. The documentation is on readthedocs, the CI and coverage badges are in the README, and there is a Gitter chat community. The package was authored by Cory Benfield and is maintained by the members of the python-hyper organisation, with Thomas Kriechbaumer listed as a maintainer.

## Where the responsibility moves when you adopt it

The tradeoff of the design is that everything above the frame layer becomes your problem, and the list is long. You write the frames, so you decide the flow control window behaviour and whether to respect the peer's settings. You do the HPACK work through hpack, so header block management and the encoder and decoder state are yours. You do the connection, so you handle the preface, the SETTINGS exchange and the GOAWAY semantics that h2 gives you events for but does not act on. And you do the concurrency, because the library has no rules about it. None of this is a defect, and for a proxy or a framework that needs to interleave HTTP/2 with other protocols it is the only design that works. It does mean that the question to ask before adopting is not whether h2 is good, but whether your project is prepared to own the layer above it.

## Conclusion

Adopt h2 if you need HTTP/2 in a Python program and want to control the transport yourself, since the library is deliberately limited to frames and events and will sit under any async framework you already use. Do not adopt it if you want a request library, because there is no URL parsing, no connection pooling and no HTTP semantics, and you would be writing those yourself. Verify first that your Python is 3.10 or newer, and that the two runtime dependencies, hyperframe and hpack, are acceptable in your build, since hpack is where the header encoding and HPACK compression work actually happens.

## FAQ

### What is the h2 Python package?

It is a pure-Python implementation of an HTTP/2 protocol stack, written to be embeddable in whatever program you choose, so you can speak HTTP/2 regardless of your programming paradigm. It provides no parsing layer, no network layer and no rules about concurrency.

### How do I install h2?

Run `python -m pip install h2`. The package requires Python 3.10 or newer and depends on hyperframe and hpack, both with narrow version ranges.

### Which async frameworks does h2 work with?

The examples directory includes asyncio, curio, eventlet, gevent, plain sockets, tornado and twisted, plus a fragments directory for code that does not fit a framework. The library does the framing while the framework does the I/O.

### What do the h2 dependencies do?

hpack is the header compression layer implementing HPACK, and hyperframe is the frame layer, so framing and per-frame-type state machines live in a separate, independently tested package.

### What licence is h2 released under?

The MIT License, with the details in the LICENSE file in the repository. The package was authored by Cory Benfield and is maintained by the members of the python-hyper organisation.

## Sources

- [Issues](https://github.com/python-hyper/h2/issues)
- [License: MIT](https://github.com/python-hyper/h2/blob/master/LICENSE)
- [Project website](https://python-hyper.org/)
- [python-hyper/h2 on GitHub](https://github.com/python-hyper/h2)
- [README](https://github.com/python-hyper/h2/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/python-hyper-h2
