# picoquic: a QUIC implementation built for spec work

> picoquic is a C implementation of QUIC written to test and shape the IETF specification rather than to ship a browser stack, and it carries experimental extensions such as multipath, ACK frequency and AEGIS cipher suites. It suits developers who need to exercise new QUIC drafts and embed a small QUIC core in C.

**private-octopus/picoquic** — Minimal implementation of the QUIC protocol

- Repository: https://github.com/private-octopus/picoquic
- Stars: 785 · Forks: 257
- Language: C
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/private-octopus-picoquic

## A QUIC stack whose first job was arguing about the spec

picoquic is a minimalist implementation of the QUIC protocol as defined by the IETF, written in C under the MIT licence. The README is unusually explicit about why it exists.

The first goal was to provide feedback on the development of the QUIC standard in the IETF working group, whose charter is linked from the README. The project notes that the specification started from the version of QUIC defined by Google and implemented in Chrome, but that the IETF specification is independent of Chrome and does not attempt to be backward compatible. That framing explains the design: this is an implementation that can disagree with a shipping stack.

The second goal is to experiment with APIs for non-HTTP development, DNS over QUIC being the example given, with a pointer to RFC 9250. The README is careful to mark the rest of the wish list as future work, mentioning peer-to-peer applications and forward error correction as things that might be dreamed of rather than things that exist.

So the audience is specific. If you need a fast HTTP/3 library for a web service, this is the wrong shape of project. If you need to test a QUIC draft, or build a non-HTTP application over QUIC, or read a QUIC implementation written in plain C, it is close to ideal.

## The RFC surface and the drafts riding on top of it

The README lists the specifications the current version supports: RFC 9000 for QUIC itself, RFC 9001 for TLS, RFC 9002 for loss detection and congestion control, and RFC 8999 for invariants. Those four are the stable base.

Everything else is where the project gets interesting, and the list is long. Datagrams per RFC 9221, compatible version negotiation per RFC 9368, QUIC Version 2, greasing the QUIC bit per RFC 9287, the spin bit, QUIC ACK Frequency at version 04 of its draft, and an experimental BDP draft frame that the README says was tested in various simulations of satellite and interspatial links. There is also an experimental timestamp draft and experimental AEGIS TLS and QUIC cipher suites at version 06 of the AEGIS draft.

Multipath gets special attention, and it appears twice. The README lists both the evolving QUIC Multipath draft and the simple multipath alternative, pointing at the quicmpath project by the same author. Multipath is named as ongoing IETF work after RFC 9000 was published, and the README says picoquic enables developers to test this new work.

The practical implication for a user is that you can exercise draft behaviour that no released browser offers. The cost is that several of these features are pinned to draft version numbers, so they change underneath you as the drafts move.

## HTTP/3 support and the deliberate minimalism around it

The distribution includes a minimal implementation of HTTP/3 per RFC 9114, with a static implementation of QPACK that is compatible with RFC 9204. Static QPACK means the encoder and decoder use preconfigured tables rather than the dynamic table machinery, which keeps the implementation small at the cost of compression efficiency.

On top of that sit two further extensions: HTTP Datagrams and Capsules per RFC 9297, and WebTransport over HTTP/3 per the WebTransport draft. That combination is the interesting part for application developers, because WebTransport is what makes QUIC usable for media and other traffic that wants datagram semantics rather than a request and response cycle.

The word to keep in mind is minimal. The project describes the whole thing as a minimalist implementation, and the HTTP/3 layer is explicitly called minimal. There is no mention of a full browser-facing API, of HTTP/2 fallback handling, or of the sort of feature set a production HTTP stack accumulates.

The project also points to Quicdoq, an implementation of DNS over QUIC, as both an interesting application in its own right and an example of building something other than HTTP on top of picoquic. If you want to see how the API handles a non-HTTP protocol, that repository is the reference, not the HTTP/3 code.

## The Picotls contract that decides whether your build works

picoquic does not implement TLS itself. It depends on the Picotls implementation of TLS 1.3, and the README explains that Picotls comes in two modes: a feature rich version that depends on OpenSSL, and a leaner version depending only on the minicrypto library. picoquic currently uses the OpenSSL version, so it has a dependency on OpenSSL.

The version requirement is the part that bites. The README asks for a recent version of Picotls and states the current code is tested against the Picotls version of Tue Oct 31 2023, after commit af66fc4aa8853b0725fcb2c18a702e8f1c656cf1. It also explains why that matters: those commits changed the Picotls API by removing code for the now obsolete ESNI draft, and prior versions will not work with picoquic. In other words, the dependency is not a loose version range you can satisfy with whatever your system has.

OpenSSL support is stated as version 1.1.1 or version 3.0. Anything else is out of scope.

This is the concrete upgrade cost for an adopter. Before pulling a new picoquic release, check that your Picotls build is current, because the API underneath has moved and the old code will not compile against it. The project also keeps a documentation pass in progress, with a first pass at documenting architecture and API in doc/architecture.md, and says the focus was initially on correctness rather than performance.

## Building the library with the bundled Dockerfile

The repository ships a Dockerfile, and it is the most complete build recipe in the tree. It starts from ubuntu:20.04, installs the toolchain and OpenSSL, clones and builds Picotls from source, and then builds picoquic itself.

The base and the workspace are declared like this:

```dockerfile
FROM ubuntu:20.04
RUN mkdir /src
WORKDIR /src
```

Picotls is built from a fresh clone rather than from a package, and its own submodules are initialised before the build:

```bash
git clone https://github.com/h2o/picotls.git
```

The Dockerfile then configures Picotls with cmake, runs make, and runs make check before moving on to the picoquic build in the copied source tree. That ordering matters: the Picotls test suite is run as part of the image build, so an image that completes is an image where Picotls built and passed its own checks.

