keptlocal
· 8 min read · Technical

How Browser-Based File Tools Actually Work (WebAssembly Explained)

HP
Hitendra Patel
Founder, keptlocal · Senior Technical Lead, Healthcare IT

A few years ago, the idea of merging PDFs, compressing images, or converting HEIC photos in a browser — with no server, no download, no waiting — would have seemed implausible. Today it works on any modern phone or laptop. The technology that made this possible is WebAssembly, and understanding how it works explains why browser-based tools are now genuinely competitive with desktop software.

The old model: why browsers needed servers

Before 2017, JavaScript was the only language that ran in browsers. JavaScript is a dynamically typed, interpreted language — convenient for building interactive interfaces, but slow for computationally intensive tasks like decoding image formats, parsing binary file structures, or applying compression algorithms.

The consequence was a hard boundary: anything requiring real computation happened on a server. You uploaded your file, a server ran a C++ or Python program to process it, and the result came back over the network. This was not a design choice — it was a technical necessity.

It also created the business model that defines most "free" online tools today: the server is the product. Hosting, bandwidth, and compute cost money. Tools recoup those costs through advertising, freemium conversion, or (less visibly) data retention and use.

What WebAssembly is

WebAssembly (abbreviated Wasm) is a binary instruction format designed to run in browsers at near-native speed. Introduced in 2017 and now supported by all major browsers, it is not a programming language you write directly — it is a compilation target.

Code written in C, C++, Rust, Go, or other systems languages can be compiled to WebAssembly instead of (or in addition to) native machine code. The resulting .wasm file contains compact binary instructions that the browser's WebAssembly engine executes directly, bypassing the JavaScript interpreter.

The performance difference is significant. WebAssembly runs at roughly 80–90% of native speed for compute-intensive tasks. A C++ PDF library compiled to WebAssembly and running in Chrome performs comparably to the same library running as a native desktop application — not identically, but close enough that the user cannot tell the difference for typical file operations.

How keptlocal's tools use this

keptlocal's PDF tools use pdf-lib, a pure JavaScript implementation of the PDF specification. When you load the merge tool, pdf-lib is downloaded from a CDN once and then cached — this is a JavaScript library, not WebAssembly, but JavaScript performance is sufficient for the operations pdf-lib performs: reading page structures, copying content streams, and writing the output. When I first tested a merge of twelve 10-page documents, the whole thing completed in under two seconds on a mid-range laptop. No server involved.

The image tools use the browser's built-in Canvas API and the JPEG/PNG/WebP encoders that browsers ship natively — these are implemented in native code inside the browser engine and exposed to JavaScript through the canvas API. When you call canvas.toBlob('image/webp', 0.85), the browser's internal C++ WebP encoder runs on your CPU.

HEIC decoding uses heic2any, which implements the HEVC decoder in JavaScript — a computationally intensive operation, which is why HEIC conversion is slower than simpler format conversions.

None of these operations require a network connection once the library code is cached. The file bytes never leave the browser.

The File API: how files get into the browser

WebAssembly solves the computation problem. But how does a file from your disk get into the browser in the first place without uploading it?

The File API (part of the web platform since 2012) lets browser code read files that you explicitly select or drop. When you drag a PDF onto a drop zone or click a file input and select a file, the browser reads the file's bytes into memory. The JavaScript code can then access those bytes directly using the FileReader API or the newer File.arrayBuffer() method.

Critically, this is a local read — the equivalent of opening a file in a desktop application. No network request is made. The bytes move from your disk to your browser's RAM. The browser's security model prevents JavaScript from reading files outside the ones you explicitly selected — so the tool cannot access your entire file system, only the specific files you give it permission to read.

The download side: how processed files get back to your disk

Once the processing is done, the output bytes are in browser memory (a JavaScript Uint8Array or ArrayBuffer). Getting them to your disk also requires no server:

  1. A Blob is created from the output bytes with the appropriate MIME type (application/pdf, image/jpeg, etc.).
  2. A temporary object URL is created from the blob using URL.createObjectURL(blob). This URL looks like blob:https://keptlocal.com/... and exists only in memory.
  3. A hidden <a> element is created with the object URL as its href and the desired filename as its download attribute.
  4. The click is triggered programmatically, which causes the browser to save the blob to your downloads folder.
  5. The object URL is revoked to free the memory.

The file goes from browser RAM to your disk via the browser's download mechanism — the same path as any other file download, but without a server on the other end.

What the browser's security model guarantees

Several browser security properties make client-side file processing safe:

Origin isolation means JavaScript on one website cannot read data from another. A keptlocal tool cannot access your banking session or read cookies from other tabs. File system access is opt-in — the tool can only read files you explicitly select; the browser cannot silently read files in the background. Network access is auditable: a script cannot make arbitrary network requests without them appearing in DevTools. Nothing is hidden. And each browser tab runs in its own process (in Chromium and Firefox), so a tool in one tab cannot access data from another.

These properties do not make browser-based tools immune to all attacks — a malicious script could exfiltrate your file data by making a network request. This is why the Network tab audit matters: if a tool claims to be local but makes an outbound request when you process a file, it is not actually local regardless of what its homepage says.

What browser-based tools still cannot do

The browser environment imposes real constraints:

RAM is the ceiling. Browsers impose limits on how much memory a tab can use (typically 1–4 GB depending on device and browser), and processing files larger than available RAM will crash the tab. Browser-based tools also cannot watch a folder for new files, write directly to a file path, or integrate with the system clipboard for file objects — everything is download-on-demand, one file at a time. And for tasks that are trivial in native code — compressing a 50 MB TIFF, running OCR on 200 pages — the browser may be too slow for a good user experience. Server-side processing is the right call for those.

Where this leaves us

For the large majority of everyday file operations — PDF merging, splitting, rotating, watermarking, image compression, conversion, and cropping — browser-based tools in 2026 are as capable as the desktop applications most people have used for years. No installation. No account. Nothing transmitted.

WebAssembly, the File API, and native browser encoders together provide the technical foundation. The privacy guarantee is a structural consequence of the architecture, not a policy promise. You can verify it yourself in thirty seconds: open DevTools, run an operation, and watch the Network tab stay quiet.

All keptlocal tools run this way — processing in your browser, files never leaving your device.

Free browser tool
Try a tool

See WebAssembly in action — any keptlocal tool processes files without a server.

No upload. No signup. Runs in your browser.

Use Try a tool