pdfformatsdocuments

How a PDF works inside: objects, xref and why it weighs what it weighs

A PDF's internal structure: header, body, xref table, compressed streams and embedded fonts. Understand why some PDFs weigh 100 KB and others 50 MB.

August 25, 2026·8 min read

The PDF has spent over thirty years as the universal document format, and it remains a black box for most: it opens, it displays, it prints. But its internal structure explains almost every practical behavior — why a scanned PDF weighs 50 MB while a native one is 200 KB, why sometimes you can delete a page in seconds and other times it takes minutes, and what "flattening" a form actually means.

A PDF is not a stream: it's a database

Unlike DOCX or HTML (read sequentially), a PDF is a graph of numbered objects with random access:

%PDF-1.7                        ← header with version
1 0 obj ... endobj              ← object 1
2 0 obj << /Type /Page ... >>   ← object 2
...
xref                            ← reference table
trailer
<< /Size 42 /Root 1 0 R >>
startxref
9125
%%EOF

Each object carries number and generation (2 0 obj). The trailer points to the catalog's root object (/Root 1 0 R), which hangs the page tree, resources and content. The xref table stores each object's byte offset inside the file — so a viewer jumps straight to page 340 without reading the previous ones.

This architecture explains two real behaviors: adding pages or annotations to a PDF can be pure append (new objects + incremental xref), which is why editors can save huge changes without rewriting everything.

Pages don't contain text

Classic surprise: a PDF page doesn't "have" letters. It contains a content stream — a mini drawing language (operators) that paints glyphs at coordinates:

BT
/F1 24 Tf
72 720 Td
(Hello world) Tj
ET
q 0 0 1 rg 36 36 re f Q

That means: font F1 at 24pt, move to (72, 720), paint the string "Hello world", then a blue rectangle. Text in a PDF is the result of drawing instructions — from this come familiar phenomena:

  • Copying text sometimes yields absurd characters: if the font uses custom encoding without a /ToUnicode map, the viewer paints correctly but doesn't know the letters.
  • Reading order may not match visual order: operators execute in drawing order, not paragraph order.
  • Extracting text from a scan returns nothing: there's no text stream, just an image — hence OCR.

Why some PDFs weigh so much

The usual culprits, by frequency:

Unrecompressed images: a 300 DPI scanner produces huge TIFF/JPX files embedded as-is. One scanned page = one full photo. Ten pages = tens of MB.

Complete embedded fonts: a proper PDF embeds used fonts. Without subsetting, you drag the entire typeface (megabytes) to use 40 glyphs. With subsetting only present characters travel.

Duplicated objects from incremental edits: each incremental save accumulates old versions inside the file. Heavily edited PDFs grow like snowballs; a clean rewrite ("save as optimized") shrinks them drastically.

Forgotten metadata and attachments: cached thumbnails, application origin data, entire attached files.

Compression inside the PDF

Streams can declare their compression filter:

3 0 obj
<< /Length 1204 /Filter /FlateDecode >>
stream
...data compressed with DEFLATE...
endstream
endobj

FlateDecode (the usual zlib/DEFLATE) is standard for content and metadata. For images, DCTDecode (= internal JPEG) and JPXDecode (JPEG2000); modern PDFs also accept JBIG2 for black and white, brutally efficient on scanned text.

This solves the optimization mystery: shrinking a PDF isn't "compress harder", it's recompressing images to appropriate resolution, subsetting fonts and purging orphaned objects.

Forms and signatures: layers over the graph

An AcroForm is dictionaries with fields (/Fields) referencing widgets placed over pages. "Flattening" a form = painting values as static content and removing interactive fields — that's why a flattened PDF can no longer be edited but guarantees everyone sees the same thing.

Digital signatures go further: a signature dictionary contains the cryptographic hash of the document's bytes up to that point. Any later modification invalidates the chain — it's mathematics, not convention. That's why "editing a signed PDF" breaks validation: exactly what should happen.

Operating on PDFs in the browser

All this structure is manipulable client-side with libraries like pdf-lib or pdf.js: splitting = creating a new document copying page references; merging = the inverse; rotating = modifying /Rotate; numbering = adding operators to the stream. Our PDF toolbox does all of this locally in your browser — your documents never upload to any server — and each operation has its detailed guide: merge, split, compress or extract text.

FAQ

What about PDF/A? It's an ISO profile for long-term archiving: bans fragile features (embedded JS, external font links), mandates metadata and standardized colors. Notarial and public archives usually require it.

Why does my PDF look different on every viewer? If it doesn't embed fonts, each system substitutes its own. Proper PDF = embedded fonts = identical everywhere. That portability is its raison d'être.

Can text be recovered from a scanned PDF? Only via OCR: the scan is an image. Quality depends on original resolution (>300 DPI ideal) and page cleanliness.


Edit, merge, split and compress PDFs with our PDF tools suite, free without uploading anything to the cloud.

Try it without code

PDF Tools

Images → PDF and remove pages.

Open PDF Tools

Built by

Miguel Ángel Colorado Marin (MACM)

Full-Stack Developer · Guadalajara, España

I develop web apps, digital tools and full projects — from design to deployment.

Contact me