Every few months I want to send a file to someone and realise none of the options are quite right. Email has size limits. Cloud drives want accounts on both ends. Most “send a link” services promise privacy on a page full of tracking pixels. AirDrop is great until the recipient is on a different operating system or a different continent.

So I built TorDrop. It’s a small native macOS app that turns any file on your disk into a .onion URL you can hand to someone. They open it in Tor Browser and download. You click Stop Sharing. The onion service, and its private key, cease to exist.

No accounts. No servers I run. No persistent keys anywhere.

The pitch

Open TorDrop, drop one or more files into the window (or use the file picker), and you get a .onion URL and a QR code. Send the URL to whoever needs the files, over whatever secure channel you already use to talk to them. They open it in Tor Browser and download. When you’re done, you click Stop Sharing and the onion service vanishes.

That’s the whole app.

It’s deliberately minimal. There’s no sign-in, no “my files” list, no history. Nothing is ever uploaded anywhere - the file stays on your disk the entire time, served directly from your machine through Tor.

While a share is starting or live, TorDrop also drops a small status icon into the menu bar. Click it to bring the window back, or drop a file straight onto it to start another share. When nothing is being shared, the menu bar icon disappears.

How it works

File → local HTTP server (127.0.0.1:random) → tor → v3 onion service → Recipient

When you share a file, TorDrop starts a tiny HTTP server bound to a random loopback port on your machine. It then spawns tor, connects to its control port, and asks it to create an ephemeral v3 hidden service that forwards onion port 80 to the local HTTP port.

The magic bit is the ADD_ONION NEW:ED25519-V3 Flags=DiscardPK command. That tells tor to generate a fresh onion service keypair and not hand us the private key. The service exists only inside that running tor process. When you stop sharing, the process forgets it, and the .onion address is gone forever. There is nothing on disk to leak, back up, or forget to wipe.

Why native

I wanted sharing a file to feel like AirDrop, not like opening a webapp. A regular Mac app you can drag files into, that doesn’t need a browser tab of its own, and that gets out of the way when you’re not using it.

The whole thing is a SwiftUI window backed by an NSWindowController, with an NSStatusItem that only appears while a share is active - so you can dismiss the window and still see at a glance that something is being shared, and drop more files on it if you want.

The surprising part: writing an HTTP server by hand

TorDrop has exactly one external dependency: the tor daemon itself. Everything else - the HTTP server, the Tor control-protocol client, the QR code renderer - is first-party code built on the macOS system frameworks.

This wasn’t philosophical purity. It’s that for something whose whole value proposition is “this is doing what it says on the tin,” auditability matters. A dependency tree a mile long undermines the pitch. If you can read the source in an afternoon, you can actually trust it.

So I wrote the HTTP server. It’s a small Network.framework listener that speaks just enough HTTP/1.1 to serve a directory listing and range-request downloads. I wrote the Tor control-protocol client too - it’s a line-oriented text protocol that’s genuinely pleasant to implement. Between the two, it’s a few hundred lines of Swift. Small enough to reason about, big enough that it definitely works.

There’s something grounding about writing the primitives yourself once in a while. You remember that HTTP is not magic, that a file server is just sockets and strings, that the stack you depend on every day is made of things a person wrote.

Security notes

TorDrop doesn’t try to add anything on top of what Tor itself provides. What it does try to do is not weaken it:

The usual Tor caveats still apply. If you need to be certain the URL reached the right person, confirm it through a channel you already trust.

What it’s for (and what it isn’t)

TorDrop is for one-off, person-to-person file handoffs where you care about not routing the file through somebody else’s infrastructure. Sending a keyfile to a colleague. Sharing a video with a family member abroad. Getting a big artifact off your machine and onto theirs without it being cached, indexed, or scanned along the way.

It is not a backup tool, not a sync client, not a hosting service. Your machine has to be on for the transfer to work. The moment you stop sharing or quit the app, it’s over.

Play with it

github.com/tuckerwales/tordrop - source, build instructions, and a Makefile that produces a .app. You’ll need brew install tor and macOS 13 or later.

If you try it, I’d love to hear how it went.