Skip to content
reader.me

Technical notes

How reader.me works

Every PDF you open never leaves your machine. This page explains how that's possible architecturally, what each piece does, and how you can verify the claim yourself in 30 seconds.

The short version

Modern browsers ship a near-complete runtime: a JIT JavaScript engine, WebAssembly, the 2D canvas, cryptography, file APIs and persistent storage. That's enough to do every operation a desktop PDF editor does — without sending the file anywhere.

reader.me is roughly 4 MB of JavaScript and WebAssembly that glues four open-source libraries into the 20 tools you see. The PDF you drop into the browser is read from the local File handle into a Uint8Array, manipulated in memory, and the result is offered back to you as a download via URL.createObjectURL. At no point is there a network request involving your document.

What happens when you drop a PDF

  1. The browser hands the file directly to JavaScript. The Drag-and-Drop API gives us a File object pointing at the bytes already on disk — no upload occurs to get the data into our code.
  2. We read the bytes into a typed array. await file.arrayBuffer() gives us the raw bytes. Everything from here on operates on this Uint8Array.
  3. The right library does the work. Each tool wires this byte array into one of four engines: pdf-lib (pure JS structural manipulation), PDF.js (rendering), Tesseract.js (OCR via WebAssembly), and Comlink Workers for files over 20 MB.
  4. The result becomes a download. The output Uint8Array is wrapped in a Blob, a temporary object URL is created, and an invisible <a> tag with a download attribute is programmatically clicked. The browser saves the file to your downloads folder.

Why this is structurally private, not just policy-private

Most "no upload" claims from cloud PDF services mean something weaker: the server discards your file after a couple of hours. The file did reach their servers — they just promise to delete it.

In reader.me there is no "after" to discard, because there is no upload to begin with. The privacy promise is not a policy we enforce; it's a property of the system. You can't accidentally violate it without rewriting the application.

That's the difference between policy privacy ("we won't keep it") and structural privacy ("it never gets here").

What about analytics?

We load Google Analytics (deferred, post-LCP) for traffic counts and Cloudflare Web Analytics for performance. Neither sees your PDFs — they only fire pageview beacons with the URL path (e.g. /merge-pdf), the locale and the standard browser user agent. No file names, no file contents, no per-user identifier in our datalayer.

Robots are explicitly allowed (GPTBot, ClaudeBot, Google-Extended, PerplexityBot, etc.) — there is no document data to scrape, only the same public marketing copy you're reading now.

Verify it yourself in 30 seconds

  1. Open the browser DevTools (F12 on Windows, ⌥⌘I on macOS) and switch to the Network tab.
  2. Clear the request list. Tick "preserve log" so requests survive a potential page reload.
  3. Drop a PDF on, say, the Compress tool. Click "Compress PDF".
  4. Watch the Network panel. You'll see asset requests (pdf.worker.min.mjs, cached after first load) and the GA beacon, but no request carrying your file — no POST, no XHR, nothing. The download arrives as a blob: URL, which is a browser-local pseudo-URL.

Once you've seen it once, it's the same for every tool. The architecture doesn't have a server-side path for document data even when we wanted it to.

Trade-offs we accept

Doing everything in the browser isn't free. Honest list of limitations:

  • File-size ceiling. 50 MB per file on web. The browser is fine with bigger files but mobile memory is tight; a desktop Tauri build (Phase 4) will lift this.
  • No qualified e-signatures. SES (Simple Electronic Signature) is doable client-side; QES with FNMT/DNIe certificates requires OS smart-card APIs, also Phase 4.
  • OCR language data is large. The first OCR run in a new language downloads ~12 MB from the public Tesseract CDN. Cached forever after.
  • PDF/A loses selectable text. We rasterize each page to guarantee compliance regardless of what fonts the input uses.

Related

reader.me is an idea by David Carrero , built at Color Vivo Internet S.L.