Fingerprint PDF
Mark each copy of a PDF with its own hidden identifier, then read that identifier back out of a leaked file.
Drag & drop a PDF here
or click to select a file
About Fingerprint PDF
When a confidential document goes to twenty people and turns up somewhere it should not, the useful question is which of the twenty copies it was. This tool answers that by giving every copy its own identifier, written into the file in several places at once, and by reading those identifiers back out of a file you were later handed. Everything happens in this browser tab — the document is never uploaded.
Say this plainly: deterrence, not proof
The marks written here are not cryptographic. Nothing is signed, nothing is timestamped by an independent authority, and nothing detects tampering. A person who suspects their copy is marked can remove every trace in under a minute: print it to a new PDF, flatten it to page images, run a metadata stripper, pass it through OCR, or retype the interesting paragraphs into an email. The value is that most leaks are careless rather than careful, and that telling recipients their copies are individually marked changes behaviour on its own. A recovered identifier tells you which copy a file descends from. It does not establish who shared it, and the manifest that links identifier to person is a document you control and someone could reasonably dispute. Use it as one signal among several.
Where the identifier is written
Three places, so that a partial cleanup still leaves something behind. It goes into the Keywords entry of the document information dictionary, preserving any keywords already there. It goes into a custom Fingerprint key in that same dictionary, which ordinary metadata editors do not show and some do not carry forward. And it is drawn as real page text at four points and two per cent opacity in two corners of every single page, so it survives operations that only touch metadata — merging, splitting, rotating, page-number stamping. On a page too narrow to hold the marker at four points the text is scaled down to fit rather than drawn past the page edge, where a viewer would clip it away and no extractor could read it back. Both corners are measured from the page a reader actually sees — the CropBox where there is one, overlapped with the sheet — rather than from the sheet itself, because those are not the same rectangle on a cropped or print-ready file and a mark outside the visible box is dropped by text extractors, this tool's own Verify included. All three marks use the same bracketed marker so the scanner can find them again, and the identifier is kept to 120 characters of a conservative alphabet precisely so that what is written can always be read back. Optionally you can add a faint diagonal line of visible text across each page, which is the honest kind of watermark: it announces that the document is tracked.
The corner text is faint, not hidden. Anyone who selects all the text on a page, or runs the file through a text extractor, will see it. Making it invisible to extraction would also make it invisible to this tool's own Verify mode, which would defeat the purpose.
Batches and the manifest
Batch mode takes one source document and a list of recipients, and returns a ZIP containing one uniquely marked PDF per recipient plus a manifest.csv holding the copy number, the filename, the recipient label, the random UUID written into that copy, and the time the batch was made. Because the identifiers are random rather than derived from names, an intercepted copy gives away nothing about who else received one — and equally, without the manifest a recovered identifier is a meaningless string. Save the manifest somewhere you will still have it in six months, and do not put it in the folder you distribute. If you leave the recipient list blank the tool makes numbered copies instead, which suits handing out a document at an event.
Practical limits
Encrypted PDFs cannot be parsed by any of the three modes, so unlock them with Unlock PDF before marking and re-protect afterwards with Protect PDF; to check a protected copy kept its marks, unlock a duplicate and verify that, since most encryptors drop the two metadata marks and leave only the page text. Identifiers are folded to unaccented letters, digits and a handful of punctuation marks and cut to 120 characters, because spaces break the text scanner and anything longer or more exotic cannot be reliably read back out of a page. A batch is capped at 200 copies and each one is built in memory before the ZIP is written, so a large source file with many copies will be limited by RAM rather than by the tool; abandoning a batch — choosing another file, or switching mode — stops it, and no ZIP arrives afterwards. In Add mode every click of the button writes another copy, so the panel lists every copy made from the file you loaded, filename and all, rather than only the last one; an identifier you type is used exactly as typed, so leaving it in place across two clicks gives you two files carrying the same mark, and the panel says so rather than letting you distribute them as though they were distinct. Verify reads the text layer only: a fingerprinted document that was printed and scanned back in has no text layer left, and will come back clean even though the paper passed through a marked copy. If you only need a plain visible watermark on every page, Add Watermark to PDF is the simpler tool; if you want the metadata gone rather than added to, use Remove PDF Metadata.
Three marks per copy
The identifier goes into the Keywords entry, into a custom Fingerprint key in the document information dictionary, and as 4pt text at 2% opacity in two corners of every page — placed inside the page a reader actually sees, and shrunk to fit where that page is too narrow for it, so the text mark never runs off the edge and out of reach. Deleting all three by accident is unlikely; deleting them on purpose is not hard.
A distinct copy per recipient
Paste a list of names and get back a ZIP holding one uniquely marked PDF each, plus a manifest.csv that maps every filename and recipient to the identifier inside it. That mapping is the entire point — without it a recovered id means nothing.
Reads the marks back out
Drop a leaked file into Verify and it scans the metadata with pdf-lib and every page text layer with pdf.js, reporting each identifier it finds and exactly where. A clean file simply reports nothing found.
Frequently Asked Questions
Is this proof of who leaked a document?
No, and it is important to be clear about that. This is deterrence and attribution evidence, not cryptographic proof. Nothing here is signed, timestamped by a third party or tamper-evident. Anyone who suspects a document is marked can flatten it to images, re-print it to PDF, strip the metadata, run it through OCR, or simply retype the contents, and every mark this tool writes is gone. A confident recovered identifier tells you which copy the file came from; it does not, on its own, prove who passed it on, and the mapping in your manifest could itself be disputed. Treat it as one signal, not a verdict.
Will the invisible text show up when someone reads or prints the document?
It is drawn at 4 points at 2% opacity in two corners, which is below the threshold of casual notice on screen and normally invisible in print. It is not genuinely hidden, though: anyone who selects all the text, copies a page, runs pdftotext, or opens the content stream will see it immediately. That is a deliberate trade-off — a mark that survives copy and paste is a mark that a determined reader can find.
Does it change how the document looks?
In Add mode with the visible watermark off, almost not at all: two corner marks at 2% opacity and some new metadata. Turn the diagonal watermark on and it is meant to be seen — grey text set at 45 degrees across the middle of every page at 8% opacity. A line at 45 degrees uses up as much height as width, so it is sized against the shorter side of the visible page and covers about 85% of it, which keeps it on the page on wide short pages too. It is also capped at 46 points, so a short label stays smaller rather than being blown up into a headline: the default CONFIDENTIAL on A4 hits that cap and covers roughly 40% of the width. On a page too small to hold the line at four points — a stamp-sized page, or a long label on a very small one — the diagonal is skipped for that page rather than drawn off the edge, where a reader would see half a word; the hidden corner marks scale further down and still go on. The diagonal is drawn with Helvetica, which can only render Latin-1, so characters outside that (a name in Chinese, say) are dropped from the line and the tool tells you before you run it — if nothing drawable is left, the diagonal is skipped rather than replaced by something else. Page content, fonts, images and page count are untouched either way; the file grows by a few hundred bytes per page, so about a kilobyte on a three-page memo and around 50 KB on a 200-page report.
What is in the manifest, and why does it matter so much?
manifest.csv has one row per copy with the copy number, the filename in the ZIP, the recipient label you typed, the identifier written into that copy, and a timestamp. Keep it somewhere safe and out of the ZIP you distribute. The identifiers are random UUIDs, so a recovered id is meaningless without the manifest — which is exactly what you want if the ZIP is intercepted, and exactly what ruins the exercise if you lose the file.
My recipient names look wrong when I open manifest.csv in Excel.
The file holds exactly what you typed — the recipient column is written verbatim, commas and quotes and all, so any CSV reader gets your labels back byte for byte. What Excel and Google Sheets do on top of that is the problem: a cell beginning with an equals sign, a plus, a minus or an at-sign is treated as a formula the moment the file is opened, so a name pasted from a bulleted list as "- Alice Reviewer" displays as #NAME? and "=Consulting" tries to evaluate. Nothing in the file has changed and the identifier column is never affected, because those are always UUIDs. To see the labels as written, import rather than open: in Excel use Data › From Text/CSV and set the recipient column's type to Text, and in Sheets use File › Import with "Convert text to numbers, dates, and formulas" turned off. The tool deliberately does not insert escaping apostrophes of its own, because the manifest is the record of who got which copy and it should say precisely what you typed.
Why do the identifiers get characters replaced, and why are they cut short?
An identifier is folded to unaccented letters, digits and the characters dot, underscore, hyphen, plus, colon and at-sign, then cut to 120 characters. The alphabet is narrow because the identifier has to survive a round trip through page text: spaces would let pdf.js split the marker into two text runs, square brackets would confuse the scanner's terminator, and characters that depend on the PDF's text encoding come back unreliably. Accented Latin letters are folded to their base letter rather than dropped, so Zoë becomes Zoe and ümlaut becomes umlaut; scripts with no Latin equivalent, such as Chinese, drop out entirely and a label made only of those falls back to a random UUID. The 120-character cut matters more than it looks: an identifier longer than that could be written but not read back, so the field truncates instead and shows you exactly what will be written. Acme Corp / batch 7 becomes Acme_Corp_batch_7. Auto-generated UUIDs are already safe.
Verify found nothing. What does that mean?
Either the file was never fingerprinted here, or the marks have been removed. Common ways they disappear: the document was re-exported or printed to PDF by another application, it was flattened to page images, it went through OCR, someone ran a metadata stripper, or only extracts were copied out rather than the file itself. Verify also cannot read a scanned page as text, so a fingerprinted PDF that was later scanned back in from paper will come back clean. What it does not mean is that the identifier was too unusual: any marker this tool has ever written is readable, whatever its length, and a protected file is reported as protected rather than as clean.
What happens if I fingerprint a file that is already fingerprinted?
The metadata is replaced — the Keywords entry and the custom Fingerprint key end up holding the new identifier only, with any keywords of your own left intact. The corner text is a different matter: it is page content, and the earlier marks cannot be removed, so the new ones are drawn alongside them. Verify will then report both identifiers, the newer one in metadata and on the pages, the older one only on the pages. That is usually a signal you re-marked a copy rather than the original, which is worth catching before you distribute it.
Can it fingerprint a password-protected PDF?
No. An encrypted document cannot be parsed, so Add, Batch and Verify all report the problem rather than work on the file. Remove the password with Unlock PDF first, fingerprint the result, then re-apply protection with Protect PDF if you need it. Two things to expect from that order. Re-encrypting rewrites the file and most encryptors drop the Keywords entry and the custom Fingerprint key, so the copy you hand out will usually be carrying the page-text marks alone — which is still enough to trace it. And because Verify cannot open a protected file either, the way to confirm the marks survived is to unlock a copy with Unlock PDF and verify that copy, not the protected one.
How big can a batch be?
Up to 200 copies, and every copy is a complete PDF held in memory before the ZIP is assembled — so a 20 MB source at 50 copies means roughly a gigabyte of working memory and a very large download. The ZIP is deflated, and because the copies are nearly identical it compresses well, but the peak memory is what will stop you. If a big batch stalls the tab, split it into two runs; the identifiers are random, so nothing collides.
Does any of this leave my computer?
No. The document is read with the File API, marked with pdf-lib, scanned with pdf.js and zipped with JSZip, all inside this tab. There is no upload, no account and no server-side record — which also means nothing here remembers which identifier went to whom. That is what the manifest is for, and it is yours to keep.