DEV Community

Cover image for I Built a PDF Tool Because I Didn’t Trust PDF Tools
Pranav Mailarpawar
Pranav Mailarpawar

Posted on

I Built a PDF Tool Because I Didn’t Trust PDF Tools

If you’ve ever used an online PDF tool, you’ve probably had this moment:

“Wait… did I just upload my bank statement to some random server?”

Same.

That uncomfortable feeling is exactly why I built ihatepdf — a PDF tool that runs entirely inside your browser.
No uploads. No accounts. No “we delete your files later”.

Just your device, doing the work.

The Problem With Most PDF Tools

Most PDF websites follow the same model:
1. Upload your PDF
2. Process it on a server
3. Download the result
4. Trust them to delete it

This breaks down fast when:
• the file is large (50–150MB)
• the document is sensitive
• your internet is slow or unstable

And from an engineering point of view, it’s expensive, slow, and risky.

So I asked a simple question:

What if PDFs never left the user’s device at all?

Why Client-Side PDF Processing Is Hard

Here’s the part most people don’t realize:

A 50MB PDF can easily need 200–300MB of memory while being processed.

Now try doing that:
• inside a browser
• on a phone
• without freezing the UI
• without crashing the tab

JavaScript isn’t meant for heavy binary workloads.
Do it wrong and the browser just… dies.

That’s why most “free” tools:
• limit file sizes
• lock features behind paywalls
• or quietly fail on large PDFs

The Approach I Took

I treated the browser like a real application runtime, not a thin client.

A few core principles shaped everything:
• Files never leave the device
• Keep data binary as long as possible
• Adapt to the user’s device automatically
• Fail early, not after a crash

That’s how ihatepdf works.

How It Actually Works (Without the Buzzwords)

  1. Everything Is Local

PDFs are read as ArrayBuffers and processed directly in memory.

No uploads.
No background APIs sending data anywhere.
You can open DevTools → Network tab and watch it yourself.

  1. Smart Memory Management (This Is the Real Secret)

Different devices get different limits.

A phone cannot be treated like a desktop.

So the app automatically adjusts:
• max file size
• DPI / image quality
• number of pages processed at once

If a task would use too much memory, the user is warned before anything breaks.

  1. Batching Prevents Crashes

Trying to convert 100 PDF pages at once is a guaranteed crash.

Instead:
• process pages in small batches
• clean up memory immediately
• pause briefly so the browser can free RAM
• continue safely

It’s not flashy, but it’s the difference between “works sometimes” and “works reliably”.

  1. Real PDF Tools, Not Gimmicks

Under the hood:
• pdf-lib for structural PDF edits
• pdf.js for rendering and text extraction
• Ghostscript (WebAssembly) for real compression

That means:
• 60–70% size reduction
• searchable PDFs stay searchable
• links, forms, and metadata survive

Not just “images in a PDF wrapper”.

Features People Actually Use
• Compress large PDFs (100MB+)
• Merge / split / reorder pages
• Convert PDFs to high-quality images
• Add text, signatures, annotations
• Chat with PDFs (text extracted locally)
• Remove passwords locally

And yes — it works offline after the first load.

Privacy Isn’t a Feature — It’s the Default

With ihatepdf:
• your files never hit a server
• nothing is logged
• nothing is stored remotely
• airplane mode still works

If something can’t leak, it won’t.

That’s the whole idea.

What This Taught Me

The modern web is way more powerful than we give it credit for.

With WebAssembly, proper memory discipline, and realistic UX constraints, you can build desktop-class tools directly in the browser — without compromising privacy.

Try It Yourself

If you’re curious, you can check it out here:
👉 https://ihatepdf.cv

Open DevTools.
Turn off your internet.
Throw a big PDF at it.

That’s the point.

Final Thought

Good software doesn’t just “work”.

It respects:
• the user’s privacy
• the user’s device
• the user’s time

That’s what I tried to build.

Top comments (0)