You drag a sensitive PDF — a contract, a passport scan, a payslip — onto some "100% free, secure, private" online converter. It spits out the result in two seconds. The page swears it "deletes your files after processing."
Here's the thing: you have no way to verify that claim. "We delete after processing" is a promise about a server you can't see, running code you can't read, with a retention policy you can't audit. It might be true. It might be true today and not next quarter.
But you don't have to trust the promise. If your file never left your browser, there's nothing to delete and nothing to subpoena. And whether or not it left is a fact you can check yourself in about 60 seconds.
Here's the skill.
The 60-second audit
- Open the tool's page in Chrome/Edge/Firefox.
- Open DevTools (
F12orCmd+Opt+I), go to the Network tab. - Click the 🚫 clear button to start clean. Leave "Preserve log" off for now.
- Run the conversion — pick your file, hit convert.
- Watch what rows appear.
That's it. You're now looking at every request the page made. The question is simple: did one of them carry your file out?
A faster way to find the row: type your filename into the Network tab's filter box, or click Fetch/XHR to hide assets, then sort by the Size column. At convert-time, a row roughly the size of your file (a ~2 MB row for a 2 MB file) is the one to inspect.
What an upload looks like
When a tool sends your file to a server, you'll see a request that is unmistakable once you know the shape of it. Click the row and look at the Headers and Payload tabs. You'll see something like:
Request URL: https://api.someconverter.com/v1/convert
Request Method: POST
Status Code: 200
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAb3x
Content-Length: 2487193
Two tells:
-
Method is
POSTorPUT, notGET. -
Content-Type: multipart/form-datawith aContent-Lengthroughly the size of your file (here, ~2.4 MB — that's your file in bytes).
Open the Payload tab (in Firefox, click the request and open the Request tab) and you'll see the form-data parts:
------WebKitFormBoundaryAb3x
Content-Disposition: form-data; name="file"; filename="contract.pdf"
Content-Type: application/pdf
%PDF-1.7
%âãÏÓ
... (binary bytes of your actual file) ...
That filename="contract.pdf" followed by %PDF bytes is the smoking gun. Your file is, right now, sitting in a request body headed to someone else's machine. No amount of "we delete it" changes the fact that it left.
(Sometimes it's application/octet-stream or a base64 blob in a JSON body instead of multipart — same story. A big POST/PUT body sized like your file = upload.)
What a genuinely client-side tool looks like
Now run the same audit on a tool that processes locally. The signature is almost funny in how boring it is:
- You pick your file. No new network row appears at the moment of conversion.
- The result downloads — but as a
blob:URL the page generated in memory, not a response from a server.
The only requests you'll ever see are the page's own assets (JS, CSS, fonts) on first load, and — for some tools — a one-time download of a model or WASM binary. That part trips people up, so let's be precise.
The one nuance: a fetch is not always your file
Some browser-native tools download a chunk of machinery the first time you use them. OCR pulls a WASM build of Tesseract plus a trained language model; in-browser background removal pulls an ML model file. In the Network tab that looks like:
Request URL: .../tesseract-core.wasm
Request Method: GET
Status: 200 Size: 4.2 MB
Request URL: .../eng.traineddata.gz
Request Method: GET
Status: 200 Size: 10.4 MB
This is not your file leaving. Three reasons you can tell them apart:
-
Method is
GET— it's pulling code down, not pushing a file up. - It's the same file/model regardless of what you convert, and it's cached — convert a second file and it's served from disk cache (you'll see "(disk cache)" in the Size column), or there's no request at all.
- The bytes flow to you. Your document is never in a request body.
So the honest rule: a GET for a .wasm or model file is fine. A POST/PUT carrying your filename and bytes is an upload. And yes — a WASM tool could still phone home (analytics, "anonymous" telemetry, error reporting with your filename in it). The audit catches that too: if there's any outbound POST with your data in it, you'll see it.
The honest part (disclosure)
I build bestaifinds.com — 240+ free, no-signup file tools — and this audit is exactly the principle I build on, so I'll hold myself to it.
Open the Network tab on the image and PDF-structure tools and you'll see no upload: image compress, remove background, image→text OCR, PNG→WebP, PDF merge, PDF split. Convert once, watch the panel, then convert again and watch it stay quiet. The model/WASM download is the only thing that crosses the wire.
And I'll be straight about the rest. A few tasks genuinely can't run in the browser yet:
-
Video (ffmpeg).
ffmpeg.wasmexists, but transcoding a real clip in WASM is slow and memory-hungry enough that a real ffmpeg binary is just better. - Ghostscript-grade PDF compression and PDF→text — real downsampling and quality text extraction want native binaries.
- HEIC decode — most browsers can't natively decode HEIC, so HEIC→JPG leans on libheif/ImageMagick.
So PDF compression, PDF→text, HEIC→JPG, and all the video tools do go to a server — and the file is deleted right after. That last claim you'll have to take on trust, which is the whole point of this post: when a heavy task claims to be 100% local, audit it, because sometimes "in your browser" quietly means "in our browser, on our server." Prefer the tools where you don't have to trust.
So next time something promises "private and secure," open the Network tab and let the wire tell you.
What conversion do you wish ran fully in your browser but always seems to need an upload? Drop it in the comments — genuinely useful for deciding what to build (or audit) next.