Two details in the Dockerfile are worth knowing before you copy it. The Perl modules Test::TCP and Scope::Guard are installed from CPAN, and the comment says the Perl stuff is for the picotls test code, so they exist to satisfy Picotls rather than picoquic. The image also builds with the default cmake configuration and a plain make, so it produces the library and the test and demo binaries without the tuning a production deployment would want.

For a local Linux build rather than a container, the same sequence applies outside Docker: get Picotls and OpenSSL, then configure the project with CMake. The repository root carries CMakeLists.txt, cmake/ and picoquic-config.cmake.in, so the project also installs as a CMake package.

## Windows builds hinge on OPENSSLDIR and applink.c

The README documents a separate Windows path, and the project is developed as a Visual Studio 2017 project while being tested on Windows and on Linux simultaneously. The Windows steps are specific.

You need to install and build OpenSSL yourself, then record the location of the OpenSSL install in the environment variable OPENSSLDIR, or OPENSSL64DIR for the x64 builds. A copy of libcrypto.lib must be available at that location, and a copy of applink.c must be available at the include location, which is $(OPENSSLDIR)\include\ for win32 builds and $(OPENSSL64DIR)\include\ for the x64 builds. Picotls must be cloned and compiled using the Picotls for Windows options.

The reason the environment variable matters is that the Visual Studio project resolves OpenSSL through it rather than through a package manager, so a missing or wrong OPENSSLDIR surfaces as a link error rather than as a helpful message.

The test story differs by platform too. The project consists of a core library named picoquic, a test library named picoquictest, and a test program named picoquicdemo, all in C. In the Visual Studio project the test library is wrapped in the Visual Studio unittest framework for regression testing during development, while the Linux builds run the tests through a command line program. The repository tree shows the matching directories, picoquic, picoquictest, picoquicdemo equivalents such as picoquic_t, plus picohttp and picohttp_t for the HTTP layer, and p_sim for the simulator.

## Interop testing, quicperf and the Rust bindings

The README points to the QUIC Interop days, where picoquic is actively tested against other implementations, with a wiki page on milestones and interop testing. It also notes that many QUIC implementations are listed in the quicwg wiki, and that several of them provide docker images to the Quic Interop Runner project, with results updated daily.

That comparison matters when you evaluate the project. Interop results are the closest thing to a public scoreboard for QUIC implementations, and they are published continuously by a third party rather than by the project itself.

For measuring throughput, the demo program includes an implementation of the quic performance test protocol, documented in doc/quicperf.md, and the README says the focus was initially on correctness rather than performance, with performance work ongoing. The performance claim stated in the README is that recent tests showed picoquic sending data at up to 5Gbps. That is the project's own figure and the README does not publish the test conditions behind it, so treat it as a direction rather than a baseline to plan against.

There is also a Rust binding for the library, developed by Bastian Köcher and hosted as bkchr/picoquic-rs, which the README recommends checking out if you want the C library from Rust.

On maintenance, the repository is not archived and the last push was on 2026-10-20, with dated release tags such as v2026.10.19.9b7d167 appearing on the same day. The rate of tagged builds is high, which suits a project whose users track drafts.

## Conclusion

Use picoquic when your work touches QUIC itself: testing draft extensions, prototyping a non-HTTP application on QUIC, or embedding a QUIC core in C where a browser stack is too large to consider. Do not pick it as a general HTTP/3 client library, since the HTTP/3 support is described as minimal with a static QPACK implementation, and do not plan around the current Picotls API without checking compatibility, because the project notes that older Picotls versions will not work after the ESNI-related changes. Before you build, pin the Picotls revision the project tests against, decide between OpenSSL 1.1.1 and 3.0, and check the release tags, since the project ships frequent dated builds such as v2026.10.19.9b7d167 and the last push was on 2026-10-20.

## FAQ

### What is picoquic and which QUIC specifications does it implement?

picoquic is a minimalist C implementation of QUIC as defined by the IETF. The current version supports RFC 9000, RFC 9001, RFC 9002 and RFC 8999, along with extensions such as QUIC datagrams, compatible version negotiation, QUIC Version 2 and ACK Frequency.

### How do I build picoquic on Linux?

You need Picotls and OpenSSL, then configure with CMake. The bundled Dockerfile shows the full sequence: clone Picotls from https://github.com/h2o/picotls.git, build it with cmake and make, then build picoquic from the copied source tree with cmake and make.

### Why does picoquic fail to compile against my Picotls installation?

Picotls versions before the commits that removed the obsolete ESNI draft code will not work with picoquic. The project is tested against the Picotls version of Tue Oct 31 2023, after commit af66fc4aa8853b0725fcb2c18a702e8f1c656cf1, and OpenSSL must be version 1.1.1 or 3.0.

### Does picoquic support HTTP/3 and WebTransport?

The distribution includes a minimal HTTP/3 implementation per RFC 9114 with a static QPACK implementation compatible with RFC 9204, plus HTTP Datagrams and Capsules per RFC 9297 and WebTransport over HTTP/3 per the WebTransport draft.

### Can I use picoquic from Rust?

Yes. The README points to Rust bindings for the picoquic library developed by Bastian Köcher, hosted in the bkchr/picoquic-rs repository, and recommends checking it out.

## Sources

- [Issues](https://github.com/private-octopus/picoquic/issues)
- [License: MIT](https://github.com/private-octopus/picoquic/blob/master/LICENSE)
- [private-octopus/picoquic on GitHub](https://github.com/private-octopus/picoquic)
- [README](https://github.com/private-octopus/picoquic/blob/master/README.md)
- [Releases](https://github.com/private-octopus/picoquic/releases)

---

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