← Tous les cours / WebTransport — le temps réel nouvelle génération Cours
00 — VUE D'ENSEMBLE

Encore un protocole ?

Chrome et Firefox l'embarquent déjà, alors que sa spec n'est même pas finalisée. WebTransport n'a pas encore de numéro de RFC — mais il pourrait bien remplacer la moitié de ce qu'on utilise aujourd'hui.

Il y a quelque chose d'inhabituel avec WebTransport : les navigateurs l'embarquent avant que sa spécification soit finalisée. Chrome le supporte depuis un moment, Firefox l'a activé à son tour. Pourtant, le protocole est toujours à l'état de brouillon — il n'a même pas encore de numéro de RFC officiel. C'est rare, et ça dit quelque chose : le besoin est réel.

Mais quel besoin, au juste ? On a déjà WebSocket, SSE, HTTP/2, HTTP/3… pourquoi encore un protocole ? C'est toute la question de ce cours. La réponse courte tient en une phrase :

WebTransport
Une API de transport moderne dans le navigateur, bâtie sur HTTP/3 (donc sur QUIC). Elle donne au code client le pouvoir d'ouvrir des streams bidirectionnels fiables et des datagrammes non fiables — l'équivalent d'UDP, directement depuis une page web, sans l'héritage encombrant de WebSocket.

Pour comprendre pourquoi c'est un changement de cap, il faut remonter le fil : voir comment le web a multiplié les ruses pour faire parler le serveur, où WebSocket bute, ce que les streams de HTTP/2 et HTTP/3 ont apporté, et enfin ce que WebTransport débloque par-dessus tout ça.

requête/réponse
long polling · SSE
WebSocket
WebTransport
⚠️ C'est encore un brouillon. La spec bouge, les détails d'API peuvent changer, et le support est expérimental. Ce qui compte ici, ce sont les concepts — sessions, streams, datagrammes, le rôle de QUIC — qui, eux, sont stables et éclairent toute une famille de protocoles.
01 — LA LIGNÉE

Faire parler le serveur en premier

Le web est né sur un schéma simple : le client demande, le serveur répond. Toute l'histoire du temps réel, c'est une suite de ruses pour contourner cette règle — et WebTransport en est la dernière.

Le web a été conçu pour partager des documents. Son protocole, HTTP, repose donc sur un échange d'une simplicité absolue : le client envoie une requête, le serveur répond, et c'est terminé. Le serveur ne prend jamais l'initiative — il attend, sagement. Parfait pour afficher une page. Frustrant dès qu'on veut de l'interactivité, car comment le serveur te prévient-il qu'un message est arrivé s'il ne peut pas parler le premier ?

Toute l'histoire du temps réel sur le web est une suite de ruses pour contourner cette règle. Chacune ajoute une capacité, sans tout résoudre.

TechniqueL'astuceCe qui manque
Long pollingLe serveur garde la requête ouverte jusqu'à avoir quelque chose à direUne requête par message ; toujours à sens unique
SSEUne requête, une réponse infinie découpée en « événements » (chunked, text/event-stream)Le serveur parle, mais le client ne peut rien renvoyer sur ce canal
WebSocketOn upgrade la connexion HTTP en un canal brut, bidirectionnelUn surcoût par trame, et une dépendance à TCP (voir section suivante)

Le long polling et SSE sont des détournements astucieux du couple requête/réponse — on peut même bricoler du bidirectionnel en combinant les deux, mais ce n'est jamais naturel. C'est précisément ce qui a justifié WebSocket : un vrai canal à double sens. Et c'est cette même quête de naturel qui mène, des années plus tard, à WebTransport.

🔑 Pour creuser cette lignée : les Server-Sent Events et le streaming HTTP ont leur cours dédié, Streaming HTTP ; et WebSocket — son handshake, son full-duplex, sa comparaison avec le polling — est détaillé dans la section réseau du cours Chat temps réel serverless.
02 — LIMITES DE WEBSOCKET

Ce qui manque à WebSocket

WebSocket a réglé la bidirectionnalité, et on s'en sert tous les jours. Mais il traîne un héritage de 2011 : un surcoût par trame, un masquage devenu inutile, et une dépendance à TCP dont il ne peut pas se défaire.

Soyons clairs : WebSocket est excellent, et on s'en sert quotidiennement. Mais il a été conçu en 2011, et il porte les marques de son époque. Trois limites, en particulier, expliquent pourquoi on a fini par chercher mieux.

1. Un surcoût par trame

