QUIC · HTTP/3 · WebTransport
QUIC, HTTP/3, QPACK and WebTransport — from UDP to your request handler, without OpenSSL or a single native binding.
npm install quico — no compiler, no prebuilt binaries.createServer and request as in node:https; Express, Fastify and Koa work. npm install quicoTested against Google, Cloudflare, Facebook, Microsoft and nginx.
Interop
Every big QUIC deployment reads the RFCs a little differently. These are the ones QUICO is tested against.
Features
Transport, crypto, HTTP/3 and WebTransport — written from the RFCs, readable end to end.
Connection IDs, flow control, key updates and handshake timeouts — RFC 9000 and RFC 9001.
A pure-JavaScript TLS 1.3 handshake, AES-GCM cipher suites and HelloRetryRequest — no OpenSSL.
Requests multiplexed over one connection, headers compressed with QPACK.
Bidirectional and unidirectional streams plus unreliable datagrams, on the server and in a Node.js client.
createServer, request, get, SNICallback — and your framework keeps working.
Advertises itself with Alt-Svc and falls back when the other side does not speak HTTP/3.
Usage
import quico from 'quico';
import fs from 'node:fs';
const server = quico.createServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
}, (req, res) => {
res.writeHead(200, { 'content-type': 'text/plain' });
res.end('Hello from HTTP/3!');
});
server.listen(4433);
// curl --http3 https://localhost:4433import quico from 'quico';
quico.request('https://www.google.com/', (res) => {
console.log('Status:', res.statusCode);
res.on('data', (chunk) => process.stdout.write(chunk));
});import express from 'express';
import quico from 'quico';
const app = express();
app.get('/', (req, res) => res.send('hi'));
// The same Express app, now on HTTP/3.
quico.createServer(tlsOptions, app).listen(4433);const wt = new WebTransport('https://localhost:4433/echo');
await wt.ready;
const stream = await wt.createBidirectionalStream();
wt.sendDatagram(Buffer.from('ping'));Compare
What you get from QUICO next to the HTTP options already in Node.js.
Deep dives
Engineering notes from the blog — the ideas behind the code.
QUIC never retransmits a packet. Track acked and in_flight as byte ranges, and "what is missing" becomes one inversion.
// The entire retransmit logic:
const missing = flat_ranges.invert(
acked_ranges ∪ in_flight_ranges,
0, total_size
);
// Loss detected? delete in_flight[pn].
// That byte range is now "missing" again.Read the deep dive →Estimate the bottleneck bandwidth and the minimum RTT; the window is their product. No loss-based guessing.
// The BBR model, in one line:
const bdp = bbr_btlbw * bbr_min_rtt;
const cwnd = clamp(
2 * bdp,
min_limit_bytes_in_flight,
max_limit_bytes_in_flight // safety net
);Read the deep dive →Checker
Point a QUIC client at a hostname and see what answers: protocol, implementation, cipher and round trip.
Type a hostname to see the kind of report the checker gives.
Demo: the values are a sample derived from the name you type — no connection is made. The live checker is on the way.
Docs
Everything is in the README on GitHub — these are the sections people look for first.
Install, generate a certificate, serve your first HTTP/3 response.
Read →createServer, request and get — what matches node:https and what is new.
Read →Sessions, streams and datagrams on the server and in the client.
Read →Run the app you already have over HTTP/3.
Read →Local certificates, forcing h3 in Chrome, the interop examples.
Read →Found a bug or a server QUICO cannot talk to? Open an issue.
Read →Ecosystem
The same author, the same idea: protocols in readable JavaScript, no native code.
One package, no build step.
npm install quicoApache 2.0 · no native code · Star it on GitHub