How UnboundPDF handles large PDFs locally

Updated 18 August 2026

Large documents are opened in stages, rendered as you reach them, batched during export and released as they go, with the plan chosen against your device before the run starts. Every figure below was measured on 2026-08-15 across Chromium, Firefox and WebKit, and every output was reopened in an independent PDF reader.

What runs where, why big documents are hard, and the 2026-08-15 benchmark tables across three browser engines — including the parts we could not measure.

UnboundPDF is a free suite of 43 PDF and image tools that run entirely in your browser — merge, split, compress, edit text, OCR in 126 languages, redact, sign, convert and archive to PDF/A. Your document is read and written by the page on your own device; there is no document-upload endpoint in the core tools, no account, no watermark and no daily cap. Every result can be checked — with the Network tab, or with the Document Passport the Workspace writes for a chain of steps.

  1. Open PDF Editor and load the largest PDF you have — a few hundred scanned pages is a good test.
  2. Watch the first page: it should paint before the rest of the document has been built.
  3. Scroll to the middle. Pages render as you reach them rather than all at once.
  4. Read the panel before you run anything — it names the mode it picked for your device, and says so when it has never measured a device like yours.
  5. Press Stop mid-run. The run ends, and the file you opened is untouched.

Last benchmark: 15 August 2026. 124 runs, three browser engines, twelve fixtures, one desktop machine. 79 of 79 byte-producing runs were reopened and checked in poppler — an independent PDF stack. The machine-readable per-tool record is capabilities.json; the dated write-up of what changed is the changelog.

What runs where

Every tool opens your document with pdf.js and writes it back with pdf-lib, inside the page. Two vendor libraries bring their own threads: pdf.js parses PDF structure in its own worker, and Tesseract recognises text in its own. Both are vendor code, and we record them as vendor code. Everything else — rasterising pages onto canvas, re-encoding JPEGs, assembling ZIP archives, and every pdf-lib call — runs on the page's own main thread.

We have no first-party worker. The capability registry records workerEnabled: false on all 33 PDF tools in the 15 August 2026 matrix, and the registry build refuses to run if any row claims otherwise. One first-party worker was written — a JPEG re-quantisation worker — and it ships switched off because its own benchmark failed: no improvement in the longest stall, and 818–1008 MB more peak process memory. We would rather publish that than describe a design we did not ship.

What makes main-thread execution liveable is measured rather than assumed. During the heaviest operations in the corpus, a self-rescheduling timer measured the longest stretch in which a queued task — your own click on Stop — could not run:

