DOCX vs PDF

Same detector, very different inputs. A Word file describes intent; a PDF describes the marks on a page. That single difference explains everything below.

The short version

DOCXPDF
Font per run of textNamed exactlyOften subset-mangled
Paragraph stylesAvailable, with inheritanceDo not exist
IndentationStored as a valueMust be reconstructed from coordinates
Reading orderExplicitInferred from position
Where the text isOne XML partScattered across drawing operations
Detection reliabilityNear-exact when code is formattedGood in one column, variable otherwise

Why DOCX detects so well

A .docx file is a ZIP archive containing XML. The main document part records, for every run of text, which font it uses and which paragraph style it belongs to. When somebody pastes code into Word, one of three things almost always happens: Word applies a monospaced font, the author picks one, or the paste lands in a style such as HTML Preformatted.

Any one of the three is strong enough on its own to settle the question before a single heuristic is consulted. The stylesheet is read too, and basedOn chains are resolved, so a custom style that inherits its font from a code style is still recognised.

This is the reason the DOCX reader is written from scratch rather than delegated to an existing converter. General-purpose libraries are built to extract semantic content and deliberately discard run-level font information as presentational noise. For this tool that discarded metadata is the single most valuable signal available — so the thing most libraries throw away is the thing worth keeping.

How the file is actually read

No ZIP library is involved. The platform's own DecompressionStream handles the deflate streams, the central directory is walked directly, and the XML is scanned with a small tag reader rather than a DOM parser — which is what lets the same reader run unchanged whether it is given a file in a browser or on a server. The result is that a Word file is parsed with no third-party code at all.

Why PDF is harder

A PDF does not contain paragraphs. It contains instructions to place glyphs at coordinates. There is no concept of a line, let alone an indent, and often no reliable concept of which text came first.

Lines are rebuilt from vertical position

Text fragments are grouped by baseline, with a tolerance of half a line height, then sorted left to right. This works well for body text and code alike, and is the standard approach.

Indentation is measured, not read

Leading whitespace is recovered by measuring the distance from the page's leftmost text to the start of the line, then dividing by the median character width across the page. Gaps inside a line are converted back to spaces the same way, which preserves column alignment.

For monospaced code this is accurate, because the divisor is exactly the character cell. For code set in a proportional font it is approximate and an indent level can land one space out. Since Python's meaning depends on indentation, this is the single most consequential PDF limitation.

Monospace detection has to work harder

PDF font names are frequently subsetted into something like ABCDEF+Consolas, and some producers emit no usable name at all. The subset prefix is stripped and the remainder matched against the same name list used for Word files. Where the name is unusable, the run's declared font family is used as a fallback.

Multi-column layouts can interleave

Because lines are ordered by vertical position, a two-column page can produce lines that alternate between columns. A code block that crosses a column break may come back out of order. Single-column documents — which is most technical documentation — are unaffected.

Practical advice

  • If you have both, use the DOCX. It carries strictly more information and detection is materially better.
  • If the PDF was generated from Word or LaTeX, it will work well. The text layer is clean and usually single-column.
  • If the PDF came from a scanner, it will not work at all. There is no text to read; see the limitations page.
  • If indentation matters and the result looks wrong, the DOCX original will fix it, because indentation there is a stored value rather than a measurement.

Writing the document back out

Both formats are offered whichever one you started from, but they are not the same operation, and the difference matters.

You uploadYou downloadWhat happens
.docx.docxEdits your file. Non-code paragraphs are never rewritten.
.pdf.pdfEdits your file. Code regions are painted over; the rest of the page is the original.
.docx.pdfRebuilds, carrying the formatting across.
.pdf.docxRebuilds, carrying the formatting across.

What a conversion carries across

