As developers, we often reach for cloud-based APIs to solve complex problems. Need to extract text from a PDF? Send it to an OCR API. Need to analyze data? Send it to a backend service.
But when it comes to highly sensitive user documents—like financial records or medical reports—the cloud-first approach introduces massive privacy risks.
In this post, I'll share how we shifted from cloud-processing to 100% local, in-browser PDF processing using WebAssembly and React, and why this architecture is the future of privacy-first web apps.
The Problem: The Hidden Cost of "Free" Tools
If you search for "free PDF tools" online, you'll find thousands of results. But if you read their privacy policies (which nobody does), you'll often find clauses that allow them to store, analyze, or even train AI models on the documents you upload.
When a user uploads a salary slip or a blood test report, they are handing over:
Their full name and address
PAN and Aadhaar numbers
Employer details and bank account numbers
Intimate health markers
Uploading this data to unknown third-party servers is a massive liability.
The Solution: In-Browser Processing with WebAssembly (Wasm)
Modern browsers are incredibly powerful. With the advent of WebAssembly (Wasm), we can now run complex C/C++ or Rust libraries directly inside the browser at near-native speeds.
For PDF processing, libraries like PDF.js (JavaScript) and MuPDF (compiled to Wasm) allow us to extract text, render pages, and even modify PDFs without the file ever leaving the user's device.
How it Works in React
Here is a simplified flow of how you can read a PDF locally:
javascript
`import * as pdfjsLib from 'pdfjs-dist';
// Point to the local worker
pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs';
async function extractTextFromPDF(file) {
const arrayBuffer = await file.arrayBuffer();
const pdf = await pdfjsLib.getDocument(arrayBuffer).promise;
let fullText = '';
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const textContent = await page.getTextContent();
const pageText = textContent.items.map(item => item.str).join(' ');
fullText += pageText + '\n';
}
return fullText;
}`
Because this runs entirely on the client, you completely eliminate the need for a backend infrastructure to handle file uploads. There is no multipart/form-data upload, no temporary storage in an S3 bucket, and zero risk of a data breach on your servers.
Real-World Examples
We recently implemented this local-first architecture for two highly sensitive use cases:
Financial Data Parsing
We built a Salary Slip Analyzer that extracts salary components (Basic Pay, HRA, PF deductions, TDS) directly from Indian payslips. Users can calculate their exact HRA exemption or estimate their tax liability. Because the extraction happens locally, their financial data remains completely private.Medical Report Translation
Similarly, we launched a Medical Report Analyzer that reads complex blood test and X-ray reports and explains the medical jargon in plain English. Medical data is arguably the most sensitive data a user possesses. By processing it locally, we ensure HIPAA-level privacy by default.
The Benefits of Local Processing
Zero Server Costs for File Handling: You don't pay for bandwidth to upload large PDFs or storage to keep them.
Instant Feedback: The user doesn't have to wait for a 5MB file to upload over a slow 3G connection. The processing starts instantly.
Absolute Privacy: "We don't store your data" isn't just a promise; it's a technical guarantee. The data never reaches your server.
Conclusion
Before you reach for a cloud API to process user files, ask yourself: Can this be done in the browser?
With WebAssembly and modern JavaScript engines, the answer is increasingly "yes." By moving processing to the edge (the user's device), you build faster, cheaper, and vastly more secure applications.
Have you experimented with local-first processing? Let me know in the comments!
Top comments (1)
How do you handle cases where local processing is too resource-intensive, especially with large PDFs? I'd love to swap ideas on this, been following your work on secure file handling.