EngineCompress Balanced, 300-page scanPage images, 1,000 pagesOCR, 100-page scan
Chromium35 ms39 ms34 ms
Firefox35 ms14 ms30 ms
WebKit (Safari's engine)57 ms30 ms35 ms

The worst figure anywhere was 57 ms, and the run most likely to look frozen — an 18.5-minute OCR grind in Firefox, sampled 51,226 times (this is the responsiveness probe's own run of that cell; the throughput matrix's run of it took 19.7 minutes — the same work, measured twice, and both figures appear on this page) — was the one where a queued click would have run within 30 ms. That is the mechanism: these loops hand the thread back between batches and after each item, rather than holding it. Two bounds on that result: it is desktop only, on three operation classes only, and it measures queued-task lag, not frame timing — the paint meter that would have measured smoothness distorted the thing it measured by 26× and was discarded, so this page makes no claim about visual smoothness. On phones the opposite was observed by hand: scrolling a 1,000-page document was described as "like hanging" on an iPhone.

Why large PDFs are hard

The intuitive model — memory grows with file size — is wrong, and we published the measurement that falsified our own version of it. An early estimator encoded page-image export at roughly 55× the input size, derived from a single 39.76 MB measurement. Driven across a ten-fold input range in Chromium on 2026-08-13, that ratio collapses:

InputPeak process memoryImplied ratio
39.76 MB / 100 pages2219 MB55.8×
118.99 MB / 300 pages2400 MB20.2×
237.98 MB / 600 pages2515 MB10.6×
396.72 MB / 1,000 pages2362 MB6.0×

Peak memory is nearly flat while the input grows ten-fold. The cost is a working set — how much of the document an operation insists on holding at once — not a multiple of the document. The "55×" was a fixed cost divided by the smallest input anyone had measured. Shipped as written, that estimator would have refused a document that finishes in under two minutes.

The same run gives the reason to distrust any single memory number: the identical 100-page fixture measured 1807, 1954, 2219 and 2721 MB across four runs in Chromium — a ±25% band on unchanged input. Every memory figure on this page is one sample of a quantity that does not reproduce, and none of them is a boundary.

Staged and lazy rendering

The single largest improvement in this programme was in the editor, and it was a structural bug rather than a memory problem. The editor built a canvas for every page before painting any of them, so on a 1,000-page document the first pixel arrived only after the last page was built:

DocumentFirst page painted, beforeFirst page painted, after
100-page scan9,036 ms
300-page scan22,074 ms
1,000 pages73,394 ms≤ 1,027 ms

The "after" figure was sampled at one-second resolution, so it is an upper bound rather than a reading of 1,027 ms. The 2026-08-15 matrix re-measured the same behaviour at 500 ms polling across all three engines and found first paint no longer scales with page count at all: ≤ 517 ms in Chromium, ≤ 588 ms in Firefox, ≤ 516 ms in WebKit on a 1,000-page document — the same half-second as on a one-page document.

Page thumbnails are lazy and capped. Organize Pages, Split PDF and Rotate PDF render at most 200 thumbnails however long the document is, and render them in a band around the viewport: in standard mode a page starts rendering 300 px before it scrolls into view and is released 900 px after it leaves. Memory for those tools is bounded by the feature, not by the page count — 3,000 pages cost 721 MB where 1,000 pages cost 688 MB in the same Chromium run.

The editor keeps a small cache of rendered pages around the one you are looking at — three in standard mode, one in low-memory mode — and zeroes the backing store of the canvases it evicts.

Batch processing

Page-image export is the most memory-hungry operation we have, and it was rebuilt as a render → encode → release pipeline: a batch of pages is rasterised, encoded to JPEG bytes and released before the next batch starts, rather than every page canvas living until the end. Batch size is eight pages in standard mode and four in low-memory mode.

Measured against the same 100-page scan, PDF to JPG fell from 2219 MB before that change to a 534–582 MB band after it. On the 300-page scan, the same operation read 2400 MB in the 2026-08-13 matrix and 779 MB in Chromium on 2026-08-15.

One cliff is not fixed, and it is a page-count cliff rather than a size one: the exporter still holds every encoded JPEG while the ZIP is assembled as a single contiguous array. On a 1,000-page document that read 1500 MB in Chromium — for a 2.3 MB input — while producing a 320 MB archive that poppler confirmed holds all 1,000 images.

What gets released, and when

Every heavy resource a run allocates is registered with a cleanup ledger and disposed in reverse order when the run ends — whether it ended by finishing, by failing, or because you pressed Stop. Canvases have their backing store zeroed, ImageBitmaps are closed, object URLs are revoked, vendor workers are terminated, large arrays are dropped. Each disposal is independent, so a failure to clean one resource can never overwrite the run's real outcome.

What is verified: a repeated-save stress suite asserts that process memory stays flat across five consecutive saves, and the ledger's release-on-every-exit contract is unit-tested. What is not verified by the benchmark matrix: leak behaviour across a long session, because every matrix run started from a cold browser and each engine's process tree was drained before it.

Where intermediate bytes go

When you drop a file on the homepage and pick a tool, the document is carried across in IndexedDB rather than through a string copy — bytes, a name and a type, stored under one key. It is taken exactly once, deleted in the same transaction, and ignored entirely if it is more than five minutes old, so a document from an earlier session cannot resurface in a later tab. Those bytes never touch the network.

We did not ship OPFS. The Origin Private File System was in the design as an option for spilling intermediates to disk; it was not built, and nothing in the product uses it. Intermediates live in page memory for the life of the run.

The pre-flight check

Before a heavy run starts, the tool looks at the document — pages, bytes, the operation class — and at what the browser will tell it about the device, and picks one of five execution modes: standard, low-memory, selected pages (on the tools that accept a page range), desktop recommended, and one that stops before it starts — where the operation cannot produce a valid file at that size, the tool refuses rather than running, in its own words: “we are stopping before it starts. Your file has not been changed.” In every case it names the mode it picked and why, before anything begins rather than after.

The part worth reading is what it does when it does not know. Memory bands exist for exactly one device class — the desktop the benchmark ran on. A device outside that class gets the verdict unknown, in those words: "no memory band has ever been measured on this device class." A browser reporting a small memory budget gets low-memory mode and an unknown verdict, because a small budget is a signal we have no measurement for. No memory quantity is ever shown to you, on any device, because on every device except one we do not have one to show.

Low-memory mode — and the claim we will not make

Low-memory mode is wired on seven of the 33 tools in the 15 August 2026 matrix, and it does something different on each family. On PDF Editor, Fill & Sign and Sign PDF it shrinks the rendered-page cache from three pages to one and clamps the canvas area budget from 16 to 4 megapixels. On Split, Organize and Rotate it narrows the thumbnail band so pages render only once they are on screen and are released 300 px later. On PDF to JPG it narrows that same thumbnail band and halves the export batch as well — the page cache and the canvas clamp are read only by the editor, so PDF to JPG does not get those.

We cannot tell you it reduces the risk of failure. "Reduces risk" is a comparison against a failure rate, and the failure rate we have measured is zero — nought failures in 124 runs on 2026-08-15, nought in the 20 runs before that. There is no risk in our data for the mode to reduce. The mode is real, it is named, and what it changes is listed above; its effect on failure is unmeasured, and will stay unclaimed until something actually fails.

Stopping a run

Every long operation carries a Stop control, and the label tells you what stopping means for that operation rather than offering one vague promise: "it stops within the current item" (26 tools), "it stops after the current page finishes" (7 tools), "this cannot be stopped during the final rebuild" (4 tools, plus 1 that is item-cancellable up to its rebuild), or "stopping discards the work — there is no resume; you would start again" (4 tools, the image tools, whose single pass has nothing to abandon part-way). One tool is recorded as not wired, and says so in the registry rather than pretending.

Nothing resumes. All 33 tools in that matrix are recorded as restart-required, and the registry's resumable value is defined so that it can never be assigned — pdf-lib and pdf.js need a full restart, and a resume claim would be a lie the code could not honour. Cancellation is driven through four real tools in a real browser on every gate run, which asserts that the run ends, that the tool can be run again afterwards, and that your input file is untouched.

Verifying the output

Of the 124 runs on 2026-08-15, 79 produced an output document, and 79 of 79 were reopened and checked in poppler — a PDF stack entirely independent of the one this site ships. The other 45 produce no document: 36 are open-path runs and 9 are refusals. Each check is specific rather than a green tick: correct page count wherever the input's own count was readable (including 301-page and 501-page merges), a real page-1 raster in every PDF, ZIP entry counts equal to page counts, including a 1,000-entry archive, 91,127 searchable characters extracted from an OCR output, and 2,988 characters surviving a re-save of a Chinese document.

The product does not verify itself. Poppler checked those outputs externally, afterwards, in our test harness. The four guided outcome chains do verify on the output bytes before they show you a receipt — that is what makes them chains rather than articles — but the 33 individual tool pages do not. If you want the check on your own file, reopen the result in a different reader.

Working offline

A service worker caches the site shell and, on first use, the heavy engines. Only one tool has a verified offline run: on every gate run the HTTP server is killed outright, the browser context is put offline, Merge PDF is reloaded from cache, two real PDFs are merged and the output is reopened. The other 42 tools are recorded as shell-cached but unverified offline, and that is exactly how the registry words it.

The same suite enumerates every cache entry on the origin and byte-scans each one for a needle taken from the middle of each input document. No byte of either document appears in any cache. Caching the program is not caching your file, and that distinction is tested rather than asserted — the method for checking it yourself is in the PDF Privacy Lab.

The benchmark tables

All of the following was measured on 15 August 2026 on one machine — Apple M4, 16 GB unified memory, macOS 26.3.1 — driving the real interface through Playwright 1.61.1 on Chromium, Firefox Nightly and WebKit. Wall times come from a headless browser with unthrottled animation timing: they are the friendliest this product will produce, and they are not phone numbers.

One document, six operations, three engines

A 300-page scanned document, 118.99 MB. Every memory figure in this table and the next is a single sample of a quantity that does not reproduce — a lower bound on one run, never a boundary; the paragraph under the third table gives the repeat measurements that establish that.

OperationChromiumFirefoxWebKitOutput, checked in poppler
Compress, Balanced15.5 s · 949 MB13.6 s · 1561 MB13.4 s · 1260 MBvalid 300-page PDF, page 1 rasters
Compress, Maximum22.6 s · 795 MB25.4 s · 1505 MB18.4 s · 962 MBvalid 300-page PDF
Merge (+1 page)2.4 s · 1076 MB2.7 s · 2082 MB2.5 s · 1288 MBvalid 301-page PDF
Page images → ZIP23.0 s · 779 MB23.8 s · 1793 MB19.8 s · 1517 MBvalid ZIP, 300 JPEG entries
Editor open (first page painted)528 ms592 ms523 msopen path — no output document
Organize open (first thumbnail)515 ms597 ms516 msopen path — no output document

Five of the same six on a 1,000-page document (2.31 MB, born-digital text)

Compress Maximum is absent deliberately: on a text-only 1,000-page fixture it is the page-image path, so the matrix pruned it as a re-measurement of the row below it at roughly three times the cost. Sixty-eight cells were pruned that way, each against a written rule.

OperationChromiumFirefoxWebKit
Compress, Balanced1.8 s · 567 MB1.8 s · 1258 MB1.8 s · 734 MB
Merge (→ 1,001 pages)1.4 s · 644 MB1.7 s · 1300 MB1.3 s · 770 MB
Page images → ZIP21.6 s · 1500 MB16.1 s · 2163 MB28.8 s · 1737 MB
Editor open (first page painted)517 ms588 ms516 ms
Organize open (first thumbnail)516 ms522 ms568 ms

Compression depends on the browser, not only on the document

Identical input, identical Balanced setting, identical slider position, on 2026-08-15. Output-to-input byte ratio:

DocumentChromiumFirefoxWebKit
100-page scan, 39.76 MB0.3420.3870.565
300-page scan, 118.99 MB0.3420.3870.565
500-page mixed, 99.6 MB0.3460.3900.567
1,000-page text, 2.31 MB0.9860.9860.986
2-page government form, 0.21 MB1.0111.0111.011

Read as the numbers a person would quote: on that same 118.99 MB scan on 2026-08-15, Chromium delivered a 66% reduction, Firefox 61%, and Safari's engine 43%. The mechanism is in the code the measurement pointed at. Balanced re-quantises embedded JPEGs arithmetically — pure JavaScript, and correspondingly identical on all three engines, which is exactly what the text and form rows show. But a photograph above 150 DPI for its page box takes a different route: it is decoded, downsampled through a canvas and re-encoded by the browser's own JPEG encoder, and Skia, Gecko and ImageIO do not produce the same bytes at the same nominal quality. Every scan in this corpus is 200 DPI, so every scanned page lands on that branch. This is why Compress PDF carries no single "compress by X%" figure anywhere on this site.

The same split shows in Maximum (0.195 in Chromium, 0.214 in Firefox, 0.299 in WebKit on the 100-page scan) and in page-image output size. And Maximum has a failure mode in the other direction: on a document with nothing to rasterise it makes the file larger — 1.695 in Chromium, 1.775 in Firefox, 2.62 in WebKit on the 2-page form, and 25.1× on a 2.4 KB letter in Chromium. The tool detects that and tells you to keep your original rather than announcing a win.

OCR is roughly twelve times slower in Firefox

EngineOCR, 100-page scanPer pageOutput
Chromium94.2 s0.94 svalid 100-page PDF, 91,127 characters
WebKit88.9 s0.89 svalid 100-page PDF, 91,464 characters
Firefox1179.3 s (19.7 min)11.8 svalid 100-page PDF, 91,127 characters

We recorded that cell as a hang first, and were wrong. A three-page control settled it — 36.4 s in Firefox against 4.1 s in Chromium for the same file — and a progress sample through the run showed a per-page counter, a bar backed by that counter and a live Stop button at every sample. OCR in Firefox is slow, not stuck, and it produced byte-for-byte the same recognised text.

Observed completions per operation class

The largest document each operation class was measured finishing, with the peak process memory recorded on that run, and that same peak with the engine's own idle floor subtracted (Chromium 407 MB, Firefox 1075 MB, WebKit 444 MB — Firefox carries roughly 660 MB more baseline before this product has done anything):

Operation classEngineLargest completedPeakMinus browser floor
EditorChromium100 pages / 39.76 MB1466 MB1059 MB
EditorFirefox300 pages / 118.99 MB1905 MB830 MB
EditorWebKit500 pages / 99.6 MB1090 MB646 MB
MergeChromium100 pages / 39.76 MB896 MB489 MB
MergeFirefox300 pages / 118.99 MB1620 MB545 MB
MergeWebKit500 pages / 99.6 MB1237 MB793 MB
OCRChromium100 pages / 39.76 MB849 MB442 MB
OCRFirefox100 pages / 39.76 MB1401 MB326 MB
OCRWebKit100 pages / 39.76 MB1176 MB732 MB
Page imagesChromium1,000 pages1500 MB1093 MB
Page imagesFirefox500 pages / 99.6 MB1609 MB534 MB
Page imagesWebKit1,000 pages1463 MB1019 MB
CompressChromium300 pages / 118.99 MB949 MB542 MB
CompressFirefox500 pages / 99.6 MB1598 MB523 MB
CompressWebKit500 pages / 99.6 MB1336 MB892 MB
Organize / splitChromium300 pages / 118.99 MB811 MB404 MB
Organize / splitFirefox300 pages / 118.99 MB1510 MB435 MB
Organize / splitWebKit300 pages / 118.99 MB1034 MB590 MB

Read every memory figure above as a single sample and a lower bound. Peak process memory does not reproduce. A pdf-to-jpg cell repeated five times under identical conditions in Chromium read 684, 689, 627, 694 and 709 MB in that order — a spread of 13.1% — while wall time held steady. An independent four-run repeat of a different cell, a compress run in WebKit, spread 924–1681 MB (+82%) with byte-identical output across all four. These are the largest documents each operation was seen to finish, not the point at which anything stops. Nothing stopped.

Difficult documents: the intake door

A clean, named refusal is a pass here. Across 27 runs on damaged, encrypted, rotated, Chinese-script and structurally deep documents: zero silent hangs, zero crashes, zero "something went wrong".

DocumentBehaviour, on every engine that ran it
Password-protectedRefused in ≤ 0.6 s, 9 runs of 9. Two different messages, not one: the editor's 3 runs name the tool that fixes it — Unlock PDF — while compress and organize (6 runs) name the reason and the action but not the tool. All 9 are actionable; only 3 of 9 point at the tool.
Truncated cross-reference table (poppler cannot open it at all)Opened and processed on all three engines, 9 runs of 9. The repair route recovered 22 pages; compress produced a valid 22-page PDF, merge a valid 23-page one. You are never asked to know the file was damaged — Repair PDF exists for when you do.
Mixed page rotations3 thumbnails, 3 JPEG entries, valid 3-page re-save.
Chinese text, CID-keyed embedded fontsCompressed output still yields 2,988 non-space characters through poppler — the text layer survives the re-save.
756 pages, deep bookmark tree, owner-restricted encryptionOpens rather than refusing — an owner-password-only file with an empty user password is correctly treated as readable. First paint ≤ 516 ms, 200 thumbnails, all 756 pages intact after compression.

Real devices — two phones, run by hand

These are the only non-desktop rows that exist. They were driven by hand by the site's author on 2026-08-13 against the live site, on bundles older than the one the desktop matrix measured, with a stopwatch and a human eye. The bounds are coarse because the method was coarse, and they are reproduced with those bounds intact.

DeviceTestResult
iPhone 14, SafariEditor open, 100-page 40 MB scanPage 1 visible within 10–20 s; no crash, no reload
iPhone 14, SafariCompress Balanced, 100-page scanCompleted fast, sizes shown; no memory-kill banner
iPhone 14, SafariCompress Balanced, 300-page 119 MB scanCompleted in 30–40 s — no white flash, no reload
iPhone 14, SafariPage images + ZIP, 100-page scanCompleted in 10–20 s, ZIP download landed
iPhone 14, SafariEditor open, 1,000 pagesPage 1 visible, but scrolling "like hanging" — jank, not failure
Xiaomi (model not recorded), ChromeEditor open, 100-page scanPage 1 in 30–40 s; scrolling "okay, not slow or fast"; no crash
Xiaomi, ChromeCompress Balanced, 100-page scanCompleted; 40–60 s
Xiaomi, ChromeCompress Balanced, 300-page 119 MB scanCompleted, 60–100 s — no crash, no reload
Xiaomi, ChromePage images + ZIP, 100-page scanImages under 60 s, conversion under 60 s, completed
Xiaomi, ChromeEditor open, 1,000 pagesLoaded 10–20 s; scroll slow on that bundle

What these rows license: both handsets completed a compression of a 119 MB, 300-page scan, and neither hit a memory wall at that size. What they do not license: any figure for a phone not in that table, any timing tighter than those bounds, or any memory number for any phone — no memory measurement exists for any phone at all. The dominant problems found on phones were interface and speed, not crashes. Phone-specific walkthroughs live in the iPhone guide and the Android guide.

What we still cannot tell you

The benchmark was written as a gate on this page, with a pass/fail verdict against fourteen requirements. Nine passed — one of those nine, prompt cancellation, is a pass cited from a separate suite rather than re-measured in this matrix. Here are all five that did not, in the benchmark's own words.

RequirementVerdictWhy
Heavy work moved to its own thread wherever possibleFAILNo first-party worker is enabled on any of the 33 PDF tools in the 15 August 2026 matrix. The one that was built ships off, and its benchmark is why.
Unsafe tasks detected before a crashUNPROVENNothing has ever crashed — 124 runs here, 20 before. A pre-crash detector cannot be validated against a crash that has never been produced, and desktop browser flags cannot manufacture one. The logic exists and is unit-tested; its thresholds are uncalibrated.
Low-memory mode materially reduces failure riskUNMEASURABLEThe mode exists and is described above. The claim about its effect cannot be tested against a measured failure rate of zero.
The interface stays usable during processingPARTIALMeasured on desktop only, on three operation classes only. No mobile measurement exists, and the instrument that would have measured visual smoothness had to be discarded.
Output is verified before success is shownPARTIALThe four guided chains verify on the output bytes. The 33 individual tool pages do not — poppler checked those externally, afterwards.

And what was never measured at all, stated as an absence rather than left as an implication:

  • Mid-range laptops — the class most likely to actually struggle. Not run. No such machine was available. Nothing on this page describes an 8 GB Intel laptop.
  • Mid-range Android. Not run. The Xiaomi handset's model and Android version were never recorded, so it cannot even be classified.
  • Instrumented phone runs. Not possible with this harness. The phone rows are human observation: no memory sampling, no per-phase timing, no output verification.
  • iOS Safari's desktop-class mode. Never tested. WebKit on macOS is not a proxy for it.
  • Edge, and any browser on Windows or Linux. Not run. Headless Chromium is not Chrome on Windows.
  • Several tabs or several operations at once — which is how people actually run out of memory. Not run.
  • A genuine allocation failure. Never observed, in 144 instrumented runs. The branch that handles one is proven only against injected errors.
  • Peak memory as a distribution. Not characterised. No cell has enough samples to state one.
  • The current bundle on any phone. Not run — the phone rows are older builds.

Twenty-seven of the 33 tools in that matrix have no large-document benchmark of their own and are recorded as unknown rather than inheriting a neighbour's numbers. Which six are measured, and what each one's record says, is in capabilities.json.

Method, and how to check it

Twelve fixtures across three classes — ordinary documents, large documents, and deliberately difficult ones — driven through the real interface exactly as a person drives it: file input, action button, then wait for the tool's own result panel or the tool's own error panel. An error panel is a result, not a harness failure, which is why a named refusal is recorded as a named refusal and only a genuinely silent wait becomes a timeout.

Memory is peak resident set size of the whole browser process tree, sampled every 500 ms, matched to that engine's own process tree — a run that samples zero is recorded as instrumentation failure, never as 0 MB. We learned that the hard way: the browser's own JavaScript-heap metric read 4.7 MB while a tab held a 119 MB PDF, because PDF bytes, decoded images and canvas backing stores live outside it. Output validity is checked with poppler, chosen precisely because it shares no code with what this site ships.

Every table above regenerates from a machine-readable record of all 124 runs, and the run plan can be printed without running anything. The full write-up, including all 68 deliberately pruned matrix cells with the rule that pruned each one, is the source this page is drawn from; the per-tool summary is published as capabilities.json and the dated account of what changed is in the changelog. If you would rather check the privacy claim than the performance claim, the Privacy Lab is a method you can run yourself in a browser you control, and About explains what we do and do not promise.

Related

PDF Privacy Lab · Why in-browser is faster · Compare with upload tools · Changelog · All 43 tools · All guides

Frequently asked questions

Does UnboundPDF use worker threads of its own?

No. Two vendor libraries bring their own — pdf.js parses in its worker, Tesseract recognises in its — but no first-party worker is enabled on any of the 33 PDF tools in the 15 August 2026 matrix, and the build refuses to emit the capability registry if a row claims one. The one we did build ships switched off, because its own benchmark showed no improvement and 818–1008 MB more peak memory.

How big a document have you actually seen finish?

On 2026-08-15, on one Apple M4 desktop: a 300-page 119 MB scan compressed, merged, exported to JPEGs and opened in the editor on all three engines; a 500-page 99.6 MB mixed document likewise; a 1,000-page document opened, merged and exported. Those are documents we watched operations finish, not a point where anything stopped — nothing stopped.

Why does compression give a different result in a different browser?

Photographs above 150 DPI for their page box are re-encoded with the browser's own JPEG encoder, and Skia, Gecko and ImageIO produce different bytes at the same nominal quality. On the same 119 MB scan on 2026-08-15, Balanced returned a ratio of 0.342 in Chromium, 0.387 in Firefox and 0.565 in WebKit. Documents with no oversized photographs come out identical on all three.

What happens if my device runs out of memory?

In 124 measured runs on three browser engines on 15 August 2026, plus 20 in an earlier matrix, no run produced an allocation failure; before a large job starts, the tool checks the document against your device and tells you what it found. The branch that handles one has so far been tested only against injected errors. What is measured is that no run modified its input file.

Can I stop a long run?

Yes, and the tool tells you what stopping means for that operation: within the current item, after the current page finishes, or not during the final rebuild. Nothing resumes — every tool is recorded as restart-required, and no tool anywhere claims resumability.