A rebuild is not a plain-text dump. Both parsers keep the formatting they can see, and the generators reproduce it:

  • Page size and margins — taken from the Word section properties or the PDF page box, so a Letter document stays Letter.
  • Point size per run — an 18 pt heading stays 18 pt.
  • Bold and italic — including several runs inside one sentence, so emphasis mid-paragraph survives.
  • Typeface class — serif, sans and monospace are kept apart and mapped to the closest available face.
  • Text colour from Word, including coloured headings.
  • Indentation and alignment — left, centred, right, and paragraph indents.
  • Line spacing — from a PDF, the actual measured baseline-to-baseline distance of each line.

What it still cannot carry

  • Images are not extracted, so they do not appear in a rebuild.
  • Tables arrive as their text, not as a table.
  • The exact typeface. A PDF can only be written with fonts that are embedded in it; the standard set is Helvetica, Times and Courier. A document in Calibri comes out in Helvetica — metrically close, visually a shade different. Shipping the real font file is not something a browser tool can do.
  • Headers, footers and footnotes live outside the document body and are not read.

So a conversion of a text-and-code document lands very close to the original. A document built around images, tables or a heavily branded template will not. Use the matching format when fidelity has to be exact — the tool states which of the two you are about to get before you press the button.

How the same-format paths keep their promise

DOCX: the untouched parts are never rewritten

The exported Word file is the original archive with a single part modified. Every other entry — styles, numbering, relationships, content types, embedded images — is copied across still compressed, reusing its original checksum. Those bytes are never decoded, so they cannot be altered.

Inside word/document.xml, only the exact character ranges of the paragraphs detected as code are replaced. Prose paragraphs are not regenerated, not re-serialised, not normalised — the new XML is spliced in around them. So the font, size, spacing, indentation, colour and style of your ordinary text survive because they are literally the same characters as before, not because the tool reproduced them accurately.

Each listing is rebuilt as ordinary shaded paragraphs, filled #1E2433, with one coloured run per token. The characters are unchanged; only colour, font and shading are added.

Paragraphs, deliberately, and not a table. A table would give an unbroken background for free, but it makes the listing structurally a table: you cannot edit it as ordinary text, and stripping the highlight leaves the cell shading behind. The pale stripes that shaded paragraphs are prone to — where a paragraph's fill stops at its own text box and the page shows through the leading — are a line-height problem, not a reason to reach for a table. Pinning an exact line rule makes consecutive shaded boxes meet.

Line numbers are optional. With the Line numbers switch off they are not written at all, so selecting the block gives you clean code; with it on they are part of the line. The block carries a little padding at the top, bottom and left, and sits flush at the right.

PDF: the code regions are painted over

A PDF cannot be edited the same way. Its text is a sequence of drawing instructions, not a document tree, so there is no "paragraph" to swap out. Instead the original pages are loaded and left entirely intact, and new drawing operations are appended: an opaque Dark+ panel over the area each code block occupies, then the same lines redrawn on top in colour.

Everything else on the page — prose, headings, tables, images, page size, margins, metadata — is the original object, untouched.

The panel spans the page's whole text column rather than only the width the listing occupied, so a block that was indented on the page still reads as a deliberate pane instead of a stub floating mid-page. It also stretches to cover any line that ran past the margin in the original, because a panel sized to the column would leave the tail of that line visible beside it.

Type is fitted to the column. The code face is whichever font you picked, embedded into the file so it travels with it; where that is not possible it falls back to Courier, which is wider than most faces a document will have used. Either way the size is reduced until the longest line fits, using the font's own measured character width rather than an assumed one — Courier advances 0.60 em per glyph and Consolas 0.55, and guessing puts the line numbers in the wrong place. Anything still too wide at the minimum readable size is clipped at the panel edge rather than allowed to run off the page.

One honest caveat. Because this paints over rather than replaces, the original code text is still present in the file's text layer underneath the panel, even though it is no longer visible. If you need the old text genuinely gone rather than merely hidden, export the .docx instead, where the runs are actually replaced.

What this costs you in page weight

The DOCX reader is a few kilobytes and always present. The PDF engine is substantially larger and is only fetched when you actually open a PDF — opening the site, or using it on Word files, never downloads it. That keeps the landing page fast for everyone regardless of which format they came for.

Read next

How it works

What happens to your document between dropping it in and getting it back.