A PDF carries its own paperwork — a revision chain, two sets of metadata, a producer string and a pair of identifiers. These five families read that paperwork and check it against itself. None of them looks at the page; they ask what the file says about how it came to exist, and whether those statements are consistent.
Part of the field guide — five of the eighteen families the engine reports.
Signals, not verdicts. Every finding here is a structural fact about a file. "This document was modified after generation" is true or false about the bytes; "this document is fraudulent" is a judgement about a person, and Tamperlens does not make it. The API returns no boolean verdict field, by design.
incremental-updates
medium high- What it detects
-
That the file contains more than one revision — bytes were appended after
the document was first written out and terminated with
%%EOF. PDF's incremental-update mechanism appends new objects, a new cross-reference section and a new trailer rather than rewriting the file, so earlier states of the document are still physically present. The parser walks the/Prevchain backwards and works out which object numbers each revision introduced and which it overwrote. - The escalation is about what changed, not how many times. If a later revision replaces an object number that already existed in an earlier revision, and that object carries page, content-stream or image data, then the rendered appearance of the document changed after generation. Annotation and metadata objects do not escalate.
- Evidence returned
-
revisions,updatesAfterCreation,eofOffsets,startxrefValues,revisionChainBroken, a per-revision breakdown (changedPerRevision: which objects each revision wrote and which of those it overwrote, with the kind of each), andcontentObjectsOverwritten. - Benign causes
- Extremely common, and this is the family most likely to fire on an honest file. Applying a digital signature is an incremental update — that is how signing preserves the signed bytes. So is filling in an AcroForm field, adding an annotation, a comment or a sticky note, applying a redaction in some tools, and certain linearisation and optimisation passes. Document-management systems routinely add a revision on ingest. A statement that a customer opened, signed and re-saved is not a forgery.
-
The converse trap: a single revision does not mean the file
was never edited. A tool that rewrites the whole document flattens the
history, so this family stays silent while
metadata-mismatch,producer-fingerprintorfont-anomaliescarry the finding instead. - Severity logic
-
Silent at one revision. medium for any additional revision.
high when at least one overwritten object is of kind
page,contentorimage.
metadata-mismatch
medium high- What it detects
- Disagreement between the two independent metadata stores a PDF can carry: the trailer's Info dictionary and an embedded XMP packet. Four fields are compared — producer, creator/creator-tool, creation date and modification date. A single tool writing a file once fills both consistently; consumer editors very often update one and leave the other stale.
-
Comparison is deliberately forgiving so that version drift is not a
finding. Tool strings are normalised to lowercase alphanumerics and count as
agreeing when either is a substring of the other, so
iText 7.2.5andiTextagree. Timestamps agree within one minute, because the two stores round differently. A field is skipped entirely when it is absent from either store, and the family does not run at all unless both stores are present. - Evidence returned
-
A
mismatchesarray (field, Info value, XMP value), both raw producer/creator strings from both stores, both date pairs,infoEditorTool/xmpEditorTool(which known consumer editor each store names, if any), andeditorRevealedByMismatch. - Benign causes
- Multi-stage publishing pipelines produce this pattern legitimately and constantly: a design application writes XMP, a distiller writes the Info dictionary, a post-processor updates one of them. Some server-side generators write XMP once and never refresh it. macOS Quartz and several print-to-PDF drivers are known to leave the stores divergent. A plain divergence is a question, not an accusation.
- Severity logic
- medium for any divergence. It escalates to high only in one specific case: the divergence is on a producer or creator field and the two stores name different known consumer editors — including the case where one names an editor and the other names none. In that situation the mismatch is the only reason the editing tool is visible at all, which is materially different from two server libraries disagreeing.
date-anomalies
low medium- What it detects
-
Timestamps that a correctly running generator could not have produced. Four
distinct findings, evaluated across all four available date fields (Info
/CreationDateand/ModDate, XMPxmp:CreateDateandxmp:ModifyDate): -
mod-before-creation— the modification timestamp precedes the creation timestamp within the same store (the two stores are compared as separate pairs, so cross-store skew is handled bymetadata-mismatchinstead).future-date— a timestamp more than one day in the future.impossible-timezone— a declared UTC offset beyond ±14:00, which corresponds to no real timezone.unparseable-date— a string that follows neither the PDFD:YYYYMMDDHHmmSSOHH'mm'syntax nor ISO-8601. - Evidence returned
-
A
findingsarray — each with a kind, the field or field pair involved, the offending value and a one-line note — plus the four raw date strings exactly as they appear in the file. - Benign causes
- Malformed dates are largely a generator-quality issue: plenty of niche and legacy producers emit dates that do not parse, and that is why a report containing only unparseable dates is downgraded rather than treated as manipulation. Future dates can come from a genuinely wrong system clock, which is why the threshold is a full day rather than a second. Mod-before-creation is the hardest to explain away benignly, but it does occur with tools that copy a creation date forward from a source document while writing a fresh modification date.
- Severity logic
-
low when every finding is
unparseable-date. medium otherwise. The title reflects the strongest finding: a mod-before-creation pair is named explicitly, malformed-only reports say so, everything else reports internal inconsistency.
producer-fingerprint
info low medium- What it detects
-
A tool a human drove appearing in the document's production chain. Four
source fields are checked — Info
/Producer, Info/Creator,pdf:Producerandxmp:CreatorTool— against a curated fingerprint list in five categories: online editors and converters (iLovePDF, Sejda, Smallpdf, PDFescape, PDF24, PDFfiller, DocHub, Soda PDF, PDF2Go, Convertio, Zamzar and others), desktop PDF editors (PDF-XChange, Foxit, Nitro, PDFelement, Wondershare, interactive Acrobat Pro), OCR post-processors (ABBYY, Readiris), image and design editors (Photoshop, Illustrator, GIMP, Inkscape, Canva, Figma, Affinity) and office/print re-save pipelines (LibreOffice, Word, Microsoft Print to PDF, Quartz PDFContext, CutePDF, doPDF, PrimoPDF). - Each fingerprint carries an origin, and the origin decides everything: an authoring tool (Word, Canva, Google Docs, a print driver, an OCR pass) is where a document's existence begins, so naming it says nothing about whether anything changed afterwards. A pdf-editor (iLovePDF, Sejda, PDF-XChange, Acrobat Pro's interactive editor) takes an existing PDF as input and writes a new one — a claim about the file's history rather than its authorship. Matching is case-insensitive on the alphanumeric-normalised string, so punctuation and version numbers do not defeat it.
- A separate branch handles the opposite case: no producing tool declared in either store at all.
- Evidence returned
-
matches(which field, the raw value, the matched tool label, its category and its origin), the deduplicatedtoolsandeditorToolslists, the resolvedorigin, all four raw strings,revisions, andfullPageImagePages— the page list is evidence only and no longer moves the severity. - Benign causes
- Enormous, and this family needs local calibration more than any other. Legitimate reasons a consumer tool appears: the customer downloaded the statement and re-saved it in Preview or Acrobat to combine pages; they used an online tool to merge two statements into one upload, or to compress a file under an upload limit; they printed to PDF from online banking because no download button existed; the issuer itself uses LibreOffice or a print driver in its own pipeline — small institutions genuinely do. ABBYY and other OCR tools appear routinely and legitimately in scan workflows.
- The absent-producer case is weaker still: metadata stripping is a normal privacy-hygiene step, and some minimal generators simply never write the field. It removes a corroborating fact rather than supplying one.
- Severity logic
- No match, and a producer is declared: silent. low when no producing tool is declared anywhere. For a match, two facts and nothing else: the tool's origin, and whether the file has more than one revision. An authoring tool is info on a single-revision file and low on a re-saved one; a pdf-editor is low on a single-revision file and medium on a re-saved one. This family can no longer reach high: a producer string is a self-report by the tool that wrote the file — a forger can set it to anything, and an honest document sets it to Word. Full-page imagery no longer escalates it either; a full-page raster marks a document that is a picture (a Canva design, a scan), not a document that was edited.
id-inconsistency
info medium- What it detects
-
Divergence in the trailer's
/IDarray. The PDF specification assigns the two elements different jobs: the first is a permanent identifier set when the document is created and must never change; the second is rewritten by the producing application on every save. In a conforming writer their divergence is the format's own machine-readable record that the file was saved again after creation — but plenty of real writers simply generate both elements fresh on first output, so divergence alone is not that record. Tamperlens reads the/IDfrom the newest trailer that carries one, and reports every trailer's/IDas evidence. - Evidence returned
-
idOriginalandidCurrentas hex,trailerCount,revisions, andallTrailerIdsso you can see the identifier evolve across revisions. - Benign causes
-
Anything that legitimately re-saves a document updates the second element —
signing, form filling, annotation. The signal says "saved again", nothing
more. Two additional weaknesses worth knowing: some minimal generators omit
/IDentirely, and a tool that rewrites the whole file can set both elements to the same fresh value, erasing the trace completely. A matching pair is therefore not evidence of an untouched document. - Severity logic
-
Identical pair: silent. Divergent pair: medium only when
the file's own structure agrees it was written more than once. On a
single-revision file the divergence is reported at info —
a file written once cannot have been "saved again", and measured against
uncurated document populations most divergent pairs sit on exactly such
files. No
/IDarray at all: info — its absence removes the check rather than indicating a change. info findings contribute nothing to the score and are reported so the observation stays auditable.
See the report on your own file
The free checker runs every family on this page and renders the full evidence — no account, nothing stored. To run it in your own pipeline, see the API quickstart or create an account for a key with 50 free documents a month.
Tamperlens reports risk signals, not authenticity verdicts. Signals can have benign causes; combine them with your own decision logic.
The rest of the guide
- What a PDF's pages give away Six families.
- What a PDF signature actually covers Three families.
- When a document's own numbers disagree Four families.
- All eighteen families The index, the severity vocabulary and how signals become a score.