iphonephotobackup.com - GET /how.html - 200 OK
A short tour for people who like cables, packets, and not sending their camera roll to a cloud.
The page is a static bundle: HTML, JavaScript, and a Zig program compiled to WebAssembly. After it loads, it does not need the internet. USB talks to the phone. The File System Access API writes into the folder you picked. Pairing keys stay in this browser's IndexedDB. There is no account, no server copy, no analytics.
To verify: open DevTools, Network, start a backup, and watch that the only traffic (if any) is this page. Or toggle airplane mode after load.
com.apple.afc. AFC is Apple File Conduit: a simple RPC to list directories and read files, jailed to the media tree (/DCIM, /PhotoData).The mux/lockdown/AFC state machine is synchronous: it blocks on USB reads. Browsers refuse to block the UI thread, so the Zig WASM runs in a worker and waits with Atomics.wait on a SharedArrayBuffer. The page thread owns WebUSB and the folder handle, and replies to the worker. That is also why this page is served with COOP/COEP (cross-origin isolation). SharedArrayBuffer requires it.
Chrome and Edge on localhost or HTTPS. Firefox's WebUSB support is not enough for this.
The first time, iOS shows Trust This Computer. We generate a pairing record (certificates + host id) and save it only in IndexedDB under this origin. Next visit, the same browser can skip the dialog unless you wiped site data. That record never goes to a server. Clearing this site's data in the browser forgets the pairing.
USB 2.0 High Speed tops out around 35 to 40 MiB/s of useful payload in practice. The speed you see is an exponential moving average of bytes actually written, so a single huge video does not make the number jump around. Time remaining is remaining bytes divided by that smoothed rate, then smoothed again so "38 minutes" does not flicker to 12 and back.
usbmuxd, libimobiledevice, or FUSE on the host.Photos.sqlite in your destination directory after a copy, not from a remote API.