WebSocket a son propre concept de trames, avec un en-tête sur chacune. Ce n'est pas énorme — quelques octets par trame, plus une clé de masquage — mais c'est un coût que tu n'avais pas avant, et qui s'accumule sur un canal très bavard.

2. Le masquage, une précaution devenue inutile

Le masking
Chaque trame envoyée par le client est masquée (un XOR avec une clé). L'objectif d'origine : empêcher l'empoisonnement de cache des proxys intermédiaires qui ne comprenaient pas WebSocket. Mais c'était une parade conçue avant que TLS ne soit omniprésent. Sur un canal chiffré, personne ne peut intercepter ni altérer le trafic — le problème n'existe plus, et le masquage n'est qu'un travail cryptographique en pure perte.

3. Prisonnier de TCP

C'est la limite la plus profonde. WebSocket s'établit au-dessus de HTTP/1 (et peut l'être sur HTTP/2), donc au-dessus de TCP. Or TCP impose une livraison ordonnée et fiable : impossible de demander « envoie-moi ces paquets vite, tant pis si l'un se perd ou arrive dans le désordre ». Pour de l'audio ou de la vidéo temps réel, c'est exactement ce qu'on voudrait pouvoir faire.

WebSocket
TCP
ordonné & fiable, point
💡 Le constat : WebSocket résout la bidirectionnalité, mais il reste collé à TCP et à un format un peu daté. Pour aller plus loin, il faut d'abord comprendre ce que les versions modernes de HTTP ont changé dans la façon de transporter les données — c'est l'objet de la section suivante. TCP et UDP eux-mêmes sont disséqués dans TCP & Sockets.
03 — STREAMS HTTP/2 & /3

Le multiplexing et son talon d'Achille

HTTP/2 a introduit les streams : plein de requêtes sur une seule connexion. Génial — mais tant qu'on est sur TCP, un seul paquet perdu bloque tout le monde. C'est là que QUIC entre en scène.

HTTP a évolué, et HTTP/2 a apporté une idée décisive : les streams. Au lieu d'une connexion TCP par requête (ou de requêtes mises bout à bout sur une même connexion), on découpe une seule connexion en multiples flux logiques. Chaque morceau de données est étiqueté d'un identifiant de stream ; le serveur peut donc démêler des dizaines de requêtes envoyées en même temps sur le même fil.

Multiplexing
Plusieurs streams indépendants partagent une seule connexion. Chacun a son couloir, identifié par un id ; tout se mélange sur le câble, mais le destinataire sait les séparer. Une seule connexion sert ainsi des requêtes concurrentes — fini la file d'attente.

Magnifique sur le papier. Sauf que HTTP/2 reste au-dessus de TCP, et TCP livre les octets dans l'ordre, quoi qu'il arrive. Si un seul segment se perd, le noyau retient tous les streams en attendant sa retransmission — même ceux qui n'ont rien à voir. C'est le fameux blocage en tête de file (head-of-line blocking) : tes couloirs indépendants sont, en réalité, à la merci d'un seul paquet perdu.

🔑 C'est la raison d'être de HTTP/3. En passant de TCP à QUIC (lui-même au-dessus d'UDP), HTTP/3 rend les streams réellement indépendants : un paquet perdu ne bloque que son propre stream. Tout le détail de HTTP/1.1 → /2 → /3, des streams et du blocage en tête de file, est dans le cours HTTP · De 1.1 à 3.

L'angle mort du navigateur

Reste un problème de pouvoir. gRPC, le protocole de Google bâti sur les streams de HTTP/2, exploite ce découpage à fond — streams unidirectionnels, bidirectionnels, sérialisation par Protocol Buffers. Mais gRPC ne fonctionne pas nativement dans le navigateur, malgré ce qu'on entend parfois. Pourquoi ? Parce qu'il a besoin d'un accès bas niveau aux streams, que le navigateur refuse : depuis une page, tu n'as que l'API fetch. Tu envoies une requête, tu lis une réponse — mais tu ne décides pas des connexions ni des streams, le navigateur s'en charge à ta place.

C'est exactement le verrou que WebTransport vient ouvrir : donner au code client ce contrôle des streams, mais de façon sûre et encadrée.

04 — WEBTRANSPORT

Sessions, streams et datagrammes

Voici la pièce maîtresse : une session dans laquelle client et serveur ouvrent des streams fiables — ou des datagrammes non fiables. Autrement dit, de l'UDP dans le navigateur, enfin.

On y est. WebTransport ouvre une session au-dessus de HTTP/3, et fait pour toi ce travail bas niveau que le navigateur cachait jusqu'ici. Dans cette session, le client ou le serveur peut ouvrir trois sortes de canaux.

Type de canalSensGaranties
Stream bidirectionnelLes deux parlentFiable, ordonné
Stream unidirectionnelUn seul sensFiable, ordonné
DatagrammeUn seul sens, « tire et oublie »Non fiable : ni ordre, ni retransmission
Le datagramme non fiable — la nouveauté
C'est de l'UDP, exposé dans le navigateur. Tu envoies un paquet, le réseau le livre comme il peut — peut-être dans le désordre, peut-être pas du tout — et tu t'en accommodes. Jusqu'ici, la seule source de « presque-UDP » côté web était WebRTC. WebTransport en fait une primitive de première classe.

Pourquoi vouloir moins de garanties ? Parce que pour de l'audio ou de la vidéo en direct, attendre la retransmission d'un paquet perdu est pire que le perdre. Mieux vaut une image sautée qu'un gel de l'écran. WebTransport te rend ce choix : c'est toi, l'application, qui décides quoi faire d'un paquet en retard ou manquant — l'ignorer, le bufferiser, sauter une trame.

🔑 Le contrôle est précieux. Une boîte magique qui « gère tout » sans rien t'exposer est un cauchemar le jour où tu dois optimiser. C'est la même philosophie qu'une base comme PostgreSQL et ses centaines de paramètres de réglage : le système est complexe, les cas d'usage le sont aussi, alors on rend la main au développeur.
⚠️ Bidirectionnel ne veut pas dire « pousser sans limite ». Si le serveur émet plus vite que le client ne consomme, ça déborde. WebTransport intègre donc du contrôle de flux et de la limitation. C'est la leçon que tout le monde réapprend : le push ne passe pas à l'échelle tout seul (HTTP/2 push est mort, Kafka a choisi le modèle pull). On y revient en synthèse — et le sujet des files et du pull/push est traité dans Files de messages.

Le simulateur ci-dessous oppose les deux mondes. Envoie une rafale de paquets sur un stream fiable, puis sur un datagramme non fiable, avec une perte au milieu — et observe la différence de comportement.

Choisis le mode, puis envoie des paquets (l'un sera perdu) :

05 — HTTP/2 OU HTTP/3

Deux saveurs, pas les mêmes pouvoirs

WebTransport existe au-dessus de HTTP/2 et de HTTP/3 — et ce ne sont pas les mêmes capacités. Le transport sous-jacent décide de ce que tu peux faire, à commencer par les datagrammes.

Détail qui a son importance : WebTransport existe en deux saveurs, selon le HTTP qui le porte. Il y a un brouillon au-dessus de HTTP/2, et un autre au-dessus de HTTP/3 — écrits par des équipes différentes, au point que les deux specs se ressemblent à peine. Et surtout, ils n'offrent pas les mêmes pouvoirs, parce que le transport sous-jacent n'est pas le même.

WebTransport / HTTP/2WebTransport / HTTP/3
TransportTCPQUIC (sur UDP)
Streams bidirectionnelsOuiOui
Streams unidirectionnelsOuiOui
Datagrammes non fiablesNon (TCP est ordonné)Oui
Blocage en tête de fileOui (au niveau TCP)Non (streams QUIC indépendants)

La logique est implacable : sur TCP, impossible d'offrir des datagrammes non fiables, puisque TCP ordonne et garantit tout par construction. Il faut UDP pour ça — et c'est exactement ce que QUIC apporte. C'est aussi pour cette raison que HTTP/3 a été inventé : éliminer le blocage en tête de file qui handicape HTTP/2.

💡 HTTP/3 est la vraie maison de WebTransport. La version sur HTTP/2 existe pour les environnements où QUIC ne passe pas encore, mais elle est amputée de ce qui fait l'intérêt du protocole : les datagrammes et l'absence de blocage. Le pourquoi de QUIC est détaillé dans HTTP · De 1.1 à 3.

Le simulateur ci-dessous te laisse choisir le transport sous-jacent. Bascule entre HTTP/2 et HTTP/3 et observe quelles capacités s'allument.

Choisis le transport, observe les capacités :

06 — LES ATOUTS DE QUIC

Les atouts de QUIC

WebTransport n'hérite pas que de l'absence de blocage. Il hérite de deux superpouvoirs que TCP ne pourra jamais offrir : une connexion qui survit au changement de réseau, et une reprise sans aller-retour.

On a dit que WebTransport vit sur HTTP/3, donc sur QUIC. Ce choix ne se résume pas à « éviter le blocage en tête de file » : QUIC apporte deux capacités que TCP, par construction, ne pourra jamais avoir. Comprendre ces atouts, c'est comprendre pourquoi WebTransport vise l'avenir et pas le rattrapage.

La connexion qui survit au changement de réseau

Comment TCP identifie-t-il une connexion ? Par un quadruplet : IP source, port source, IP destination, port destination. Change l'un des quatre — par exemple ton téléphone qui bascule du Wi-Fi à la 4G, donc une nouvelle IP — et pour TCP, c'est une connexion différente. L'ancienne est morte ; ton WebSocket tombe, et il faut tout refaire : handshake TCP, puis handshake TLS.

Migration de connexion (QUIC)
QUIC n'identifie pas une connexion par l'adresse IP, mais par un Connection ID indépendant du réseau. Quand ton IP change, la connexion migre : le Connection ID reste le même, aucun nouveau handshake, la session continue sans rien perdre. Pour une application mobile, c'est la différence entre une coupure et une continuité parfaite.

0-RTT : reprendre sans payer l'aller-retour

Quand un client se reconnecte à un serveur qu'il connaît déjà, QUIC peut glisser des données applicatives dans le tout premier paquet, avant même la fin du handshake. C'est le 0-RTT : zéro aller-retour d'attente, la reprise est quasi instantanée.

⚠️ Le piège du 0-RTT : le rejeu. Comme ces données partent avant que la poignée de main soit terminée, un attaquant peut capturer un paquet 0-RTT et le rejouer — le serveur recevrait alors deux fois la même opération. Règle de sécurité : ne mets en 0-RTT que des opérations idempotentes (une lecture, jamais un « débite 100 € »). C'est un compromis vitesse/sûreté à manier avec précaution.

Des boutons de réglage

Fidèle à la philosophie du contrôle, WebTransport expose des préférences plutôt que de tout cacher : congestionControl permet d'indiquer si tu privilégies le débit ou la latence, et reliability renseigne sur le support du transport fiable ou non. Tu orientes le comportement sans réécrire la pile réseau.

Tout ce socle — QUIC, son handshake, son 0-RTT (hérité de TLS 1.3) — est creusé dans HTTP · De 1.1 à 3 et TLS/HTTPS.

Le simulateur ci-dessous met les deux mondes face au changement de réseau. Bascule le réseau et compare ce qui arrive à une session WebSocket/TCP et à une session WebTransport/QUIC.

Change de réseau et compare les deux sessions :

07 — ÉTABLIR UNE SESSION

Une connexion, mille usages

Fini d'« upgrader » toute la connexion comme avec WebSocket. WebTransport ne réserve qu'un stream — si bien qu'une même connexion porte tes pages, une session WebTransport et un flux SSE, en même temps.

Comment ouvre-t-on une session WebTransport ? La réponse révèle une des plus belles idées du protocole. Pour la saisir, repartons de WebSocket.

Avec HTTP/1, WebSocket s'établit via un en-tête Connection: Upgrade : on prend la connexion TCP existante et on la convertit entièrement en canal WebSocket. À partir de là, cette connexion ne sert plus qu'à ça. C'était acceptable en HTTP/1 — mais en HTTP/2 et /3, ce serait du gâchis : on perdrait une connexion précieuse, capable de multiplexer des dizaines de streams, juste pour un seul usage.

Le CONNECT étendu (RFC 8441)
Plutôt que d'upgrader toute la connexion, on n'en réserve qu'un stream. Une méthode HTTP spéciale, CONNECT étendue (introduite par la RFC 8441 pour faire passer WebSocket sur HTTP/2), négocie ce stream. Si le serveur accepte (réponse 200), ce stream devient le canal — et son identifiant sert d'identifiant de session pour ouvrir d'autres streams ensuite.

La conséquence est spectaculaire. Une seule connexion vers un domaine, sur le port 443, peut désormais porter simultanément :

1 connexion :443
GET/POST normaux
·
session WebTransport (N streams)
·
flux SSE

Tu peux continuer à cliquer sur des liens et charger des pages pendant qu'une session WebTransport fait circuler cinq streams et qu'un flux d'événements tourne en parallèle — le tout sur la même connexion. On peut même ouvrir plusieurs sessions sur une seule connexion, chacune avec sa propre authentification.

🔑 Côté QUIC, les identifiants de stream encodent qui les a ouverts (client ou serveur) et leur sens (uni ou bidirectionnel) : client et serveur puisent dans des plages distinctes, si bien que leurs streams ne se télescopent jamais — sans coordination. Et comme tout passe par TLS, le chiffrement est intégré au transport (voir TLS/HTTPS).

Le simulateur ci-dessous est cette connexion unique. Ajoute différents canaux et regarde-les cohabiter, chacun avec son identifiant de stream.

Ajoute des canaux sur la même connexion :

08 — L'API EN PRATIQUE

L'API en pratique

Assez de théorie. Voici à quoi ressemble vraiment WebTransport dans du JavaScript de navigateur : ouvrir une session, créer un stream, pousser un datagramme — le tout sur l'API Streams standard.

Les concepts sont posés ; voyons le code réel. L'API WebTransport du navigateur est étonnamment compacte, et elle s'appuie entièrement sur l'API Streams standard du web (ReadableStream / WritableStream) — donc tu récupères le contrôle de flux (backpressure) gratuitement.

Ouvrir une session

const wt = new WebTransport('https://exemple.com:4433/chat');
await wt.ready;           // la session est prête
// wt.closed est une Promise qui se résout à la fermeture

Un stream bidirectionnel fiable

const stream = await wt.createBidirectionalStream();

const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode('salut'));

const reader = stream.readable.getReader();
const { value, done } = await reader.read();

Des datagrammes non fiables

// wt.datagrams est un flux duplex (lecture + écriture)
const dgWriter = wt.datagrams.writable.getWriter();
dgWriter.write(payload);          // tire et oublie : ni ordre ni retransmission

const dgReader = wt.datagrams.readable.getReader();
const { value } = await dgReader.read();
Les streams initiés par le serveur
Le serveur aussi peut ouvrir des streams. Côté client, on les reçoit via wt.incomingBidirectionalStreams et wt.incomingUnidirectionalStreams — eux-mêmes des ReadableStream dont chaque élément est un stream entrant à lire.

Régler et fermer

// préférence exprimée à la création
const wt = new WebTransport(url, { congestionControl: 'low-latency' });

await wt.getStats();     // statistiques HTTP/3 de la connexion
wt.close({ closeCode: 0, reason: 'fini' });
💡 Tout est en API Streams. Lecteurs, écrivains, backpressure : c'est la même mécanique que fetch().body ou les flux Node. Si cette API te semble nouvelle, les flux et le backpressure sont au cœur des cours Streaming HTTP et PHP Streaming.
09 — SYNTHÈSE

Lequel choisir, et pour quoi

SSE, WebSocket, WebRTC, gRPC, WebTransport : cinq façons de dépasser le request/response. Voici la carte pour t'y retrouver — et un pari sur ce qui survivra.

Cinq façons de dépasser le vieux request/response coexistent aujourd'hui. Aucune n'est « la meilleure » dans l'absolu — chacune répond à un besoin. Voici la carte.

TechnoSensTransportNon fiable ?Pour quoi
SSEServeur → clientHTTP/TCPNonFlux d'événements descendants (notifs, ticks)
WebSocketBidirectionnelTCPNonBidirectionnel mature, support universel
WebRTCBidirectionnel (P2P)UDPOuiPair-à-pair audio/vidéo
gRPCBi/unidirectionnelHTTP/2NonService-à-service (pas natif navigateur)
WebTransportBi/unidirectionnelHTTP/3 (QUIC)OuiTemps réel moderne, fiable et non fiable

Comment choisir

Ce que tu emportes
WebTransport n'invente pas le temps réel : il en réunit les meilleures idées sur la fondation la plus solide (QUIC). Une session, des streams au choix fiables ou non, le tout multiplexé sur une connexion qui sert aussi le reste du site. C'est l'aboutissement d'une longue lignée de ruses pour faire parler le serveur.
💡 Un pari, pour finir. Beaucoup pensent que WebTransport finira par remplacer WebRTC, gRPC et WebSocket — en absorbant leurs usages dans un seul protocole. Peut-être dans trois ans, peut-être dans vingt, peut-être jamais : la spec est encore un brouillon, et l'histoire des protocoles est pleine de favoris déchus. Mais la direction est claire, et elle vaut la peine d'être comprise dès maintenant.

Pour explorer les territoires voisins : HTTP · De 1.1 à 3 (QUIC, streams, blocage en tête de file), Chat temps réel serverless (WebSocket en pratique), Streaming HTTP (SSE), TCP & Sockets et TLS/HTTPS.