How a PDF finds its own pages
A PDF is an object graph indexed by a table at the end of the file. That design is why Acrobat can silently repair damage that would destroy any other format.
Open a PDF in a hex editor and it looks like prose interrupted by binary. There is a header, a pile of numbered objects, and then, right at the end, the part that makes the whole thing work.
Objects and indirect references
A PDF is not a stream to be read front to back. It is a set of numbered objects: a page is an object, a font is an object, the compressed bytes of a paragraph are an object. They reference each other by number, so the file is an object graph rather than a sequence.
That raises an obvious question. If object 47 references object 213, how does the reader find object 213 among several megabytes of file?
The cross-reference table
It looks up the byte offset in the cross-reference table, the xref. Each
entry records where an object starts, as a ten-digit byte offset, plus a
generation number and a flag for whether the slot is in use.
The table sits near the end of the file, followed by a trailer dictionary
naming the document catalog, and then the crucial line:
startxref
116942
%%EOF
startxref is the byte offset of the xref itself. A reader opens a PDF by
seeking to the end, reading startxref, jumping backwards to the table, and
only then loading the pages you asked for. It is why a 400-page PDF can display
page 300 without parsing the first 299.
Since PDF 1.5 the same information can be stored as a compressed cross-reference stream instead of a plain table, and a single file may carry both for backward compatibility. The mechanism is identical; only the encoding differs.
Incremental updates
Annotate a PDF and the editor does not usually rewrite it. It appends the
changed objects, appends a new xref covering just those, and points the new
trailer back at the previous table with /Prev. A file that has been edited
five times may contain five xref sections chained together, and the reader
walks the chain, with later entries winning.
This is why PDFs grow when you edit them, and why deleted content sometimes still sits in the file, reachable by anyone willing to read the earlier revisions.
Why Acrobat can repair a damaged PDF
Now the useful part. If the xref is wrong, the situation is not hopeless, because the objects themselves are still labelled. Every one begins with a line like:
213 0 obj
So a reader that cannot trust the index can scan the whole file for that pattern, record where each object actually starts, synthesise a fresh table from what it found, and carry on. That is essentially what Acrobat does when it reports that it repaired a document, and what libraries such as qpdf do deliberately.
The consequence for anyone trying to produce a genuinely broken PDF is significant: destroying the xref alone achieves nothing. The reader rebuilds it in milliseconds and never tells the user anything interesting happened. This is the same lesson that flipping random bytes in a DOCX teaches about ZIP containers, arriving from a completely different direction.
To actually break a PDF you have to remove every route back:
- the
%PDF-header, so the file is not identified as a PDF at all - every
xrefsection and everystartxrefoffset - the
trailerdictionaries, including the ones from earlier revisions - the
N G objmarkers themselves, so the rescan finds nothing to index - the object streams, so even a hand-built table points at unusable bytes
That full sequence is what the PDF corrupter applies, and it is why the result gets “the file is damaged and could not be repaired” rather than a silent rebuild. If you want to see the difference for yourself, produce a broken PDF at Light level and then at Standard, and open both.
Linearization, briefly
One more structure worth knowing. A linearized or “fast web view” PDF puts a special first-page section and a second xref at the front of the file, so a viewer streaming over a slow connection can render page one before the rest arrives. It means some PDFs have index data at both ends, which occasionally surprises people writing parsers.
Why this matters beyond corruption
The xref is a good mental model for a pattern that shows up everywhere. ZIP has
a central directory, MP4 has a moov atom, and each of them is an index whose
loss matters more than any amount of damage to the payload. Formats that keep
an index are fast and seekable. They are also exactly as fragile as that index,
unless the reader is willing to scan and rebuild, which is precisely the
trade-off PDF made.
The video version of the same decision, and what happens when the index sits at the wrong end of the file, is in why a corrupted video stops after two seconds. The identifying bytes that let any of this be recognised in the first place are covered in magic bytes, and why a file extension is not a file type.