MEASURED
The numbers behind Filum.
Every number on this page has a source. No unverified quality claims. No marketing language. Where data is inferred from observable behavior, it says so explicitly.
| Metric | Filum | Context |
|---|---|---|
| Third-party origins per page | 1 | One origin — error and performance telemetry. Nothing in the file path contacts anyone. |
| On-device processing | Yes — every tool | Split, merge, rotate, sign, organize, watermark, crop, redact, page numbers, compress, convert — every tool runs entirely in your browser. Your file never leaves your device. |
| PDF to image output quality | 300 DPI | Pixel-correct output at 300 DPI on standard A4 PDF. |
| Account required | Never | Every tool is available immediately, without registration or sign-up. |
| Number of tools | 46 | Tools span PDF editing, format conversion, and image processing. |
| Files stored permanently | 0 | Your file never reaches a server — every tool processes it locally, in your browser. There is nothing on any server to store, because nothing is ever uploaded. |
Methodology
- Third-party origins per page: Measured 2026-08-10 from the browser's own network log, on cold loads of the homepage and this page: 22 requests on the homepage, 21 of them to filum.se. The one third-party origin is Sentry, which receives an error-and-performance telemetry POST — never any part of your file. This row counts origins rather than requests because the request count is not stable: telemetry can retry or abort on navigation, so a session may show more than one POST to that same single origin. The Geist font is self-hosted at /fonts/ and is first-party; an earlier version of this row called it third-party and counted 2, which was wrong on both counts. Analytics loads only if you accept it, and adds one more origin if you do.
- On-device processing: VERIFIED: tools make zero outgoing requests during operation, confirmed via network panel. There is no server in the file path to upload to or delete from.
- PDF to image output quality: Measured 2026-06-13: pixel width ÷ page width in inches = 300.1 DPI on a standard A4 document. Lossless PNG and JPG outputs both verified.
- Account required: Structural, not sampled: all 46 registry entries run on the in-browser engine, so there is no server call in a conversion to authenticate against. The count above is read from the live registry at build time, and a unit test in the commit and CI gates fails if any entry stops being in-browser.
- Number of tools: Exact count from the live registry — updated automatically when a new tool ships. Each tool is verified on a real document before it appears here.
- Files stored permanently: VERIFIED via network panel: zero file bytes leave the browser during any operation. No server receives, holds, or has visibility into your file.
Claims marked INFERRED are derived from observable behavior, not from source code review. Claims marked VERIFIED were tested directly against production. All numbers represent a point-in-time measurement — the date is stated in each source note.
HEAD TO HEAD
Measured against iLovePDF and Smallpdf.
74 measurements across 30 tools, each on the same input file, each at whatever setting the tool offers by default — because the default is what a person actually gets. 27 of them go against us, and they are listed first. A comparison page that only contains wins is an advertisement, and the sentence under every row is the cause we read out of the files rather than the story that flattered us.
| What was measured | Filum | iLovePDF | Smallpdf | Verdict |
|---|---|---|---|---|
| A PDF renamed .jpg — what the tool does with itjpg-to-pdf · measured 2026-09-12 | refuses it, 1-page output | detects it and merges its 3 pages, silently | not measured | We lose |
| Filed apart from this tool's failure-path row (now a tie, in ties.ts) because on THIS input the incumbent never reaches a failure path — they succeed. Given a real 3-page PDF wearing a .jpg name alongside a valid JPEG, iLovePDF returned a FOUR-page PDF: the renamed file's three pages plus one from the image. Verified on the downloaded bytes with pdf-lib rather than read off their UI — 50,482 bytes, /Count 4, all 595x842, one embedded DCTDecode image — and the input fixture was confirmed a 3-page PDF the same way. filum refuses the file and produces one page. They do more with the user's file. The counterpoint is real and is not buried: they say nothing about having done it, so a user who renamed a PDF by mistake receives pages they never asked for under the sentence "The images have been converted to PDF". Doing MORE than asked without saying so is its own honesty problem, which is why the fix here is not to copy them: detect the real format, SAY so, and offer it. | ||||
| How long you wait after clicking Compresscompress-pdf · measured 2026-09-08 | 1,269 ms | 759 ms | not measured | We lose |
| 67% longer. Both timed from the click on the primary action to the output existing, timestamped inside the page so no driver latency is in either number — ours to URL.createObjectURL, theirs across the navigation to their download page. The measurement is GENEROUS TO THEM and that is stated rather than buried: iLovePDF starts uploading the file the moment you pick it, so the 746 KB transfer runs while you are choosing a compression level and sits outside their 759 ms. On a slow connection or a large file it would appear in their number and never in ours, because ours never leaves the device. What the user waits for after deciding is nonetheless the axis, and on it we are slower. The work is not the same work — theirs is a round trip to a server farm, ours is recompressing every embedded image on your phone — but a user waiting does not owe us that distinction. | ||||
| Gestures from landing on the page to holding the filecompress-pdf · measured 2026-09-08 | 3 | 2 | not measured | We lose |
| One gesture more than theirs, and the extra one is ours by choice. Both take a click to open the file dialog and a click to start. Theirs then downloads the result WITHOUT a third click — verified by the browser reporting the download with no further interaction; the Download button on their result page is a fallback, not a step. Ours requires clicking Download. That is a defensible design (the result panel shows the before-and-after size first, and a browser that downloads without being asked is a browser people distrust) but it is still one more thing to do, and this row exists because nothing in this repo was measuring how much there is to do. | ||||
| Recovering from a scanned PDFpdf-to-excel · measured 2026-09-12 | sends you to another tool | offers OCR in place | not measured | We lose |
| Both sides DETECT the scan and both explain it — the failure-path axis is a tie and is recorded as one. This row is the separate thing measured alongside it: what the user can do next. iLovePDF offers two buttons, 'Continue without OCR' and 'Apply OCR', and the second continues the same flow with the same file. filum says 'Run it through OCR first, then convert', which means leaving the page, re-picking the file on ocr-pdf, waiting for tesseract, downloading, returning, and re-picking again. Five steps against one. Their in-place path is gated behind Premium and ours is free, which is a real counterweight and is why this is filed as a product gap rather than a quality defect — but on what the user can DO, they win it. The fix is ours to make cheaply: ocr-pdf runs in the same tab, on the same bytes, so 'run OCR on this now' is a composition of two tools we already own. | ||||
| Size of the flattened fileflatten-pdf · measured 2026-09-02 | 6,580 B | not measured | 3,208 B | We lose |
| 105% larger, from a 6,705 B input. They roughly halve the document; we hand back something close to its original size. This is not a quality difference — the two outputs carry the same five flattened appearances, the same visible answers and identical extracted text (see the tie above, from this same measurement) — so nothing was bought with the extra bytes. The cause is NOT established and no claim is made about it: whether they drop the orphaned form dictionary and font resources we keep, re-encode the content stream, or use object streams where we do not is unread. That is the whole of what stands between this row and a clean tie. | ||||
| How much of a real 2-sheet workbook reaches the pageexcel-to-pdf · measured 2026-09-02 | 91.36% of its text (7 strings missing) | 100% | 100% | We lose |
| Every unique string in the workbook was searched for in all three outputs. Both incumbents reconstruct all 81; we lose 7 — the header/footer title, four floating text-box labels, a vessel name inside a shape, and the disclaimer. That is a stated boundary rather than a bug: we draw the cell grid and decline drawings, shapes, text boxes and headers, and the result panel names each one before you open the file. Both incumbents run a full spreadsheet renderer and draw them all. Our file is 6.3× smaller than Smallpdf's and 15.2× smaller than iLovePDF's, and that is NOT published as a win — we are smaller here largely because we drew less of your document. | ||||
| How much smaller a 1600x1200 photographic JPG getscompress-image · measured 2026-09-02 | 34.79% off (289,891 B) | 82.81% off (76,428 B) — iLoveIMG | not measured | We lose |
| Their file is 3.79× smaller than ours from the same 444,519 B source, and at the DEFAULT settings this row compares — their one automatic setting against our Balanced — that is unchanged. We hold the fidelity axis by as wide a margin as we lose this one (see the win below, from this same measurement). What HAS changed is that the tradeoff is now one a user of ours can actually choose. Until 2026-09-05 all three of our quality levels returned a byte-identical file on this image, and this row said 289,891 B was the smallest file our tool could produce here at any setting. That is no longer true and the sentence has been retired. The ladder was measured rung by rung with the shipped mozjpeg codec and the shipped SSIM: it tops out at 0.92834 (q90), BELOW even the lowest level's 0.93 target, so every level fell through to the top rung — three buttons, one output, no error. "Smaller" now carries an acceptability floor and returns q78: 80,697 B, 81.85% off, SSIM 0.81404. That reframes the gap rather than closing it. iLoveIMG's file was measured at SSIM 0.81208, so at MATCHED fidelity their 76,428 B against our 80,697 B is 5.6%, not 3.79× — their headline comes from operating at visibly-degraded quality, which our tool previously refused to do at any setting. That matched-fidelity comparison is NOT published as a tie and this row stays a loss: only OUR side was re-run, and iLoveIMG's figures are carried forward from 2026-09-02 unre-driven. Our side was re-driven through the LIVE production UI in a real browser on 2026-09-07 and both figures reproduce to the byte - 289,891 B and 80,697 B - so the earlier Node measurement, which substituted mozjpeg's decoder for createImageBitmap, is confirmed rather than merely assumed. Balanced and Sharper still return the same file as each other here — both promise imperceptibility, both deliver the best achievable — so the collapse is narrowed from three levels to two, not eliminated. | ||||
| How precisely the change is describedcompare-pdf · measured 2026-08-25 | 2 words added, 2 removed | two insertions of '+7 EDITED-' | not measured | We lose |
| Both found the one planted change, on the right page, both of its occurrences — and both reported ZERO when handed the same file twice. But a 7-character prefix was inserted into an existing word, and they say exactly that while we call it a word replaced. Theirs is the truer account, and on a document full of small in-word corrections it compounds. | ||||
| Conformance levels offeredpdf-to-pdfa · measured 2026-08-25 | 5 — 1b, 2b, 2u, 3b, 3u | 8 controls | 8 controls | We lose |
| Narrowed from 3 the same day by adding 2u and 3u, both PASSing veraPDF. The remaining gap is level A — 1a, 2a, 3a — which we decline rather than fail: it requires tagged structure, reading order and alt text that cannot be reconstructed from an untagged PDF, and generating them would ship an accessible-LOOKING document that is not accessible. Their 8 is a count of form controls; whether each is honoured is NOT MEASURED, and the one level we did check on both — 2u — came back PASS for Smallpdf and FAIL for iLovePDF. | ||||
| Output size converting a 6-page PDF to PDF/A-2bpdf-to-pdfa · measured 2026-09-02 | 30,116 B | 34,686 B | 28,666 B | We lose |
| Still the largest of the three, and still a loss — but 5.06% larger than Smallpdf where it was 49%, and now smaller than iLovePDF. The remainder was ONE font programme: 32,539 B of 42,824 B, on a document whose entire text uses 71 distinct characters. The embedded face carried every glyph the WinAnsi repertoire can address; it now carries the 71 the document draws, verified glyph by glyph against the full face in the downloaded file. All three figures were measured on the same day through each platform's real UI, and all three outputs pass veraPDF at 2b in one batch — so the comparison is between three files that each genuinely did the job. Both incumbents returned the same byte count as eight days earlier under a different hash: a fresh conversion from an unchanged engine. Nothing moved on either side, and the loss is measured rather than assumed. | ||||
| Time to recognise a 3-page 200-DPI scanocr-pdf · measured 2026-08-24 | 53,334 ms | 1,686 ms | not measured | We lose |
| About 32x slower, and a warm second run took 55,468 ms — so the cost is recognition on your own CPU, not the one-time engine download. Their figure is their server's own processing time and excludes the upload we do not need. Nearly a minute for three pages. | ||||
| Word headers, footers and sections reconstructed from a 6-page PDFpdf-to-word · measured 2026-09-03 | 6 footer parts, 6 sections | 12 parts, 6 sections | 12 parts, 6 sections | We lose |
| NARROWED, not closed. This read 0 parts and 1 section until 2026-09-03; sections and footers are now level at 6 and 6, and only the header zone is still theirs alone. The 0 headers is a deliberate refusal, not a missing feature: on this document the top line sits 44pt clear of the body while a gap INSIDE that body reaches 40pt, so a threshold low enough to hoist it would also tear ordinary paragraphs apart. The tool declines and says so on the page. Hoisting body text is silent and unfixable by a user who never sees it; leaving furniture inline is visible and correctable, so the two errors are not traded. All three still recover every word — 612, on all three. | ||||
| Character error rate on a 3-page scan against known ground truthocr-pdf · measured 2026-08-24 | 2.23% | 1.43% | not measured | We lose |
| Roughly 42 wrong characters in the document against their 27, on a clean synthetic scan — the easy case for both engines. Our margin on a photographed or skewed page is unmeasured. | ||||
| A cryptographic signature that can be verifiedsign-pdf · measured 2026-08-24 | not offered | offered (Premium) | not measured | We lose |
| On the free tier both products stamp a picture of a signature and neither file carries a signature dictionary. But a user who needs a signature that detects later tampering can buy one from iLovePDF and cannot buy one from us at any price. | ||||
| Output size of the searchable PDFocr-pdf · measured 2026-09-02 | 1,538,124 B | 1,421,024 B | not measured | We lose |
| Still larger, and still a loss — but 8.2% rather than 86.3%. The cause the old row could not name was the codec: each page was embedded with `embedPng`, and a scanned page is a photograph of paper, so a lossless format stored the scanner's own noise verbatim while the source pages were already JPEG. Measured on those pages at the recognition raster, PNG costs 1,498,104 B per page against JPEG q88's 456,406 B. q88 is the last quality at which no sample differs by more than 16/255 (PSNR 48.3 dB), which is what keeps this tool's "looks identical to the scan" claim true. Recognition is untouched — OCR runs on the bitmap before the encode. Both sides were re-driven on the same day and both searchable layers re-parsed and graded against the same ground truth: 3 pages each, and their smaller file is not smaller for having dropped text — it carries slightly MORE of it, at a lower error rate. Their output came back byte-identical to nine days earlier. The remaining 117,100 B is not decomposed; the likely lever is that we embed the 300-DPI recognition raster where the source pages are 200 DPI. | ||||
| Encryption revision, and the size it costsprotect-pdf · measured 2026-08-11 | AES-256 /R 5 — 9,903 B | RC4 128-bit — 8,089 B | AES-256 /R 6 — 6,417 B | We lose |
| Smallpdf beats us on both axes at once: 35.20% smaller AND on the revision standardised in PDF 2.0, where ours is Adobe's deprecated extension level 3. Both are AES-256, so the gap is in password verification — the axis an offline attack targets. Their own page understates them as "128-bit AES". Our figure was re-measured in production on 2026-08-28, after pdf-lib stopped stamping its own /Producer and /ModDate into every file we save (P.96): 9,951 B became 9,903 B, which narrows the gap by 48 bytes and does not come close to closing it. Only OUR side was re-run; both incumbent figures are carried forward from 2026-08-11. | ||||
| Size of the downloaded archive (6 pages split to 6 files)split-pdf · measured 2026-09-02 | 7,862 B | 9,025 B | 7,469 B | We lose |
| 5.26% larger than Smallpdf's for structurally identical content — narrowed from 17.3% by no longer writing pdf-lib's own /Producer and two timestamps into every part, but not closed. All three were re-driven on the same day and all three archives pass the same 21 structural checks; both incumbents landed within 4 bytes of where they were three weeks earlier, so the gap is slightly WIDER than the last row said, not narrower. Our parts are internally compressed, so the ZIP has almost nothing left to squeeze; theirs are larger and crush harder. Saving them uncompressed would nearly tie this row and cost 20% on the files a user KEEPS (below), so it was measured and rejected. | ||||
| Requests the page makes on a cold arrivalcompress-pdf · measured 2026-09-08 | 25 | 19 | not measured | We lose |
| 32% more round trips than theirs, on a page that is nonetheless 15% LIGHTER in bytes (595,160 against 700,852 — published as a win). More requests for fewer bytes means our code is split into more, smaller chunks than theirs, and on the Slow 4G profile this is measured at, each one costs latency that bytes alone do not show. Measured with a fresh browser context on both sides, so neither had a warm cache, and read at the network layer rather than from PerformanceResourceTiming, whose transferSize reads 0 for cross-origin responses without Timing-Allow-Origin and would have under-reported THEIR side. | ||||
| Requests the page makes on a cold arrivalpdf-to-jpg · measured 2026-09-08 | 23 | 19 | not measured | We lose |
| 21% more round trips, on a page transferring 253,017 bytes against their 703,090 — we are 2.8x lighter and still chattier. Measured on the same day, same instrument and same cold profile as the compress-pdf row above, and the same shape appears on all three tools put through /ux-verify, so this is our chunking strategy rather than anything about this tool. It is published per tool rather than once, because a row that generalises across tools is a row nobody can reproduce against a single page. | ||||
| Requests the page makes on a cold arrivalmerge-pdf · measured 2026-09-08 | 22 | 19 | not measured | We lose |
| 16% more round trips, against a page 2.8x heavier than ours (252,241 bytes to their 700,359). The narrowest of the three request-count losses measured this day. Steps to done, time to done and the failure path were NOT measured for this tool — those three axes are driven by hand and only compress-pdf got that treatment — so /ux-verify's overall verdict here is NOT-RUN rather than a comparison, and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivalrepair-pdf · measured 2026-09-09 | 22 | 19 | not measured | We lose |
| 16% more round trips, against a page 2.8x heavier than ours (253,364 bytes to their 700,830). The fourth tool measured on this axis and the fourth to lose it by the same margin, which is the point: it is our chunking strategy, not this page. Published per tool because a row that generalises across tools is a row nobody can reproduce against a single page. LCP, CLS, steps to done and time to done were NOT measured for this tool — the run took --skip-cwv and only the failure path was driven by hand — so /ux-verify reports those four axes NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivalpdf-to-excel · measured 2026-09-12 | 22 | 19 | not measured | We lose |
| 16% more round trips, against a page 2.8x lighter than theirs (253,968 bytes to their 704,185). PUBLISHED LATE, 2026-09-12, and how it hid is worth more than the row: the record was cited by the scan-recovery row above, and both gates over this — the score's worseAxesPublished and ux-evidence.test.ts — asked only whether the RECORD was cited by some row, never whether the AXIS was. So a tool that loses two different things and publishes one of them read as fully published. The measurement was taken the same day and sat unpublished for the length of one session. Both gates now count per axis. LCP, CLS, steps to done and time to done were NOT measured here, so /ux-verify reports those four NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivalocr-pdf · measured 2026-09-10 | 25 | 21 | not measured | We lose |
| 19% more round trips. (CORRECTED 2026-09-12: this row read 26 requests, 24%, and '595,000 bytes to 756,411' — three numbers that disagreed with the record it cites, which says 25, 19.0%, 594,727 and 756,167. Each ux-verify run OVERWRITES its record in place, so I cannot now tell whether the row was mistyped or the evidence moved under it; either way the row must match the file it points at, and it now does. Found by comparing every published number against its cited record — see the gate that makes it impossible to drift again.) Against a page still lighter than theirs (594,727 bytes to 756,167), but this is our SECOND-heaviest page after compress-pdf and the two are within 433 bytes of each other — worth stating because arrivalWeightBytes is what binds the Performance axis, and a fix aimed only at compress-pdf would simply hand the title to this page. Sixth tool measured, sixth to lose the requests axis: it is our chunking strategy, not any one page, and it is published per tool anyway because a row that generalises is a row nobody can reproduce. LCP, CLS, steps to done and time to done were NOT measured here — the run took --skip-cwv and only the failure path was driven by hand — so /ux-verify reports those four NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivalunlock-pdf · measured 2026-09-10 | 23 | 19 | not measured | We lose |
| 21% more round trips, against a page 2.5x lighter than theirs (284,225 bytes to their 701,730). The FIFTH tool measured on this axis and the fifth to lose it by a similar margin, which settles what it is: our chunking strategy, not any one page. Published per tool anyway, because a row that generalises across tools is a row nobody can reproduce against a single page. Measured the same day as the failure-path win on this tool and published beside it — a session that publishes only the axis it won is running a scoreboard, not a benchmark. LCP, CLS, steps to done and time to done were NOT measured here: the run took --skip-cwv and only the failure path was driven by hand, so /ux-verify reports those four axes NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivalsplit-pdf · measured 2026-09-12 | 23 | 19 | not measured | We lose |
| 21% more round trips, against a page 2.8x lighter than theirs (254,760 bytes to their 707,344). The EIGHTH tool measured on this axis and the eighth to lose it — the margins across all eight run from 15.8% to 31.6%, and in every single case we ship FEWER bytes over MORE connections. That is the finding: nothing about splitting a PDF explains it, so it is the chunking strategy, and the fix belongs in the build rather than on any one of these eight pages. Published per tool regardless, because a row that generalises across tools is a row nobody can reproduce against a single page. Measured the same day as the failure-path win on this tool and published beside it. LCP, CLS, steps to done and time to done were NOT measured here — the run took --skip-cwv and only the failure path was driven by hand — so /ux-verify reports those four axes NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivaljpg-to-pdf · measured 2026-09-12 | 22 | 19 | not measured | We lose |
| 16% more round trips, against a page 2.7x lighter than theirs (257,141 bytes to their 706,235). NINTH tool measured on this axis, ninth to lose it, and the first one that is not a PDF tool — this page takes images, which matters for the diagnosis rather than the score: these pages share almost nothing except the build that produced them. FIRST ROW MEASURED AS A MEDIAN OF THREE, and that is why it reads 22 rather than 23. A single run of this page returned 23, 20, 23, 23 within ten minutes against an unchanged build, and the 20 reached a committed record and flipped this axis to EQUAL — a published loss retired by noise, with the evidence agreeing. The probe now reports the median and keeps the spread (22-23 here, 19-20 theirs). LCP, CLS, steps to done and time to done were NOT measured, so /ux-verify reports those four NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| Requests the page makes on a cold arrivalpdf-to-word · measured 2026-09-12 | 23 | 19 | not measured | We lose |
| 21% more round trips, against a page 2.8x lighter than theirs (254,033 bytes to their 702,994). TENTH tool measured on this axis and the tenth to lose it. Measured as a MEDIAN of three per side, and this one did not move at all across the runs — 23 every time on ours, 19 every time on theirs. That matters after jpg-to-pdf flapped by three: the noise is per-page rather than inherent to the instrument, so a stable reading is worth more than a single sample and is recorded as one. LCP, CLS, steps to done and time to done were NOT measured here, so /ux-verify reports those four NOT-RUN and this row claims nothing beyond the axis it names. | ||||
| How much of the picture survives the compression (SSIM vs the original)compress-image · measured 2026-09-02 | 0.928 | 0.812 — iLoveIMG | not measured | We win |
| Both delivered files scored against the same source with the same implementation the tool's own UI reports from. Theirs is far smaller — see the loss above, from this same run — and 0.812 on a 1600×1200 image is not a subtle difference. We also tell you the measured quality of the file you just got, and that number survives independent scoring of the downloaded bytes: 0.928 claimed, 0.92834 measured. They report only a percentage saved and make no quality claim, which is not the same as being right about one. Whether 0.812 looks bad to a person is not established here; SSIM is a proxy, and nobody has compared the two files by eye. | ||||
| Drawings on a page that also carries textpdf-to-pptx · measured 2026-08-29 | 4 of 4, as native editable shapes | 1 of 4 — and only as a fill on a text box | 1 of 4 — and only as a fill on a text box | We win |
| Their slide 1 has zero pictures and zero geometry: three text boxes, one of which carries the red rectangle's fill at exactly its position and size because the label was merged into it. The blue circle, the black line and the bordered rectangle are simply absent, and nothing warns the user — their slide 1 holds ONE colour, D83838, where ours holds all four the page draws: D93838, 1F73D9, 000000, 333333. The trigger is TEXT, not difficulty: the same engine rebuilds all five shapes perfectly on the page that has none, which is a tie and is published as one. Ours used to survive as pixels inside a page render; since 2026-08-29 they are rebuilt from the content stream as <a:custGeom>, so they survive AND can be recoloured, moved and resized. Both incumbent legs were re-run the same day. | ||||
| Does a spatially laid-out table survive as a Markdown tablepdf-to-markdown · measured 2026-08-25 | yes — 108/108 cells, verified in production | claims yes; paywalled, unverifiable | not measured | We win |
| This row was published as a LOSS earlier the same day: we kept every cell value and emitted zero pipe characters, flattening a 4-column grid — a loss to our own pdf-to-excel. It is fixed and RDV'd in production. The hard part was refusing the false positive: two-column PROSE produces the same 9 multi-cell rows a real table does, and only cell length (7 chars vs 42) tells them apart. iLovePDF advertises tables and gates the tool behind Premium, so their output remains unverifiable; Smallpdf ships no such tool. | ||||
| Unchanged pages, and whether either document is uploadedcompare-pdf · measured 2026-08-25 | every page gets a verdict · 0 uploads | changed pages only · both files uploaded | not measured | We win |
| Comparing means handing over two confidential versions of the same file at once — strictly more exposure than any single-file tool — and ours never leaves the device. We also report 'Page 1 — Unchanged' explicitly; theirs lists only changed pages, so an unchanged page is absent rather than confirmed. For a reviewer those are different statements. | ||||
| Lossless PNG output, and its size against their lossy JPEG at 300 DPIpdf-to-png · measured 2026-08-25 | PNG · 1,103 KB doc / 3,766 KB scan | JPEG only · 1,405 KB / 4,380 KB | JPEG only, no options | We win |
| Neither incumbent can emit a PNG at all. At a matched 2481x3508 our LOSSLESS output is also the smaller one — 21.5% on a vector document and 14.0% on a scan. The photographic case was run specifically expecting to lose it. Their High setting compresses very lightly, so they pay JPEG's overhead without its benefit; a normal-quality JPEG would beat both. | ||||
| Does the user know what resolution they are gettingpdf-to-png · measured 2026-08-25 | buttons name the DPI | 'Normal (Recommended)' = 150 DPI, 'High' = 300 | no control | We win |
| Measured by running the same file at both of their settings: their quality control is a RESOLUTION control, and the recommended default quietly delivers a quarter of the pixels of their High. Neither label names a number. Ours read '300 DPI · Print quality' and '150 DPI · Smaller, for screen'. | ||||
| Are the extracted images the ones the PDF actually storesextract-images · measured 2026-08-25 | 3 of 3 byte-identical | 0 of 3 — re-encoded | not measured | We win |
| Checked by sha256 against the JPEG streams read straight out of the PDF. Theirs come back at the same 1654x2339 and the same 4:2:0 chroma but 7.08% of pixels differ by more than 2/255 and each file is 14% smaller — a second generation of JPEG loss on images the user asked to extract, not to compress. Measured pixel by pixel, not inferred from the byte count. | ||||
| Can someone without an account convert at allpdf-to-markdown · measured 2026-08-25 | yes — 833 ms, no account | no — Premium wall at convert | not measured | We win |
| The only incumbent that ships this tool gates it behind Premium and a signup form. Worse for their user: the file is uploaded at SELECTION and the wall appears at CONVERSION, so declining to pay means the document has already been handed over for nothing. Smallpdf ships no equivalent tool at all. | ||||
| Is the user told which typeface their archive will actually be inpdf-to-pdfa · measured 2026-08-25 | Helvetica → Liberation Sans, named before converting | not mentioned | not mentioned | We win |
| The input's Helvetica cannot be embedded, so all three had to replace it — ours with Liberation Sans, both incumbents silently with Arial. Only our panel says so, and says it before you convert. Archiving a document in a typeface nobody told you about is a decades-long surprise. | ||||
| Recovering a PDF whose cross-reference is destroyedrepair-pdf · measured 2026-08-24 | 3 of 3 pages, text intact | HTTP 400, no file | not measured | We win |
| Our output opens in a reader that refuses the input, and its text matches the undamaged original page by page. iLovePDF returned Damaged/Corrupted File — and returned it for a healthy control and for a PDF they had produced themselves, so this is their endpoint on this date rather than our fixture. It does not say our repair beats a working competitor. | ||||
| Body text wrongly hoisted into a running header, on an ADVERSARIAL documentpdf-to-word · measured 2026-09-04 | 0 header parts — every line stays in the body | 2 header parts, each holding half a sentence | 2 header parts, the same two strings | We win |
| Both incumbents take the first body line of each page and write it into that section's running header. The hoisted text is the first HALF of a sentence whose second half stays in the body, so the sentence is broken across the header boundary and its first half now repeats on every page of the section. That is the silent, unbounded error: a user who never opens the header pane cannot see that a paragraph left the flow, and cannot recover it from the output. filum declines here for a measured reason — the candidate sits 20pt clear of the body while the body's own largest internal gap is also 20pt — and says so on the page. The same three platforms TIE on a document that is merely furniture-free; this is the first time the axis has been given an adversarial one. | ||||
| Cell values recovered, output size, and the line above the tablepdf-to-excel · measured 2026-08-26 | 108/108 · 2,736 B · 3 captions kept | 108/108 · 7,544 B · captions dropped | not measured | We win |
| Data recovery is a tie at 100% — every cell of a spatially laid-out table, in the right place. We are 2.76x smaller, widened from 2.1x by no longer repeating the header, and we keep the caption above each table that they discard. Joining the pages could easily have cost us that: the captions are hoisted above the header rather than deleted, or left inline where a one-cell row would break the sortable range. | ||||
| Fidelity at the default, measured against the source at source resolutioncompress-pdf · measured 2026-08-22 | SSIM 0.97362 | SSIM 0.95738 | SSIM 0.93528 | We win |
| The widest fidelity margin in this series, kept while the file got 40% smaller. It was not free: the encoder change cost 0.00199 of SSIM, down from 0.97561. Smallpdf also drops resolution to 130 DPI where filum and iLovePDF both hold 150. | ||||
| Resolution of the image you get at each tool's default settingpdf-to-jpg · measured 2026-07-23 | 300.1 DPI | 150.1 DPI | 300.1 DPI | We win |
| Twice iLovePDF's default on an A4 page — 2481 px wide against 1241. A higher option exists in their interface; this is what a user gets without changing anything. Against Smallpdf it is a tie on resolution, and their JPEG is smaller than ours at the same pixel dimensions, which is heavier compression rather than less detail. No quality score was measured on this axis, so no quality claim is made in either direction. | ||||
| Output size for a 6-page deckpdf-to-pptx · measured 2026-08-27 | 13,562 B | 25,858 B | 25,866 B | We win |
| Was 456,390 B and the worst of the three by 17.6x, caused by six JPEG page renders worth 534 KB. The archive now contains ZERO media parts: a page that paints nothing we could not rebuild has no background left to keep, so it ships no picture. Re-run in production on 2026-08-29 against the vector-artwork build: 13,562 B, byte-identical, because a text-only deck has no painting operators for that change to touch — measured rather than reasoned. The old caveat here said 'a page carrying artwork still ships its picture, so this margin is a property of text-only pages'; that is now FALSE and is corrected rather than left. On graphics-text-3p.pdf, a deck that is two-thirds artwork, the same day measured 8,583 B against 20,950 and 20,999 — and nobody ships a picture there either. The cause of THAT margin is package boilerplate, not content: 29 parts to our 15, including three slide layouts worth 17,045 B against our one at 507 B. Their layouts are the honest half of the trade — a real Office deck has them, and a user adding a slide to ours has one to pick. | ||||
| Output size after redacting one box on one pageredact-pdf · measured 2026-08-26 | 3,125 B | 4,462 B | 3,874 B | We win |
| Was 40,970 B — 10.6x Smallpdf's — because every marked page became a 200-DPI image. The same fix that closed the text loss closed this one, and it goes past both of them rather than level with them. Measured on a foreign writer's file too: iLovePDF's own 190,579 B deck came back at 181,696 B with 584 characters removed across 8 pages, SMALLER than the input, where the old method would have produced megabytes of PNG. | ||||
| Output size of the .docx from a 6-page PDF, and emphasis preservedpdf-to-word · measured 2026-09-03 | 3,820 B · 6 bold runs | 23,824 B · 0 bold runs | 23,887 B · 0 bold runs | We win |
| About 6.2x smaller — down from 15x, because reconstructing page furniture added real parts that earn their weight. Still qualified: smaller partly because ours contains less, including a numbering part on THIS document, which carries no numbered list. The 6 bold runs against their 0 SURVIVED the furniture change, which was not free — the line carrying that emphasis is the same line the detector declined to hoist, and a test pins the count so it cannot regress silently. Conversion time is deliberately NOT claimed here: it was not re-measured on 2026-09-03, and pairing a fresh size with a ten-day-old duration would publish a comparison of two dates. | ||||
| Output size after signing a 6-page PDF, and text preservationsign-pdf · measured 2026-08-24 | 16,925 B | 40,492 B | not measured | We win |
| 2.4x smaller for the same artefact — one stamped image on page 1 — and both keep all 6 pages with every page's text byte-identical, so neither re-renders the document to sign it. Ours makes zero network requests of any kind while doing it. Our figure was re-measured in production on 2026-08-29, after pdf-lib stopped stamping its own /Producer and /ModDate into every file we save (P.96): 16,998 B became 16,925 B, with the same typed BENCH-SIGNER on page 1 and 'Place on every page' read back as off before the submit. Only OUR side was re-run; iLovePDF's figure is carried forward from 2026-08-24. | ||||
| Reduction on a 3-page scanned PDF, at each tool's defaultcompress-pdf · measured 2026-08-22 | -68.6% | -59.7% | -64.6% | We win |
| This is the only number any of these three interfaces shows the user, and until 2026-08-22 filum was LAST on it at -47.3%. Two measured causes, both now fixed: the JPEG encoder was the browser's canvas rather than mozjpeg, and the recompressed streams were not Flate-wrapped where both incumbents' were. The competitors' figures are carried forward from 2026-08-09 and were not re-run. Our side was re-measured in production on 2026-08-29 after the metadata fixes (P.96 + P.107): 239,952 B became 239,883 B, which is -68.61% against -68.60% and does not move this figure at one decimal. Recorded because it was measured, not because it changed anything. | ||||
| Output size, 6 pages numberedpage-numbers · measured 2026-08-17 | 6,451 B | 16,416 B | not measured | We win |
| 60.70% smaller. Measured cause: iLovePDF subset-embeds a font program; we use the reader's Standard-14 Helvetica. That is a real trade — their output is more self-contained — and it accounts for most of the growth. The rest is unexplained and recorded as unexplained. Our figure was re-measured in production on 2026-08-28, after pdf-lib stopped stamping its own /Producer and /ModDate into every file we save (P.96): 6,525 B became 6,451 B. Only OUR side was re-run; iLovePDF's figure is carried forward from 2026-08-17. | ||||
| Output size, 6 pages markedwatermark-pdf · measured 2026-08-17 | 6,985 B | 16,708 B | not measured | We win |
| 58.19% smaller, every page marked in both. Same measured cause and same honest trade as page numbers: their embedded font program against our Standard-14 reference. Our figure was re-measured in production on 2026-08-28, after pdf-lib stopped stamping its own /Producer and /ModDate into every file we save (P.96): 7,054 B became 6,985 B. Only OUR side was re-run; iLovePDF's figure is carried forward from 2026-08-17. | ||||
| Output size after cropping 3 pagescrop-pdf · measured 2026-08-18 | 2,977 B | 4,567 B | 4,567 B | We win |
| 34.82% smaller than either. Correctness is a tie — all three delivered the requested rectangle and all three narrow both page boxes. And none of the three actually removes the cropped-away content: it survives in every output. Only our page says so. Our figure was re-measured in production on 2026-08-29, after pdf-lib stopped stamping its own /Producer and /ModDate into every file we save (P.96, completed by P.107): 3,046 B became 2,977 B. The same rectangle was driven in by real mouse input and read back as Top 10 / Right 25 / Bottom 50 / Left 25 before the submit, and the output re-checked with the record's own instrument — 8 of 8, 297.63 x 336.76 pt on all three pages. Only OUR side was re-run; both incumbent figures are carried forward from 2026-08-18. | ||||
| Size growth from rotating 6 pagesrotate-pdf · measured 2026-08-10 | +0.02% (5,219 B) | +43.9% (7,507 B) | +23.5% (6,442 B) | We win |
| Rotation is lossless in all three — identical character counts, 15 structural checks passed each. The difference is what each writes back: we edit the page dictionaries in place. Re-measured in production on 2026-08-28, after pdf-lib stopped stamping its own /Producer and /ModDate into every file we save (P.96): rotating six pages now costs ONE byte — 5,218 in, 5,219 out — where it used to cost 72. Only OUR side was re-run; both incumbent figures are carried forward from 2026-08-10. | ||||
| Output size, two documents merged to 9 pagesmerge-pdf · measured 2026-08-11 | 7,388 B | 10,885 B | 9,294 B | We win |
| The only output smaller than the 8,162 B that went in. Worth naming the part that is not ours: Smallpdf is the only one of the three that collapses the two documents' identical font into one reference. We do not, and neither does iLovePDF. | ||||
| Output size after deleting pages, 4 keptorganize-pdf · measured 2026-08-11 | 3,558 B | 5,176 B | 4,429 B | We win |
| All three produced the right four pages in the right order, so on correctness this is a tie and the size win is invisible to a user whose only question is whether the pages went. iLovePDF's typed page range is faster than clicking thumbnails on a long document. Our figure was re-measured in production on 2026-08-29: 3,702 B became 3,558 B. The 2026-08-28 metadata fix had moved this row by nothing, because it fixed the way a PDF is LOADED and this tool builds a new document instead; P.107 closed the other half, and the output no longer carries pdf-lib's URL as its Producer. Only OUR side was re-run; both incumbent figures are carried forward from 2026-08-11. | ||||
| Total size of the PDFs you keep (6 single-page files)split-pdf · measured 2026-09-02 | 7,727 B | 10,612 B | 9,055 B | We win |
| The files that survive after the archive is unpacked. Ours are the smallest of the three even though our archive is not — see the loss above, which came out of this same measurement — and the margin is 14.7% against the better incumbent, up from 5.1% before the parts stopped carrying pdf-lib's URL as their producer and a timestamp of the minute you split the file. All three were re-driven on the same day; both incumbents landed within a few bytes of their previous figures. | ||||
| Output size, one image rotated 90 degreesrotate-image · measured 2026-08-16 | 85,732 B | 96,699 B | not measured | We win |
| 11.3% smaller, and both outputs contain exactly the same pixels — zero differing against the reference — so this is not a quality trade. Measured against iLoveIMG. Their tool rotates a whole batch in one pass and accepts GIF; ours does neither. | ||||
| What you are told when the PDF cannot be readpdf-to-word · measured 2026-09-12 | at pick, with no upload and no click | after an upload, a click and a page change | not measured | Tie |
| Both sides name a cause and a next step, on both inputs — truncated PDF bytes and a JPEG wearing a .pdf name. Ours, verbatim: "This file could not be read as a PDF. Try re-exporting it." with a "Choose another file" button. Theirs: a dedicated error page with a "Damaged/Corrupted File" heading, what to check, and a Retry button. On the axis as stated this is a tie and is published as one. WHERE WE ARE BETTER, RECORDED AND NOT SCORED: ours arrives with no upload, no click and no wait — the alert is on screen the instant the file is chosen, because this tool has no configuration step and the bytes never leave the device. Theirs needs the file uploaded, the button pressed, and a navigation. That is a difference in STEPS and TIME, and both of those axes are NOT-RUN in this record. Widening the category to absorb it after seeing the result is how a threshold stops meaning anything. | ||||
| What you are told when an image cannot be readjpg-to-pdf · measured 2026-09-12 | the format it really is, and where to take it | a cause, what to check, and a Retry button | not measured | Tie |
| MEASURED AS A LOSS AT 03:35 UTC AND AS A TIE AT 05:58 THE SAME DAY, and both readings are in the record because a row that shows only the state it was repaired into is not evidence. The loss: given a file with no image in it, the row said "can't read" — two words, no cause, no next step — against their page naming a cause, what to check, and a way back. It was the first failure path in this series an incumbent won. The fix reads the file's BYTES rather than its extension, so the sentence names what the file actually is: a renamed PDF is told it is a PDF and pointed at Merge PDF or Split PDF; a file that is no format at all is told there is no image data in it; a truncated JPEG is told the download was incomplete. Verified in production at 05:58 UTC on both inputs, in one list, each showing a different badge and a different sentence. A TIE AND NOT A WIN: the axis asks whether the user is told a cause and given a next step, and after the fix both sides do. Ours names the real format where theirs is a page reused across tools that tells someone who uploaded a .jpg to open it "with your PDF software" — a real difference, and not one this axis measures. Inventing a finer axis after seeing the result is how a threshold stops meaning anything. What we already did better and kept: on a mixed batch the button relabels itself "Create PDF (1 page)", so the count states the consequence before anything is pressed; their result page names no exclusion at all. | ||||
| Whether the document survives the edit as a document, rather than being flattened into a pictureedit-pdf · measured 2026-09-02 | 3/3 pages, 0 images added, every path operator intact | 3/3 pages, 0 images added, every path operator intact | not measured | Tie |
| An annotation tool's one real risk is that it rasterises the page and bakes the marks in, which looks identical on screen and destroys the document. It did not happen on either platform. The fixture's third page carries artwork and NOT ONE GLYPH, so a character count is blind there and only the image and operator counts can answer — both outputs still store zero images, invoke zero XObjects, and carry every path operator at exactly the source's count, with all three text anchors extractable and the added text readable as real text by an independent reader. Nobody is better than anybody. filum's output is 2,252 B against 12,296 B, but 8,171 B of that gap is an embedded ArialMT subset iLovePDF ships and we do not, so the size difference is a tradeoff and is NOT ranked here. Smallpdf is NOT RANKED: their editor applied the text correctly and their free download quota was exhausted before an artefact could be retrieved. Not measured on any platform: rendered appearance, which is exactly where the missing embedded font would show. | ||||
| A leading "1.1" turned into Word list numbering that renders the source's own numberspdf-to-word · measured 2026-09-04 | 102 numbered items, rendered 1.1-1.34, 2.1-2.34, 3.1-3.34 | 102 numbered items, same rendered sequence | 102 numbered items, same rendered sequence | Tie |
| A published LOSS until 2026-09-04, when this read 0 numbering parts against their 102. All three now emit word/numbering.xml with 102 numPr, and the numbers a reader SEES are identical item for item. Published as a tie, not a win: they were there first and we matched them. The figure quoted is the RENDERED sequence and not the element count, because 102 numPr pointing at a definition that renders 1.1 to 1.102 would satisfy every count in this row and be worse than emitting none. The mechanisms differ — they encode the constant part as the start of a level no paragraph instantiates; we carry it as literal text over a single level — and both render the same here. | ||||
| Body paragraphs from a 102-line document, which is how finely the reading order survivespdf-to-word · measured 2026-09-04 | 102 paragraphs | 102 paragraphs | 102 paragraphs | Tie |
| This read 6 against their 102 the day before: 34 separately-numbered lines per page were reflowed into roughly two flowing paragraphs. One rule fixed it — a line bearing an enumerator always starts its own paragraph — and that decision is deliberately separate from the decision to rebuild the numbering, on a lower evidence bar, because segmenting a line changes not one character while merging "1.1 Foo" and "1.5 Bar" into prose destroys the structure the user came to edit. Prose reflow is untouched: a 6-page document with no enumerators still emits the same 18 paragraphs and 6 bold runs it did before. | ||||
| Numbers that CANNOT be regenerated — a struck-clause gap, zero padding, a lone referencepdf-to-word · measured 2026-09-04 | all 8 kept verbatim, refusal stated | all 8 kept verbatim | all 8 kept verbatim | Tie |
| Converting "1.1" into generated numbering DELETES the characters a user can see, so a wrong reading changes what the document SAYS: a source numbered 1.1, 1.2, 1.5, 1.6 — clauses 1.3 and 1.4 struck — comes back 1.1, 1.2, 1.3, 1.4 under a single list. A fixture carrying that gap, a zero-padded run (2.01-2.03, which no decimal counter renders) and one isolated reference was built to find out whether the incumbents fall for it. They do not: all three decline and leave every character alone. Published as a tie rather than the win it was built hoping to find. filum additionally states why; that is candour, not correctness. | ||||
| Body text wrongly hoisted into a header, on a document with no running head or footpdf-to-word · measured 2026-09-04 | 0 hoisted | 0 hoisted | 0 hoisted | Tie |
| This axis was written down as an open question in August — whether the incumbents' header detection MISFIRES, hoisting an ordinary first line out of the page flow. Measured again today on a 3-page document of evenly-led body text with no furniture at all: none of the three hoists anything, unchanged from 2026-09-03. It is a tie on THIS document and is published as one. It is NOT the whole answer, and the win row for this tool now carries the rest: on a document that is adversarial rather than merely furniture-free, both incumbents do hoist a body line into a header, and there we win. | ||||
| Words recovered into the .docx, counting body and every header/footer partpdf-to-word · measured 2026-09-03 | 612 words | 612 words | 612 words | Tie |
| An exact three-way tie on both the total and the 68 unique words. No platform loses a word of a digital PDF, which is the floor rather than the achievement. It is recorded because filum's furniture change moved text between parts, and a reconstruction that quietly dropped a line would show up here first. An earlier extractor made this look like a 30-word win for us by joining runs without a separator, which penalised whichever side segments more finely; reading text per paragraph gives the same 612 on all three. | ||||
| Whether each field type actually carries its value into the filefill-pdf-forms · measured 2026-09-02 | 4 of 4 field types | not measured | 4 of 4 field types | Tie |
| A value can render on screen and be absent from the file, so every output was read back by an independent reader — pdf-lib, by field name — rather than by the tool that wrote it. On a form where all four fields start EMPTY, so nothing can be preserved rather than written, filum and Smallpdf both carry the text, the checkbox, the radio and the dropdown. Nobody is better than anybody. The radio target was deliberately the second option, so a tool defaulting to the first would have failed. iLovePDF is NOT RANKED here: their editor applied all four values on screen, but their download control could not be driven in this environment — the link they offered carried a placeholder task id — so no artefact of theirs was obtained by the path a user takes. Not measured: whether any of the three also draws a correct appearance, so the value is visible in a reader that does not render fields itself. | ||||
| Whether flattening locks the fields and keeps every answerflatten-pdf · measured 2026-09-02 | 4 of 4 fields removed, both visible answers kept | not measured | 4 of 4 fields removed, both visible answers kept | Tie |
| Flattening has two obligations a tool can half-satisfy: the interactive fields must be gone, and their answers must survive as page content. A tool that deleted both would look like the winner on file size, which is why size is not scored alone. On a filled form with four field types both outputs are indistinguishable — fields 4 → 0, five flattened appearances each, the static control intact, and byte-for-byte the same 126 characters of extracted text where the source had 104. Nobody is better than anybody here. Not checked on either side: the checkbox tick and radio selection carry no text, so extraction cannot see them — the appearance counts say they were carried, and no page was rendered to confirm it. iLovePDF ships no flatten tool, so this is the whole field. | ||||
| Are the drawings themselves editable, on a page that is artwork onlypdf-to-pptx · measured 2026-08-29 | yes — 5 of 5 as native vector shapes | yes — 5 of 5 as native vector shapes | yes — 5 of 5 as native vector shapes | Tie |
| Published as a LOSS on 2026-08-28 — ours was one flat 150 DPI picture and could not be touched. The artwork is now rebuilt from the content stream as <a:custGeom>, and on this page all three arrive at 5 of 5. That is CATCHING UP, and it is recorded as a tie rather than as a win, because on this axis nobody is better than anybody. Both incumbent legs were re-run the same day rather than carried forward. The one measured difference is too small to be an axis and is stated rather than claimed: the source writes 0.85 0.22 0.22, and 0.85 x 255 is 216.75 — we round to D9, both of them truncate to D8. | ||||
| Can the resulting deck actually be editedpdf-to-pptx · measured 2026-08-27 | yes — 11 visible runs on slide 1, no page image | yes — 97 visible runs on slide 1 | yes — 97 visible runs on slide 1 | Tie |
| Published as a LOSS two days earlier, and it was the tool's headline one: our slide was the page as a JPEG with the text over it at alpha 0, so retyping a heading left the old heading showing underneath — 0 editable runs against their 97. The page is now rendered with its TEXT REMOVED from the content stream and the runs painted back on top in the colour that stream drew them in. Counted the same way on all three, from slide1.xml and confirmed by python-pptx: nobody is painting invisible text any more, so the axis stops separating us. That is level, not ahead. Run COUNT is not the axis — 11 whole lines against 97 mid-word fragments is granularity, and which is pleasanter to edit was not measured. | ||||
| Text elsewhere on the redacted page (a string far outside the box)redact-pdf · measured 2026-08-26 | kept | kept | kept | Tie |
| Published as our worst LOSS two days earlier: we flattened the whole marked page to an image, so a line 60% of the way down it stopped being text while both incumbents kept it. Now the marked glyphs are deleted from the content stream and nothing else is touched — verified in production on the same fixture, with the marked string absent from the raw bytes and PUBLIC-OUTSIDE-9M2X still there. A tie is the honest verdict: they were already doing this, and we have caught up rather than overtaken. | ||||
| PDF/A-2u conformance — the level that guarantees text stays extractablepdf-to-pdfa · measured 2026-08-25 | PASS | FAIL, clause 6.6.4 | PASS | Tie |
| Published as a LOSS earlier the same day, when only Smallpdf's file reached the Unicode level. Now a tie with them and a win over iLovePDF, adjudicated by veraPDF on the same 6-page input — and on a 5-flavour corpus sweep, 24 of 24. Closing it did not need the CMap writer it looked like it needed: that was built, measured to change nothing, and deleted. What it needed was a REFUSAL — a document whose font carries no character map is now told level U is unreachable instead of being handed a file that declares a conformance it does not have. | ||||
| Text carried onto the slides, and slide countpdf-to-pptx · measured 2026-08-25 | 2,724 chars · 6 slides | 2,736 chars · 6 slides | 2,736 chars · 6 slides | Tie |
| From a 2,784-character input. All three drop a little and no one drops a page; the 12-character spread between them is not a difference. Conversion time is level too — 1,934 ms for our whole job against 1,844 and 1,933 ms of their server time, which excludes their uploads. | ||||
| Does the output actually conform to PDF/A-2bpdf-to-pdfa · measured 2026-08-25 | PASS | PASS | PASS | Tie |
| Judged by veraPDF, the ISO reference implementation, over all three outputs in one batch — and the input was proven to FAIL four clauses first, so the test is known to be able to fail. All three also preserved every one of the input's 2,784 characters across 6 pages. | ||||
| Is the covered text actually gone from the fileredact-pdf · measured 2026-08-24 | removed | removed | removed | Tie |
| Read out of the decompressed content streams, against a control file that still holds every needle so a broken probe cannot report a flattering result. No platform left the covered string recoverable. Ours is the only one that never uploads the document to do it. | ||||
| One table spanning three pagespdf-to-excel · measured 2026-08-26 | 1 sheet, 24 rows, header once | 1 sheet, 24 rows, header once | not measured | Tie |
| This was our worst loss on this tool: we returned three sheets with the header reprinted in each, and a table you cannot sort is the reason people convert a PDF to a spreadsheet in the first place. A page now joins the sheet above it when it reprints that sheet's header, and the two outputs are structurally identical — one sheet, one header, 24 contiguous data rows, 108 of 108 values each. A TIE, not a win: they got here first and we have matched them. | ||||
| Output size for one 1600x1200 imagejpg-to-pdf · measured 2026-08-26 | 114,019 B | 115,142 B | 543,348 B | Tie |
| We were 48.61% larger than iLovePDF here. We now store a 256-colour image the way they do — an /Indexed palette at one byte per pixel instead of truecolour at three — and the file fell 33.4% to just under theirs, with the pixels byte-for-byte identical. All three were re-run today and both incumbents came back byte-identical to eight days ago. A TIE and not a win: 1,123 bytes on one fixture, reached by adopting their own encoding, is catching up rather than leading. Against Smallpdf it is not close — 4.77x smaller, and lossless where they re-encode to JPEG and change 2,117,477 channel bytes. | ||||
| Output size after removing a password (6-page document)unlock-pdf · measured 2026-09-01 | 5,547 B | 7,507 B (2026-08-11) | 5,756 B (2026-08-11) | Tie |
| This was a 54.73% loss whose cause the row admitted was unmeasured. It is measured now, and it was not encryption — it was the library. Hand @cantoo/pdf-lib a PLAINTEXT document with no password anywhere and 5,218 B comes back as 8,593 B; stock pdf-lib returns 5,218 B exactly. Decryption accounted for 313 B of a 3,688 B gap. Not the content either — Page 2,782 B, Font 81 B, Catalog 33 B are byte-identical between the two — but the framing: the fork left 17 objects at top level where stock packs them into a compressed object stream and writes 8. We now decrypt with the fork, which is the only one that can read an encrypted PDF, and re-save through stock. Verified lossless by parsing rather than scanning, on a document carrying three form fields with values, a link annotation with its URI and three widgets: every one survives. 5,547 B measured in production today. A TIE AND NOT A WIN, for a specific reason: 209 bytes under Smallpdf is 3.6%, and their figure is carried forward from 2026-08-11 and was NOT re-run. jpg-to-pdf above was called a tie at a 1.0% margin WITH all three re-measured; claiming a win here on a stale number and a thinner margin would be worse evidence for a bigger claim. What is solid is that the loss is gone: going from 54.73% larger to 3.6% smaller cannot be explained by drift in their figure. | ||||
An empty column means that platform was not measured on this axis, not that it scored zero. Smallpdf's free tier allows two downloads per window and refuses the next one, so a session measuring several tools in a row runs out of them.
Every figure here is copied from a dated measurement record kept with the source, never recalculated for this page, and a build fails if a record exists that this table does not show. Numbers describe the input that was measured — a different document will give different bytes, and any of these can change when a competitor ships.
What this means in practice
On output quality the table above is the answer, and it is mixed: Filum wins most size and fidelity axes measured so far and loses several, including the compression percentage that every one of these tools puts in front of the user. Where Filum differs structurally is architecture: the operations most likely to involve sensitive documents (sign, redact, crop, organize, split, merge) run locally in your browser. There is nothing to upload and no deletion promise to trust, because nothing was ever sent.
Unlike the rest of this category, Filum runs every tool on your device — even format conversion — so your file is never uploaded to any server at all. The single-origin figure above is the whole story: one third-party receives error and performance telemetry, and nothing in the file path phones home.