Transfer files between computers using only a screen and a camera — no internet, no USB, no cables.
Some machines simply cannot be connected to anything:
- Old laptops with dead Wi-Fi/USB ports — the hardware is broken and plugging in anything isn't an option.
- Air-gapped secure VMs — corporate policy or security requirements prohibit network access, and USB ports are disabled or physically absent.
- Sandboxed research environments — you need to pull results out of an isolated VM without breaking its security boundary.
- Borrowed or locked-down machines — you don't have admin rights to install drivers or enable ports.
In all these situations you still have two things: a screen and a camera (or a phone). QROP turns that into a data channel.
- Sender reads the files you want to transfer, compresses text content with zlib, and splits everything into 1 300-byte source blocks.
- Each block is wrapped in a Fountain (LT) code — a rateless erasure code that lets the receiver reconstruct all blocks even if it misses some frames.
- Blocks are packed into QR codes (version 30-M, ~1 373 bytes capacity) and displayed on screen at a configurable frame rate (default 8 fps).
- Receiver captures frames from the camera, decodes each QR code, feeds blocks into a belief-propagation decoder, and writes the files to disk once all source blocks are recovered.
- Every file is verified with SHA-256 after reassembly.
Because Fountain codes are rateless, the sender loops indefinitely — the receiver can join late, take a break, or miss bursts of frames, and still recover the full transfer.
- Python 3.10+
- A webcam or phone camera on the receiving machine
- Both machines need Python and the dependencies below
pip install -r requirements.txt
Dependencies: segno, opencv-python, pyzbar, Pillow, msgpack, numpy, zstandard
macOS / Linux note:
pyzbarrequires thezbarnative library.
- macOS:
brew install zbar- Ubuntu/Debian:
sudo apt install libzbar0
python -m qropClick Send, select the file or folder you want to transfer, then click Start. A fullscreen QR stream begins.
python -m qropClick Receive. Point the camera at the sender's screen. Progress bars show per-file recovery. Files are saved to ~/Downloads when complete.
If the destination machine has Python but not the QROP package, use the bootstrap scripts to transfer the sender itself via QR codes first.
On the source machine (needs segno and Pillow):
pip install segno Pillow
python bootstrap/bootstrap_sender.pyOn the destination machine (needs opencv-python and pyzbar):
pip install opencv-python pyzbar
python bootstrap/bootstrap_receiver.pyThis transmits bootstrap_sender.py as a series of small QR codes (~2 s each). Once received, install the full requirements and run normally:
pip install -r requirements.txt
python -m qropqrop-repo/
├── qrop/
│ ├── app.py # Mode selection UI
│ ├── sender.py # Sender GUI + encoding engine
│ ├── receiver.py # Receiver GUI + decoding engine
│ ├── fountain.py # LT (Luby Transform) fountain codes
│ ├── protocol.py # QR packet format & wire encoding
│ └── utils.py # File scanning, block prep, SHA-256 reassembly
├── bootstrap/
│ ├── bootstrap_sender.py # Transfer the app itself — no internet needed
│ └── bootstrap_receiver.py # Receive the bootstrap transmission
├── assets/
│ └── qrop_demo.gif # Demo animation
└── requirements.txt
- Lighting matters — good ambient light on the sender screen significantly improves decode rate.
- Screen brightness — turn the sender's screen to maximum brightness.
- Distance — 40–70 cm between camera and screen is typically optimal.
- Frame rate — lower FPS (e.g. 4–6) gives the receiver more time per frame on slow cameras or at distance.
- Large files — the transfer loops continuously, so there is no rush; the receiver will catch up.
MIT
