PDFMove
How Does Structure Extraction from PDF Work? Tagged PDF and Heading Detection
Guide

How Does Structure Extraction from PDF Work? Tagged PDF and Heading Detection

8 min read

Producing Markdown from a PDF is actually quite a hard inference problem. Because a PDF usually doesn't contain the information "this is a heading" or "this paragraph is read after that one." This article explains what converters do, which clues they use, and why they succeed on some documents and fail on others.

What PDF stores and what it doesn't

A PDF page's content consists of drawing commands:

BT
/F2 18 Tf              % select an 18-point font
72 720 Td              % move to position
(Introduction) Tj      % write "Introduction"
ET
BT
/F1 11 Tf              % select an 11-point font
72 690 Td
(The subject addressed in this study...) Tj
ET

What's in these commands: which letters get drawn, with which font, at which size, at which coordinate.

What isn't: that the word "Introduction" is a heading. That the text following it is a paragraph under that heading. Where the paragraph ends and a new one begins.

A human looking at the page understands all that instantly — because seeing an 18-point bold word alone on a line means "heading." The converter has to make the same inference.

Tagged PDF: the case that needs no inference

A tagged PDF carries the document's semantic structure alongside the page content. There's a structure tree in the file:

Document
├── H1 "Introduction"
│   └── P "The subject addressed in this study..."
├── H2 "Method"
│   ├── P "The research proceeded in these steps..."
│   └── L (list)
│       ├── LI "First step"
│       └── LI "Second step"
└── Table
    ├── TR
    │   ├── TH "Year"
    │   └── TH "Value"
    └── TR ...

That tree is exactly the information Markdown needs. Producing Markdown from a tagged PDF is a matter of direct mapping, not inference:

| PDF tag | Markdown | |---|---| | H1, H2, H3 | #, ##, ### | | P | Paragraph | | L / LI | - list | | Table / TR / TD | Markdown table | | Link | [text](url) | | Figure | ![alt](image) |

The result is dramatically better than with untagged PDFs.

Where does a tagged PDF come from?

  • PDFs produced from Word with the "Document structure tags" option enabled
  • Corporate documents prepared to accessibility requirements
  • Documents conforming to the PDF/UA (Universal Accessibility) standard

Where doesn't it come from?

  • Files produced via "Print to PDF"
  • Most design program output (unless specially configured)
  • Scanned documents
  • Older PDFs

You can see whether your document is tagged in your PDF viewer's document properties window.

The inference process in an untagged PDF

Without tags, the converter does the following in sequence.

1. Gathering the text fragments

PDF stores text in small fragments. Sometimes a word, sometimes a few letters, sometimes a single character can be a separate drawing command — especially in text with adjusted letter spacing.

The converter merges fragments on the same line and close to each other to build words and lines.

The difficulty: finding word boundaries. A space character isn't always written in a PDF; sometimes the cursor is just moved forward. The converter has to decide "there's a space here" by looking at the distance between fragments. If the threshold is set wrong, either words run together or spaces appear in the middle of words.

2. Grouping lines into paragraphs

Do consecutive lines belong to the same paragraph? The clues:

  • Vertical distance: is the gap between lines normal, or larger?
  • First-line indent: a new paragraph may start with an indent.
  • Where the previous line ended: if the line runs to the full page width it's continuing; if it ends early it may be the end of a paragraph.
  • Punctuation: a short line ending with a period is a paragraph-end marker.

3. Determining reading order

This is the hardest step.

In an untagged PDF the text fragments are stored in drawing order, and that order doesn't have to match the visual reading order. A design program may have drawn all the headings first and the body text afterward.

The converter tries to build a sensible order from the fragments' coordinates. On a single-column page that's easy: top to bottom, left to right.

The trouble starts with multi-column layouts. On a two-column page, if you simply sort lines top to bottom, the first line of the left column and the first line of the right column sit side by side and the texts get interleaved:

"The aim of this study the findings obtained show that in the samples examined..."

A meaningless mix. Good converters do column detection: they look at the horizontal distribution of text blocks, find the whitespace corridors, and separate the columns. But that's also a guess and it fails on complex layouts.

4. Heading detection

The converter weighs these clues:

| Clue | Weight | |---|---| | Font size (larger than body) | High | | Bold weight | Medium | | Change of font family | Medium | | Shortness of the line | Medium | | Extra whitespace above/below | Medium | | Numbering pattern (1., 1.1.) | High | | Being written in capitals | Low | | Being at the top of the page | Low |

