⚡ Direct, device-to-device file transfer — in the browser, no size limit, nothing stored on a server.
Two devices pair with a 6-digit code. Once they're linked, the file streams straight from one browser to the other over WebRTC. No upload-then-download wait, no storage quota, no accounts.
┌────────────┐ 6-digit code ┌────────────┐
│ Device A │ ─────────────────────────▶ │ Device B │
│ (sender) │ │ (receiver) │
└────────────┘ └────────────┘
│ │
└──────────── direct WebRTC link ───────────┘
(file bytes, not the server)
| No middleman for file data | The server only handles the initial handshake (a pairing code + WebRTC signaling). Once connected, files move directly between browsers. |
| No size limit | Large files (10GB+) stream straight to disk on the receiving end via the File System Access API, instead of piling up in memory. |
| Backpressure-aware | Files send in 64KB chunks and pause automatically when the connection's buffer fills, so nothing overwhelms either device. |
| Works across networks | Same WiFi uses a direct connection. Different networks (e.g. phone on mobile data, laptop on WiFi) fall back to a TURN relay when configured — see below. |
npm install
npm startOpen http://localhost:3000 — on two devices on the same network, or two tabs to try it solo.
Any Node host works. Render has a genuine free tier and is the easiest starting point:
- Push this repo to GitHub.
- On Render: New → Web Service → connect the repo.
- Build command:
npm install· Start command:npm start· Instance: Free. - Deploy — you'll get a public
https://URL that works from any device, anywhere.
Free tier note: the service sleeps after 15 minutes idle and takes ~30–60s to wake on the next visit. Fine for occasional transfers; upgrade to a paid instance if you want it always warm.
STUN (used by default) only helps two devices discover each other — it doesn't relay traffic. If both devices are on the same network, that's usually enough. If they're on different networks, a certain share of connections will be blocked by NAT/firewalls unless a TURN server is configured to relay the (still end-to-end encrypted) traffic.
Set these environment variables — the server picks them up automatically:
TURN_URL=turn:your-turn-server.example.com:3478
TURN_USERNAME=your-username
TURN_CREDENTIAL=your-credentialOptions:
- Quick test: the free Open Relay Project —
turn:openrelay.metered.ca:80/ user & passopenrelayproject. Shared and rate-limited, good for confirming things work, not for daily use. - Your own, still free: Metered gives 5GB/month on a free plan with private credentials.
- Self-hosted: run coturn (free, open source) alongside this app for full control.
Without TURN, FileBeam still works well on the same network and many cross-network pairs — it just can't guarantee a connection in every NAT scenario.
Stuck on "Connecting" — signaling worked, but the direct WebRTC link never formed. Check, roughly in order of likelihood:
- Router client/AP isolation — common on ISP routers, blocks same-WiFi devices from reaching each other directly. Look for "AP Isolation" / "Client Isolation" in router settings.
- Mobile hotspot quirks — phone hotspots often don't properly route traffic back to the phone itself. A TURN server (above) sidesteps this entirely.
- Windows network profile set to "Public" — switch to "Private" under Settings → Network & Internet.
- Firewall blocking the browser — check Windows Defender Firewall → "Allow an app through firewall."
- Different networks with no TURN configured — see the TURN section above.
For deeper digging: chrome://webrtc-internals shows the live ICE negotiation and exactly where it's failing.
- Pairing codes are single-use and tied to one session — closing the tab invalidates it.
- Browsers without the File System Access API (Firefox, Safari) buffer incoming files in memory instead of streaming to disk — fine for most files, but very large ones are limited by available RAM.
- No database, no file storage, no accounts — restarting the server just clears any pending pairing codes.
MIT


