WebRTC vs WebSockets for File Transfer
By SRIFT maintainers · Published
Reviewed by SRIFT maintainers · last reviewed against the SRIFT 4.3.2 source.
Short answer
A WebRTC data channel sends the file directly between the two devices (or through a TURN relay that sees only DTLS ciphertext), so the server carries no file bytes and the speed is set by the path between the peers. A WebSocket transfer always goes through a server: it connects on almost any network, but the server pays for every byte twice and, with TLS alone, can read the file.
Neither wins everywhere. Direct channels are cheaper and often faster when they open; WebSocket relays are simpler and work where WebRTC cannot. A dependable tool uses both, and seals relayed chunks with keys only the two devices hold.
- WebRTC path
- Peer to peer, or via TURN when no direct pair works
- WebSocket path
- Always client to server to client
- Encryption by default
- WebRTC: DTLS between peers. WebSocket: TLS to the server
- Server bandwidth
- WebRTC: none (unless TURN). WebSocket: in and out, every byte
The difference that matters: where the bytes go
A WebSocket (RFC 6455) is a long-lived, message-framed connection over TCP from a browser to a server. Browsers can open WebSockets but cannot accept them, so two browsers exchanging a file over WebSockets each connect to the same server, and the server copies every message from one socket to the other.
A WebRTC data channel is negotiated through a server too, but only the small offer, answer and network candidates take that route. After ICE finds a working address pair, the file travels on the peer-to-peer path inside DTLS. When no direct pair works, a TURN server forwards the encrypted packets, which makes it a relay of a different kind: it moves ciphertext it has no key for, and it is used only as a last resort. The data channel guide explains that stack in detail.
Everything else in the comparison (cost, speed, privacy, reliability on hostile networks) follows from this single difference in topology.
Side-by-side comparison
| WebRTC data channel | WebSocket via a server | |
|---|---|---|
| Data path | Direct between peers; via TURN when no direct pair works. | Always sender to server to receiver. |
| Connection setup | Signaling round trips, ICE checks and a DTLS handshake before the first byte; seconds on difficult networks. | One TCP + TLS connection and an HTTP upgrade; usually fast and predictable. |
| Latency | One network path; on a LAN the traffic never leaves the building. | Two legs through the server's location, even for two devices in the same room. |
| What limits throughput | Slowest link between peers, SCTP congestion control and buffering in the browser, TURN capacity if relayed. | Sender's uplink to the server, the server's own bandwidth and CPU, receiver's downlink. |
| Server bandwidth cost | None on a direct path; TURN carries every byte when used. | Every byte enters and leaves the server. |
| NAT and firewalls | Fails without TURN on networks that block UDP or use hostile NATs; TURN over TLS on port 443 often recovers them. | Works wherever outbound HTTPS works, apart from some proxies that break the upgrade. |
| Encryption scope | DTLS from one browser to the other; TURN cannot decrypt. | TLS from each browser to the server; the server sees plaintext unless the app encrypts end to end. |
| Head-of-line blocking | Per channel; ordering can be turned off; SCTP streams do not block each other except behind a large message. | TCP delivers one byte stream: one lost packet stalls everything behind it. |
| Backpressure API | bufferedAmount on the sender; nothing on the receiver. | bufferedAmount on the sender; nothing on the receiver. |
| Ease of implementation | Harder: signaling, ICE servers, TURN credentials, connection-state handling. | Easier: one server endpoint and ordinary socket code. |
One row deserves emphasis: neither API gives the receiver backpressure. Both push messages at the page as fast as they arrive, so a transfer of any real size needs an application-level “pause” message from the receiver whichever transport carries it.
Encryption: which hops, whose keys
“Encrypted” means different things on the two transports. With WebSockets over wss://, TLS protects the browser-to-server hop and the server-to-browser hop separately. The server terminates both, so it, its hosting provider, and anyone who compromises it can read the file. That is the ordinary model for most web uploads, and it is fine when the server is meant to have the data.
A WebRTC data channel is encrypted with DTLS keys negotiated by the two browsers themselves; a TURN relay in the middle cannot read it. There is a catch: the browsers authenticate each other only by certificate fingerprints carried in the SDP, which travels through the signaling server. A signaling server that rewrites those fingerprints can place itself in the middle. DTLS therefore protects against the network and the TURN operator, and against an honest signaling server, but not against a malicious one unless the application verifies fingerprints by another route.
A relay can reach a similar position with application-level encryption: each device generates a key pair, they agree a shared key with ECDH, and every chunk is sealed with an AEAD cipher such as AES-256-GCM before it goes onto the socket. The relay then forwards ciphertext. It still sees metadata (IP addresses, sizes, timing, and whatever the protocol sends in clear), which what a relay can see inventories. Public keys exchanged through the server have the same weakness as fingerprints in SDP: the server introduces them.
Speed and reliability in practice
Claims that one transport is simply “faster” are not meaningful without the path. Some useful rules:
- Same network: a direct data channel can stay on the local network, while a relay sends the bytes to a data centre and back. This is where WebRTC has its clearest advantage.
- Different networks, both with good links: both are usually limited by the sender's upload. A well-provisioned relay close to both peers can be competitive with a direct path across a congested long route.
- Lossy links: TCP's single ordered stream stalls on every loss. SCTP has the same issue within one ordered channel, but control messages on another channel are not blocked behind file data.
- Hostile networks: blocked UDP, symmetric NATs or TLS-inspecting proxies may defeat WebRTC without a TURN server reachable on port 443. WebSockets fail only when the proxy breaks the HTTP upgrade, and even then an HTTPS long-polling stream can stand in.
The operator's cost differs sharply. A relay that forwards a 10 GB file moves 20 GB through its network interface. A direct data channel moves nothing through the operator, and TURN moves the same 20 GB only for the sessions that need it. The slow transfer guide covers how to tell which link is the bottleneck.
Why SRIFT uses both
SRIFT's browser client (version 4.3.2) runs what its code calls relay-first with a WebRTC head start. The design accepts that direct connections are better when they work and that waiting for one that will never open is the worst outcome.
- Capability check. A short probe asks public STUN servers for a server-reflexive candidate to learn whether UDP works, and the page fetches short-lived TURN credentials. If neither UDP nor TURN is available, WebRTC is skipped and the relay starts at once.
- Head start. Otherwise the direct channel gets 3 seconds to open. No file bytes are sent before it opens, so abandoning it at the deadline cannot duplicate or corrupt anything. If it opens, it carries the whole file.
- Relay fallback. If the channel misses the deadline or fails mid-transfer, the WebSocket relay takes over. Both transports write into one byte-addressed file on the receiver, which reports what it already holds, so the relay sends only the remainder. The transfer never switches back to WebRTC mid-stream, because changing transports twice is where ordering bugs live.
On the relay, each 256 KB chunk is sealed with AES-256-GCM under a key derived (HKDF-SHA256) from a fresh ECDH P-256 exchange made for that transfer. The chunk's file ID, index and total count are bound in as additional authenticated data, so the relay cannot reorder or splice chunks undetected. Up to 16 chunks are in flight, and unacknowledged ones are re-sent after 8 seconds. The CLI and its daemon use this sealed relay for session transfers rather than raw WebRTC. When WebSockets cannot open at all, the browser moves its whole session connection onto HTTPS requests instead.
Which one to choose
WebSockets alone are enough when
- Files are small and the server should have them anyway (uploads into your own application).
- Your users are mostly on locked-down corporate networks and you cannot run TURN.
- You want the simplest correct implementation and can pay for the bandwidth.
WebRTC is worth the extra work when
- Files are large, and relaying them would dominate your hosting bill.
- Peers are often on the same network, where a direct path avoids the round trip to a data centre.
- You want the server out of the data path, and you will handle the signaling trust problem honestly.
Use both when
You need transfers to succeed for everyone. Time-box the direct attempt, relay with end-to-end sealing when it fails, and make the two transports resume from the same byte offset. That is more code than either alone, but it is the only arrangement that is both efficient on good networks and dependable on bad ones. SRIFT's browser P2P transfer is one working example.
Frequently asked questions
Can two browsers connect to each other with WebSockets directly?
No. Browsers can open WebSocket connections but cannot listen for them, so one end of every WebSocket is a server. Browser-to-browser over WebSockets always means relaying through a server.
Is WebTransport a replacement for either?
WebTransport runs over HTTP/3 (QUIC) between a browser and a server, so like WebSockets it is client-to-server. It can avoid TCP head-of-line blocking and offers unreliable datagrams, which makes it an alternative for the relay leg, not for a direct peer-to-peer path.
References
Try a direct transfer
Open a session in one browser, join it from another device, and send a file. No account, nothing to install on either side.
Related resources
- How WebRTC File Transfer Works: Data Channels in PracticeWebRTC data channels explained for file transfer: SCTP over DTLS, message sizes, backpressure with bufferedAmount, ordering, and what breaks at scale.Explainer
- What a File Transfer Relay Can Actually SeeEven with end-to-end encryption, a relay sees metadata: IP addresses, sizes and timing. A concrete inventory, using SRIFT as the worked example.Explainer
- Why Is P2P File Transfer Slow? How to Find the BottleneckUpload bandwidth, TURN relaying, Wi-Fi, buffering and encryption overhead: how to find what is limiting a peer-to-peer transfer and fix it.Troubleshooting
