DEV Community

Lucian (LKB)
Lucian (LKB)

Posted on Originally published at lkforge.com

I put my own "no-upload" tools on a network monitor. Here's what actually left the browser.

"Runs in your browser, nothing uploaded" is the easiest claim in web tooling to make -- and one of the easiest to fake. A tool can pretty-print your JSON locally and quietly POST it to a server for "analytics." The only way to know is to watch the network.

So I did that to my own tools. I opened 15 of them across nine categories with the browser's network panel recording every request, and wrote down exactly where each one went. This is the method and the result -- and, more usefully, a snippet you can paste to check any tool yourself.

The method (repeat it on anything)

Every browser keeps a complete list of the hosts a page contacted. The Network tab shows it visually; the Performance API returns it as data. Load the tool, use it, then run this in the console:

const hosts = {};
for (const e of performance.getEntriesByType('resource')) {
 const h = new URL(e.name).host;
 if (!h.endsWith('lkforge.com')) hosts[h] = (hosts[h] || 0) + 1;
}
console.table(hosts);
Enter fullscreen mode Exit fullscreen mode

Swap lkforge.com for whatever origin you're testing. It prints every host the page touched that isn't the site itself. On a genuinely local tool you'll see almost nothing; on one that phones home, you'll see where.

The stronger test needs no code at all: load the tool, kill your network, keep using it. Anything that still works was never talking to a server.

The result: three tiers, not two

"Local vs. uploads" turned out to be too coarse. The tools fell into three clear tiers.

Tier 1 -- fully local (9 of 15). The formatters, a CSV converter, a Base64 encoder, a PDF splitter, an EXIF remover, a loan calculator, a chess engine: every request went to the site's own origin -- HTML, CSS, JS, and the fonts. None of them sent the text, file, or image you give them. Once the code has loaded, they do their work with the network off.

One detail that surprised me: the fonts are served first-party, not fetched from Google Fonts. No fonts.gstatic.com request at all. (It's Cloudflare rewriting the Google Fonts stylesheet into same-origin @font-face at the edge -- the browser never contacts Google.)

Tier 2 -- same-origin proxy (3 of 15). A few tools genuinely need outside data -- your public IP, where an asteroid will pass, which volcanoes are erupting. The interesting part is how they get it: the browser only ever talked to the site's own /api/* endpoints. An edge worker fetches the third party server-side and relays the result. From NASA's or the IP-lookup service's point of view, the server asked -- your browser and your IP stayed put.

Tier 3 -- direct public API (3 of 15). Three tools did contact an outside host directly: an earthquake feed (USGS), the ISS position (wheretheiss), and a currency table (er-api). In each case the request asks for public data and carries nothing personal. The currency tool, for instance, downloads the day's rate table once and then converts locally.

The honest exceptions (this is the important part)

"Nothing ever leaves your browser" is not true of every feature on any real site, and pretending otherwise is how you lose trust the first time someone opens DevTools. A handful of tools have to send something to do their job -- you cannot look up a domain's DNS, or identify a plant from a photo, without sending the domain or the photo. On my side that list is: weather (your location), DNS lookup (the domain), a plant identifier (your photo), voice dictation (your audio, via the browser's own Web Speech API), and the contact form (your message).

The point isn't that a privacy-first site has zero exceptions. It's that the exceptions are enumerated, not hidden. A claim survives DevTools only if the edge cases are named up front.

The one third-party host I couldn't hand-wave

On the "fully local" tools, exactly one non-origin host showed up: static.cloudflareinsights.com -- Cloudflare's Web Analytics. It's cookieless and receives the page URL, screen size, and load timing, not the contents of any tool. I'm counting it here rather than pretending it isn't there, because that's the whole exercise: measure, then report what you actually saw.

Takeaways if you build or use browser tools

  • Don't trust the label -- trust the Network tab. The snippet above turns "they say it's private" into "I watched it."
  • If you build tools, enumerate your exceptions. One honest "here's what leaves and why" page is worth more than a blanket "nothing is uploaded" that a single request disproves.
  • Same-origin proxying is an underused privacy pattern. Relaying third-party data through your own edge keeps the user's IP and query off the third party entirely.

Full write-up with the per-tool table and the exceptions list is on the original post. And genuinely -- run the snippet on the next "free online tool" you paste something sensitive into. It takes ten seconds and it's occasionally alarming.

Top comments (0)