Then the candidates are grouped into levels: if the document has five distinct heading sizes, the largest becomes H1, the next H2, and so on.

Typical errors:

  • An emphasized sentence in bold is mistaken for a heading.
  • A small-type subheading is mistaken for body text.
  • If different heading styles were used in different sections of the same document, the levels get scrambled.
  • Figure and table captions are mistaken for headings.

5. List detection

Bullets (•, -, ▪) and numbers (1., a), i.) are detected. The indent level determines nested lists.

The problem: in a PDF the bullet is sometimes a separate drawing object (not text), sometimes a special character, and sometimes just visual alignment made with spaces. In that third case detection becomes impossible.

6. Table detection

One of the hardest structures. Two approaches are used:

Line-based: finding the horizontal and vertical lines on the page and building a grid. Works well with ruled tables.

Alignment-based: looking at the vertical alignment of text fragments to guess columns. It's the only way with unruled tables but it's fragile — an ordinary paragraph can sometimes be mistaken for a table.

Even when detected, Markdown's table syntax is limited: merged cells, nested tables and multi-line formatting inside cells can't be expressed.

Headers, footers and noise

Every page has repeating elements at the top and bottom: the document title, the section name, the page number, a copyright notice, a date.

These are part of the page content and the converter can mistake them for content. The result is lines of noise repeating every few paragraphs.

Good converters use a heuristic: text that repeats at the same position across multiple pages is a header/footer. That detection usually works but fails on page numbers (since they're different on every page).

The font encoding problem

In some PDFs text extraction gives strange results: meaningless characters, missing letters, mixed scripts.

The reason is PDF's font encoding mechanism. In a PDF, letters can be stored as glyph numbers inside the font, and there has to be a mapping table (a ToUnicode CMap) giving those numbers' Unicode equivalents.

If that table is missing or broken, the converter can't turn glyph numbers into the right letters. The page looks correct on screen (because the drawing is correct) but text extraction produces meaningless output.

In documents with non-English alphabets this problem shows up especially on language-specific letters.

Why some PDFs convert well and others badly

The decisive factor is how the PDF was produced:

| Source | Conversion quality | Reason | |---|---|---| | Word (tagged) | Excellent | Structural information in the file | | Word (untagged) | Good | Consistent styles, single column | | LaTeX | Good-medium | Consistent but untagged | | Design program (report) | Medium | Untagged, complex layout | | Design program (brochure) | Bad | Multi-column, boxes, free layout | | Scanned + OCR | Weak | Artificial text layer | | Scanned (no OCR) | Impossible | No text |

In summary

Producing Markdown from a PDF is the work of extracting semantic structure from drawing commands. In tagged PDFs that structure is already in the file and the conversion reduces to a direct mapping — the result is nearly flawless. In untagged PDFs the converter has to guess everything from visual clues: grouping text fragments, determining reading order, deriving heading levels from font size, detecting tables from alignment. Those guesses are successful on regular single-column documents and weak on multi-column, design-heavy ones. That's why it's right to treat the conversion as a starting point requiring manual cleanup rather than a finish line.

Frequently Asked Questions

What is a tagged PDF, and how do I tell?

A tagged PDF is one that carries the document's semantic structure alongside the page content: this is a heading, this is a paragraph, this is a table cell, this is the reading order. PDF viewers' document properties window usually has a 'Tagged PDF: Yes/No' line. PDFs produced from Word with the 'document structure tags' option enabled are tagged.

Why is reading order a problem?

Because in an untagged PDF the text fragments are stored in the order they were drawn on the page, and that order doesn't have to match the visual reading order. A design program may have drawn all the headings first and the body text afterward. The converter has to guess a sensible order from the fragments' coordinates, and in multi-column layouts that guess often goes wrong.

What clues does heading detection look at?

Font size is the primary clue: lines noticeably larger than the body text are heading candidates. It also weighs weight, a change of font family, the shortness of the line, the whitespace above and below, the position on the page, and numbering patterns (1., 1.1., 1.1.1.). None of these clues is decisive; together they form a probability estimate.

Why does Markdown come out perfect from some PDFs and badly from others?

The decisive factor is how the PDF was produced. A report produced from Word as a tagged PDF carries structural information in the file and the conversion is almost flawless. A multi-column brochure with boxes coming out of a design program carries no structural information at all, and the converter has to guess everything from visual clues.

Try this out right away with PDF → Markdown.

Try PDF → Markdown