Send a file or text from one computer to another, directly. No upload, no account, no copies left on a server.
Try it: https://peeryeet.com
HORSE-LAMP-0427 and a QR code.Most "send a file" sites upload your file to their server, and the other side downloads it from there. PeerYeet doesn't. The server only introduces the two browsers. After that, they talk to each other over a WebRTC data channel, which is encrypted end to end.
setup (a few small messages) the transfer itself
Browser A ─┐ ┌─ Browser B Browser A ══════════════ Browser B
▼ ▼ direct WebRTC
signaling server
There is deliberately no relay (TURN) server. If the two browsers can't reach each other directly, the transfer fails and the page explains why, rather than quietly routing your data through someone else's machine. That mostly happens on strict office or school networks, some VPNs, and some mobile carriers.
Because the server never carries file data, a 500 GB transfer costs it the same as a 5 KB one. That's what lets the site stay free.
#HORSE-LAMP-0427), which browsers never
send to the server.One limit to be aware of: the signaling server passes along the messages that set up the encrypted connection, so you are trusting it not to tamper with them. A server that did tamper could put itself in the middle of the connection. If that's a concern, host your own. Stronger pairing is an open item in the design doc (§11).
You don't have to take any of this on faith. The logic is under 1,700 lines in two files, web/app.js and server/signal.c.
PeerYeet reads and writes files in chunks, so big transfers work. In Chrome, Edge and other Chromium browsers, the receiver picks where to save first and data streams straight to disk. Other browsers keep the file in memory until you save it, and the page warns you about that for files over 1 GB.
There are no frameworks and no build step.
| Path | What it is |
|---|---|
| web/ | The site: plain HTML, CSS and JavaScript. Served as is. |
| server/ | The signaling server: one C file, a single-threaded epoll loop with just enough WebSocket to pair two browsers. Linux only. |
| deploy/ | Caddy and systemd setup for the production host. |
| docs/concept-and-architecture.md | The design doc: what PeerYeet is, why, and what's next. |
| docs/signaling-protocol.md | The wire protocols, both browser-to-server and browser-to-browser. |
You need a C compiler, make and Python 3.
make -C server
./server/peeryeet-signal & # signaling on localhost:9000
python3 -m http.server 8000 -d web # site on localhost:8000
Open http://localhost:8000 in two windows; make the second one private so the
two don't share state. When the page is served from a non-default port, it
looks for signaling on port 9000 of the same host. Add
?ws=ws://host:port/ws to the URL to point it somewhere else.
Browsers allow Web Crypto (and the save-to-disk picker) only on secure
origins, so testing between two machines over plain http://<lan-ip> won't
work. Use an HTTPS deployment for that.
python3 server/test_signal.py # signaling server tests
.venv/bin/python tests/e2e.py # two headless browsers, real WebRTC
The end-to-end test needs Playwright; setup steps are at the top of tests/e2e.py.
deploy/ contains the full setup for a single small Linux host:
Caddy serves the site, gets HTTPS certificates automatically and forwards
/ws to the signaling server, which runs as a locked-down systemd service. A
t3.micro is plenty. Follow deploy/README.md.
To use your own domain, change peeryeet.com in
deploy/Caddyfile and in the "go to" hint in
web/index.html. The small ad at the bottom of the page is
for the author's math app; feel free to remove it.
Issues and pull requests are welcome. Please keep to the spirit of the project: direct transfers only, no build step, and as few dependencies as possible (right now there's one, a vendored QR code library).
To report a security problem, please don't open a public issue. See SECURITY.md.
MIT; see LICENSE. web/qrcode.js is by Kazuhiko Arase, also under MIT.
Also by the author: Wyrm, an app for learning algebra by touch. Drag terms, cancel factors, and you can't break the math. iOS and Android.
Send a file or text from one computer to another, directly. No upload, no account, no copies left on a server.
Try it: https://peeryeet.com
HORSE-LAMP-0427 and a QR code.Most "send a file" sites upload your file to their server, and the other side downloads it from there. PeerYeet doesn't. The server only introduces the two browsers. After that, they talk to each other over a WebRTC data channel, which is encrypted end to end.
setup (a few small messages) the transfer itself
Browser A ─┐ ┌─ Browser B Browser A ══════════════ Browser B
▼ ▼ direct WebRTC
signaling server
There is deliberately no relay (TURN) server. If the two browsers can't reach each other directly, the transfer fails and the page explains why, rather than quietly routing your data through someone else's machine. That mostly happens on strict office or school networks, some VPNs, and some mobile carriers.
Because the server never carries file data, a 500 GB transfer costs it the same as a 5 KB one. That's what lets the site stay free.
#HORSE-LAMP-0427), which browsers never
send to the server.One limit to be aware of: the signaling server passes along the messages that set up the encrypted connection, so you are trusting it not to tamper with them. A server that did tamper could put itself in the middle of the connection. If that's a concern, host your own. Stronger pairing is an open item in the design doc (§11).
You don't have to take any of this on faith. The logic is under 1,700 lines in two files, web/app.js and server/signal.c.
PeerYeet reads and writes files in chunks, so big transfers work. In Chrome, Edge and other Chromium browsers, the receiver picks where to save first and data streams straight to disk. Other browsers keep the file in memory until you save it, and the page warns you about that for files over 1 GB.
There are no frameworks and no build step.
| Path | What it is |
|---|---|
| web/ | The site: plain HTML, CSS and JavaScript. Served as is. |
| server/ | The signaling server: one C file, a single-threaded epoll loop with just enough WebSocket to pair two browsers. Linux only. |
| deploy/ | Caddy and systemd setup for the production host. |
| docs/concept-and-architecture.md | The design doc: what PeerYeet is, why, and what's next. |
| docs/signaling-protocol.md | The wire protocols, both browser-to-server and browser-to-browser. |
You need a C compiler, make and Python 3.
make -C server
./server/peeryeet-signal & # signaling on localhost:9000
python3 -m http.server 8000 -d web # site on localhost:8000
Open http://localhost:8000 in two windows; make the second one private so the
two don't share state. When the page is served from a non-default port, it
looks for signaling on port 9000 of the same host. Add
?ws=ws://host:port/ws to the URL to point it somewhere else.
Browsers allow Web Crypto (and the save-to-disk picker) only on secure
origins, so testing between two machines over plain http://<lan-ip> won't
work. Use an HTTPS deployment for that.
python3 server/test_signal.py # signaling server tests
.venv/bin/python tests/e2e.py # two headless browsers, real WebRTC
The end-to-end test needs Playwright; setup steps are at the top of tests/e2e.py.
deploy/ contains the full setup for a single small Linux host:
Caddy serves the site, gets HTTPS certificates automatically and forwards
/ws to the signaling server, which runs as a locked-down systemd service. A
t3.micro is plenty. Follow deploy/README.md.
To use your own domain, change peeryeet.com in
deploy/Caddyfile and in the "go to" hint in
web/index.html. The small ad at the bottom of the page is
for the author's math app; feel free to remove it.
Issues and pull requests are welcome. Please keep to the spirit of the project: direct transfers only, no build step, and as few dependencies as possible (right now there's one, a vendored QR code library).
To report a security problem, please don't open a public issue. See SECURITY.md.
MIT; see LICENSE. web/qrcode.js is by Kazuhiko Arase, also under MIT.
Also by the author: Wyrm, an app for learning algebra by touch. Drag terms, cancel factors, and you can't break the math. iOS and Android.