Running PDF, OCR and AI tools entirely in the browser: what worked and what broke
Most "free online PDF tools" upload your file to a server, process it there, and delete it an hour or two later. I wanted the opposite for Utilkits: 99 everyday tools, where the PDF and image tools keep the file on your
Most "free online PDF tools" upload your file to a server, process it there, and delete it an hour or two later. I wanted the opposite for Utilkits: 99 everyday tools, where the PDF and image tools keep the file on your device. Here is how the browser does the heavy lifting, where it falls short, and the two bugs that taught me the most.
The stack
It's a Next.js 16 app, and the PDF, image and on-device AI tools run client-side:
| Job | Library |
|---|---|
| Merge, split, rotate, watermark, page numbers | pdf-lib |
| Render pages, extract text, PDF to JPG/PNG | pdf.js (pdfjs-dist) |
| Password-protect and unlock (AES-256) | qpdf compiled to WebAssembly (qpdf-wasm) |
| OCR | Tesseract.js, in a web worker |
| PDF to Word / Excel / PowerPoint | docx, SheetJS (xlsx), PptxGenJS, rebuilt from the extracted text |
| Image compression and conversion | browser-image-compression and canvas |
| On-device AI | Transformers.js with onnxruntime-web (WebAssembly) |
The rule I hold myself to: if a tool can't run locally, the page says so. The redirect checker has to follow redirects from a server, so the how it works page lists it as an exception.
On-device AI: four models
-
Background removal: U²-Net (
BritishWerewolf/U-2-Netp, about 4.6 MB), run in a web worker so the page never freezes. -
Speech to text: Whisper tiny (
onnx-community/whisper-tiny.en). -
Summaries: DistilBART (
Xenova/distilbart-cnn-6-6). -
Ask your PDF: retrieval plus extraction. MiniLM (
all-MiniLM-L6-v2, about 24 MB) finds the passages closest to the question. A DistilBERT trained on SQuAD (about 66 MB) then quotes the answer, with its page number. It quotes rather than generates, so it can't invent a citation. If it isn't confident, it says so and shows the closest passages.
The models download once from Hugging Face and the browser caches them. The files themselves never leave the device.
Bug 1: a bare import no browser can resolve
The AI tools worked locally and failed in production on first use. The self-hosted transformers.web.min.js imported onnxruntime-web/webgpu by bare name, and no browser can resolve a bare module name without an import map. On top of that, the library's default is to fetch the onnxruntime .wasm engine from jsDelivr, which my content security policy blocks.
The fix: load transformers.min.js instead, copy the onnxruntime files from node_modules into /transformers/ before every build, and point env.backends.onnx.wasm.wasmPaths at that folder.
That fix had its own trap. Set wasmPaths on the existing settings object; don't replace the object. The runtime keeps a reference to the original, so assigning a new object does nothing and the engine still comes from the CDN.
Bug 2: a processor class that isn't there
The background remover also "worked" in development and never in production. Transformers.js 4 has no U2NetImageProcessor, and my code read an output name the model doesn't have.
Now the worker prepares the input itself:
- Resize the photo to 320Ć320.
- Normalise it with the ImageNet mean and standard deviation from the model's
preprocessor_config.json. - Feed the model's real input,
input.1, and read its real saliency map, output1959.
The preparation is a set of pure functions, so the same code runs in the worker and in Node unit tests.
Proving the file stays local
"Your file stays on your device" is easy to say, so every tool page has a privacy badge:
- It reads the browser's Resource Timing entries and sorts each request into downloads (engines, models, fonts) and data sent.
-
Offline mode wraps
fetch,XMLHttpRequestandnavigator.sendBeaconto block the page's own requests, and sets Google Analytics' officialga-disableflag. - The honest limit: requests made inside web workers (pdf.js, Tesseract) use the worker's own
fetch, which the page can't intercept. The badge says so.
The badge also suggests the real test: load the page, turn off Wi-Fi, run the tool. If it still works, your file had nowhere to go.
Where the browser loses
- Memory. A 500-page scan can exhaust a phone's RAM. Server tools win on huge files.
- First run. AI tools download a model once (about 90 MB for PDF Q&A) before the first answer.
- Fidelity. PDF to Word rebuilds the text page by page; fonts, images, tables and layout aren't kept. The page says that rather than pretend otherwise.
Try it, or try to break it
Everything is at utilkits.com. The single-file tools are free, with no account. If you catch a tool sending your file anywhere, tell me in the comments.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes ā full credit and traffic to the original publisher.