pdfmdtools.com

PDF to Markdown

Convert a PDF with a text layer to Markdown in your browser, then review and download the result without uploading your file.

Browser-based conversion; no uploads, login, usage quotas, or added watermarks.

Local files stay local No AI conversion No signup No watermark
PDF → Markdown

Start with your PDF

Choose a file to preview its pages and extract Markdown.

Know before you convert

  • Text extraction requires a PDF text layer; this tool does not run OCR.
  • Scanned pages, complex tables, and columns need a careful review.
  • Embedded figures and photos are not exported as Markdown images.

Output

How to use this converter

Choose, review and download

  1. Choose your PDFChoose or drop one PDF into the tool above.
  2. Review the source pagesReview the page previews. Select the pages you need and inspect any no-text-layer warning.
  3. Compare and downloadCompare the Markdown with the source, then choose Copy or Download .md.

How to Convert a PDF to Markdown — and What Actually Breaks

Last updated: 9 October 2026

Start with a PDF that has selectable text. This homepage extracts that text locally and builds Markdown you can review. Columns, tables, images and scanned pages need the specific checks below; a readable result is not proof of a complete conversion.

Everything below is demonstrated with actual output from the converter on this site, run on four test documents on 16 September 2026. Nothing here is a summary of someone else's benchmark.

Why "converting a PDF" is really two different jobs

A PDF does not store a document the way a Word file does. It stores a list of instructions: put this glyph at these coordinates, draw a line here, place this image there. Tagged PDFs can also carry logical structure such as headings and tables. This converter groups text items by position rather than reading that structure tree.

That means a converter has to do two separate things, and they fail independently:

  1. Extract the text — read the glyphs and their positions. This is mechanical and mostly reliable.
  2. Recover the structure — decide which line is a heading, which lines belong together, what order to read them in, and where a table starts and ends. This converter infers those relationships from text positions; check them against the source.

Most disappointing conversions are not extraction failures. The text was all there. The structure was wrong, which makes the output look complete while being unusable.

Check the source before converting

Open the PDF and try to select a sentence with your mouse or finger. Then look at the shape of the page.

What you seeWhat will happen
Text selects normally, one columnA suitable starting point; review the extracted words, heading levels and lists.
Text selects normally, two or more columnsCheck for interleaved columns; this tool does not reconstruct column reading order.
Text selects normally, contains tablesCheck row and column relationships; this tool does not write reconstructed Markdown tables.
Text will not select, or selects as one big blockInspect the text layer: a scan needs OCR, while other selection or encoding problems need their own checks.
Selects fine but the page is mostly images, charts and formulasText-layer captions may appear, but this tool does not export the figures or photos.

For a complex document, treat this output as a draft and compare it with the original. The fixtures below show specific failures of the recorded converter, not a prediction about every file or tool.

Cleaning up the output afterwards

Whatever route you take, the raw Markdown benefits from a pass like this before you use it for anything:

  • Rejoin broken paragraphs. A paragraph split across several lines in the PDF often stays split in the Markdown. Merge lines that clearly continue a sentence.
  • Delete running headers and footers. Page numbers, document titles and confidentiality notices repeat on every page and are noise in the output.
  • Check the heading levels are consistent. Auto-detected headings sometimes produce an H3 where you expected an H2. Normalise them.
  • Rebuild tables as Markdown tables rather than leaving flattened rows.
  • Look for interleaved lines if the source had columns — this is the error most likely to slip through unnoticed.
  • Check the very beginning and very end. Cover pages, tables of contents and appendices often convert into a mess that is easier to delete than repair.

If the output is going into a search index or a retrieval system rather than being read by a person, this cleanup step is not optional. Bad structure produces bad chunks, and can distort the context available to a downstream system. The conversion test does not measure an AI system's answer accuracy.

Which kind of tool to reach for

The right choice follows from the table above rather than from a feature list:

  • Simple digital PDFs. A browser-based converter is enough, and it has the advantage that your document never leaves your machine. That is the case this homepage tool is built for — choose a PDF above.
  • Multi-column academic or report PDFs. Check whether a layout-aware workflow preserves your required reading order. Local or server-side processing depends on the implementation; inspect its file handling separately.
  • Scans and photographs. You need an OCR pipeline, and you should budget time for proofreading.
  • One-off documents where accuracy matters more than speed. Select the text in your PDF reader and paste it. It is unglamorous, it is slower, and should still be compared with the original page.
Supported formats and limits

Text-layer conversion

To convert PDF to Markdown for notes or a draft, start with selectable text and a straightforward reading order. The words can survive while paragraph boundaries or heading levels change: this tool groups positioned text into lines and estimates headings from text size, rather than recovering the author's original document styles.

Use the page previews and selected-page output to check the passages you need before reusing them. Our choice is a free, local text-layer conversion that you can inspect. It is not a promise to reproduce every PDF perfectly, and it does not export embedded figures, highlights or comments. Use this PDF to Markdown converter to review the extracted text and download an MD file.

Table conversion limits

A PDF to Markdown converter can return readable cell values while losing the relationship between a header and its rows. In this tool, the loss happens when text items are grouped by position into lines: table cells become line text, not a reconstructed Markdown table, and adjacent columns can be joined in the wrong reading order.

Check which value belongs to which heading in the source PDF before using the result. Repeating the conversion does not add a table-reconstruction step to this parser. For a document whose meaning depends on merged cells, column associations or complex layout, keep the source beside the Markdown and review the structure manually.

Scanned PDF limits

A scan can display a clear page while supplying only an image to the text extractor. The missing words are lost at the input step: without a readable text layer, this tool has no characters to turn into Markdown. It reports pages without text for review; it does not recognize the words in their pixels.

Our homepage does not run OCR. Add and proofread a text layer with an OCR workflow before trying a scan here, or use the page preview to identify the scanned pages in a mixed document. An apparently successful conversion of other pages does not mean the scanned content was included.

Local conversion limits

If no upload is a hard requirement, a local PDF to MD converter lets you select a file and download the result without sending that document to a conversion server. This homepage uses PDF.js in your browser and does not call a model API. Repeated conversions here do not consume a model service's tokens.

That choice avoids a server-upload or model-assisted conversion step; it does not recover missing text, table structure or annotation data. We do not use OCR or an AI layout-recovery service on this homepage. Local handling is the privacy boundary, while the previews and output review help you decide whether the extracted text is sufficient for your task.

PDF structure limits

A PDF can describe where glyphs, lines and images should appear without describing a paragraph, a table or the intended reading sequence. Tagged PDFs can also contain logical reading order and table relationships, so it would be wrong to say that no PDF has them. When usable structure is absent or a conversion path does not use it, a converter has to infer meaning from page positions.

This explains why a page can look correct while its Markdown loses relationships: preserving appearance and recovering structure are different jobs. It is not evidence that every failure is a bug, nor a reason to rule bugs out. No converter, including ours, can promise correct results for every PDF. Our trade-off is inspectable, local text extraction; complex structure and scans still need a separate review or workflow.

Text extraction is not the same thing as layout recovery. If a document has two columns of text sitting on the same horizontal line, those lines come out joined together. Table cells get flattened into one line per row. And anything that is a picture of text — a scan, a photo, a screenshot saved as PDF — has nothing to extract at all.

Use the following evidence sections on this page to check the specific limitation. The Guides directory lists the other tools and their tests:

If you need plain text from a scan rather than Markdown, see PDF to Text with local OCR. If you need editable Word output, see PDF to Word (DOCX). These are separate outputs, not OCR modes of this homepage tool.

Reading order evidence

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

The test that answers the question

The corpus contains 14a-row-major.pdf and 14b-column-major.pdf. They have the same page size, font, coordinates and column strings. They are visually indistinguishable when opened side by side. The difference is the order in which their text operators appear in the PDF content stream.

The recorded converter produced these body lines:

InputObserved Markdown line
14a-row-major.pdfLeft column, line one. Right column, line one.
14b-column-major.pdfLeft column, line one.Right column, line one.

The second line has no space between one. and Right. It reads like a typo, which makes it more dangerous than an obvious error: a reader can miss that two columns have been fused together.

Why the converter sees a difference

A PDF is not a document model in the way a Markdown file is. It is a set of drawing instructions. Text can be placed at coordinates that make it look like a normal reading order, while the content stream records those text runs in another order.

In this pair, PDF.js emits the spacing between two consecutive text runs as its own synthetic text item in one case and omits it in the other. The page looks the same, but the extracted items are not the same sequence. The converter has to reconstruct reading order from those items; it cannot recover information that the file does not express consistently.

That is why “the PDF looks fine” is not a sufficient test. A visual inspection checks the rendered page. A conversion check checks the text items and the spacing decisions made while rebuilding a reading order.

Two-Column PDF to Markdown: Why the Output Comes Out Scrambled

Last updated: 17 September 2026

The short answer: in the recorded column fixtures, the converter joined text sharing a baseline instead of recovering a column-by-column reading order. Both the PDF text items and this converter's grouping logic contributed to the result. The outputs below describe those named inputs, not every PDF or converter.

There is also a second, nastier version of the same failure: sometimes the two columns are joined together with no space between them at all, so the output reads line three.Right column, line one. That one is harder to spot, and it depends on something inside the PDF that you cannot see by looking at the page. It is explained below.

The raw output examples in this section were recorded from the converter on this site, run on 17 September 2026 against the named fixtures. The historical raw outputs are quoted verbatim; explanations also refer to the current code where stated.

What actually happens

Take a page with two columns of four lines each, where the left and right columns sit on the same four baselines — a shared-baseline layout represented by the named fixture.

Every word is present and every word is in the wrong place. The correct reading order is the whole left column, then the whole right column. What came out alternates.

The cause is in how text is grouped. The converter walks the text items on the page and puts them into the same line whenever their vertical position is within 3 points of each other, then sorts those items left to right and joins them. Two columns that share a baseline are, by those rules, one line. Nothing in the coordinates says "these two runs are separate columns" — the geometry genuinely looks identical to a wide single line.

The version that is much harder to catch

Here is the same layout with one difference: the columns are slightly offset vertically, so the right column starts lower than the left and they only overlap for three lines. This is what you get in real documents whenever a section heading, a figure or a pull quote pushes one column down.

Look closely at line three: Left column, line three.Right column, line one. There is no space between the two runs. The sentence has been welded shut.

This matters more than it looks. Interleaved text with spaces is at least obviously wrong when you read it — two sentences sitting side by side is a pattern a human notices. Text welded together with no separator is the kind of thing that survives a skim, gets pasted into a document, and then fails a search or an automated check much later.

Why the space is sometimes there and sometimes not

This part is not obvious, and it is the reason the same-looking page can produce two different kinds of broken output.

I built two PDFs with identical geometry: the same four baselines, the same x positions, the same font, the same text. The only thing that differs is the order in which the text was written into the PDF's content stream — one written row by row (left line one, right line one, left line two, right line two), the other written column by column (all four left lines, then all four right lines).

Dumping the text items shows exactly what the difference is. In the row-by-row file, the extractor emits an explicit space item between the two columns:

'Left column, line one.'   x=50   y=700
' '                        x=164  y=700
'Right column, line one.'  x=320  y=700

In the column-by-column file, that space item is simply not there:

'Left column, line one.'   x=50   y=700
'Right column, line one.'  x=320  y=700

The consequence in the Markdown:

Row-by-row file:
  Left column, line one. Right column, line one.

Column-by-column file:
  Left column, line one.Right column, line one.

The two source files look the same. In this recorded conversion, their text-operator order affected whether a space survived. That result depends on both the PDF and the extraction logic; it does not establish how another converter will behave.

Three columns are worse

A three-column layout — the standard for journal papers and many product brochures — merges all three columns into a single line per baseline.

# Three Column Layout

Alpha one. Beta one. Gamma one.
Alpha two. Beta two. Gamma two.
Alpha three. Beta three. Gamma three.

The reading order is now wrong in two directions at once, and there are three times as many join points where a missing space can weld two sentences together.

A mixed page, which is the real worst case

Most documents people actually need converted are not purely one layout. A page with a heading, a two-column paragraph and a table underneath produces this:

# Mixed Layout Page

Left paragraph, line one. Right paragraph, line one.
Left paragraph, line two. Right paragraph, line two.

### Summary Table

Region Revenue Growth
North 1,200 8%
South 980 -2%
East 1,540 12%
Closing paragraph under the table.

Three separate things went wrong on one page: the two-column paragraph is interleaved, the table has lost its column structure so you can no longer tell which number belongs to which heading, and the closing paragraph has been pulled up against the last table row. The heading levels are also inconsistent — the page title is an H1, the table title is an H3, and nothing in the source document explains why.

Inspect the source before converting

Open the PDF, select a sentence in the left column and inspect what the reader selects. Treat this as a source check, then compare the actual Markdown: reader selection does not establish this converter's output order.

What the selection doesWhat it means
The selection stays inside the left column and stops at the column edgeThe reader selected one column; check the converted Markdown separately for interleaving and spaces.
The selection jumps across to the right column on the same visual lineThe reader selected across columns. Inspect the extracted order; selection alone does not predict spacing in this converter.
You can select an entire column top to bottom as one blockThe reader can select one column, but this does not prove that this converter will preserve its reading order.
Nothing selects, or the whole page selects at onceCheck for a usable text layer and review the scanned-page limits; selection behaviour alone is not proof.

A PDF reader's selection is a useful inspection aid, not a test of this converter. Tagged PDFs may contain logical structure, but the current Markdown writer groups text items by position and does not read that structure tree.

What to do about it

There is no trick that makes a simple text extractor reorder columns. It is a layout analysis problem, and a converter that does not do layout analysis cannot solve it by trying harder. So the realistic options are:

  • Repair against the source. In the shown outputs, one line can contain both a left-column and a right-column passage. Alternating odd and even lines will not separate them. Use the original page to identify the boundary before rebuilding each column.
  • Convert one column at a time. Crop the PDF into single-column strips — most PDF readers can export a page region — and convert each strip separately. This gives correct reading order and is the most reliable manual approach. It is worth doing for a document you will reuse.
  • Use a layout-aware workflow when needed. Check its output and file-handling policy directly. Layout analysis is not an implemented step in this homepage tool; it is not inherently limited to server-side processing.
  • Select and paste. For a single page, selecting the text in your PDF reader and pasting it into an editor often gives you the correct reading order, because the reader knows about columns. It is unglamorous and it is frequently the most accurate option for one page.

If the output is going into a search index or a language model

Interleaved text is not just ugly, it is actively harmful. A retrieval system splits your document into chunks and matches questions against those chunks. A chunk built from interleaved columns contains two unrelated statements spliced together, and it will be retrieved for questions about either of them while answering neither. The model then writes a confident answer from corrupted source text, and nothing in the pipeline flags it.

If you are converting documents for that purpose, the column check is not optional and it is not something you can do after the fact. Check the output before it goes in.

Test 2: two columns — this is where it falls apart

The same amount of text, laid out in two columns, with the left and right columns sitting on the same horizontal lines. This fixture tests shared baselines; it does not represent every multi-column document.

## Two Column Layout

Left column, line one. Right column, line one.
Left column, line two. Right column, line two.
Left column, line three. Right column, line three.
Left column, line four. Right column, line four.

Every word is present and every word is in the wrong place. The correct reading order is the entire left column, then the entire right column. What came out interleaves them, producing sentences that look plausible and are nonsense.

This is the most dangerous failure mode in the whole subject, precisely because it is quiet. There is no error message, no missing text, and nothing that looks broken. If you skim the output you will believe it worked. If you feed it into a search index, a knowledge base or a language model, you are feeding it corrupted content and you will not find out until something downstream gives a strange answer.

In this implementation, grouping text by vertical position joins columns that share a baseline. Recovering the intended order would require additional layout logic. The recorded result does not rule out implementation bugs or establish a limit of every PDF converter.

This failure has a second form that is harder to catch, where the columns are joined with no space at all between them, and it depends on something inside the PDF that you cannot see by looking at the page. Reading order evidence on this page shows both forms and how to tell which one you have.

Table and column evidence

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

The table and column cases

InputWhat it isolatesMeasured Markdown result
02-two-column-shared-baseline.pdfTwo columns with the same four baselines.Each line is emitted as a left-column sentence followed by the matching right-column sentence.
03-table.pdfFour rows of three cells sharing baselines.The cells become a flat sequence: Item Qty Unit price, followed by the values. No Markdown table is present.
05-two-column-offset.pdfTwo columns whose vertical ranges overlap only partly.Some lines remain separate, while overlapping lines are joined, including Left column, line three.Right column, line one.
06-three-column.pdfThree columns sharing three baselines.Each row is emitted in Alpha, Beta, Gamma order, which is readable but still not a Markdown table or column structure.
12-mixed-worst-case.pdfA title, two-column paragraph, and table on one page.The output keeps headings and text, but the paragraph and table are represented as ordinary lines rather than their visual layout.

What the raw output actually says

The measured output for 03-table.pdf is:

## Price List

Item Qty Unit price
Widget 10 1.50
Gadget 5 9.99
Bracket 22 0.75

This is not an empty conversion. It contains the words and values, but it does not preserve the cell relationships as Markdown table syntax. A downstream reader has to infer which value belongs to which column.

The offset-column case shows a different failure shape:

## Offset Two Column Layout

Left column, line one.
Left column, line two.
Left column, line three.Right column, line one.
Left column, line four.Right column, line two.
Left column, line five.Right column, line three.

The joined full stops are easy to miss in a long document. They are a sign that visual placement and extracted reading order are separate problems.

Why tables and columns are not the same test

A PDF page stores drawing instructions, text operators, positions, and streams. It does not hand a converter a Markdown table model or a column-order label. A converter therefore has to infer relationships from coordinates and text runs.

A shared-baseline table tests whether cells on the same row remain recognisable as a grid. A two-column page tests reading order and spacing. An offset-column page tests what happens when the vertical ranges overlap only for part of the page. These should be tested separately because a converter can produce a readable result for one and a misleading result for another.

Local parsing is not layout recovery

FixtureWhat it isolatesObserved result
02-two-column-shared-baseline.pdfTwo columns whose lines share baselines.Left and right text are emitted on the same lines with a space between them.
03-table.pdfA four-row, three-column table.Cells flatten into ordinary text such as Item Qty Unit price; no Markdown table is inferred.
12-mixed-worst-case.pdfA two-column paragraph followed by a table and a closing paragraph.Text is extracted, but the column and table relationships are not preserved as visual layout.
13-heading-thresholds.pdfHeading lines at several font-size ratios.13pt remains a plain paragraph, 15pt becomes H3, 18–21.6pt become H2, and 22pt becomes H1.

These are limits of the page's text-extraction algorithm, not of the browser as a platform. It groups items by approximate baseline and infers headings from font size. A local parser can access the PDF bytes without knowing which visual arrangement the author intended.

What to check after you convert PDF to Markdown

CheckWhat a bad result looks likeCorpus evidence
Reading orderText from two columns is interleaved or joined in the wrong sequence.14a-row-major.pdf and 14b-column-major.pdf
WhitespaceAdjacent text runs lose the space between words or sentences.The observed output for 14b-column-major.pdf
TablesCells that share a baseline become a flat run of text instead of a recognisable relationship.Shared-baseline and offset table fixtures
HeadingsA heading that is visually obvious is treated like body text or disappears.07-bold-headings-body-size.pdf and 13-heading-thresholds.pdf
Text layersA scan produces an empty or incomplete extraction while the conversion appears to finish.04-no-text-layer.pdf and the mixed-scan fixtures

Test 3: a table — the cells get flattened

A four-row price table with three columns.

The rows survived and the reading order is right, but the column structure is gone. You cannot tell where one cell ends and the next begins, and there is no Markdown table syntax. The original PDF probably did not help: if the table was drawn with lines rather than tagged as a table, the converter sees text at coordinates and a few graphic lines, not a grid.

This matters most for exactly the documents people care about — invoices, price lists, financial statements, spec sheets — where a value detached from its column heading is worse than no value at all.

Heading detection evidence

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

Why Headings Disappear When You Convert a PDF to Markdown

In this converter, heading detection is a font-size heuristic. The current writer compares each line's largest font size with the median font size of the text items on that page. Bold weight alone is not a heading signal. The historical fixture results below document a recorded run; they are not a document-wide heading guarantee.

The exact thresholds matter more than you would expect, because they are not round numbers and they produce results that look like bugs but are not. This page shows the measured behaviour: the same 20pt title becomes an H1 in one document and an H2 in another, and neither is an error.

Everything below is output from the converter on this site, run on 17 September 2026 against documents built to test one thing each. Output is quoted exactly as it came out.

The rule, exactly

In the current source, the converter takes the median font size across text items on each page, then compares each line's largest font size with that value. A line becomes a heading if its font size is more than 1.15 times that page baseline. The thresholds below are in the current code; the sample outputs remain the historical measurements.

Ratio to body sizeResult
1.15 or belowNot a heading. Plain paragraph.
Above 1.15, up to 1.4H3
Above 1.4, up to 1.8H2
Above 1.8H1

Two things follow from that, and both surprise people. First, the level a heading gets depends on the text items on that page, not on the heading alone. Second, the thresholds are sharp, so a change of one point in font size can move a heading up a level.

Measured: a document with one heading at each size

I built a page with nine lines of 12pt body text — enough to fix the median at 12 — and then one line at each of six different sizes. Here is what came out, with the ratio for each:

Line font sizeRatio to 12pt bodyMarkdown produced
13pt1.08Plain paragraph — not recognised
15pt1.25H3
18pt1.50H2
21pt1.75H2
21.6pt1.80H2 — the boundary is not crossed
22pt1.83H1

The 21.6pt line is the interesting one. It is exactly 1.8 times the body size, and it stays an H2, because the rule is "more than 1.8", not "1.8 or more". A designer choosing 21.6pt as a clean multiple would get a second-level heading where they expected a first-level one.

The 13pt line is the other end of the same problem: 8% larger than the body text is a perfectly visible distinction to a reader, and it is invisible to this method.

The same title, two different heading levels

This is the part that looks broken and is not. I converted two documents that both had a 20pt title. In one, the body text was 12pt. In the other, the body text was 11pt.

Title sizeBody sizeRatioResult
20pt12pt1.67H2
20pt11pt1.82H1

Nothing about the title changed. Only the size of the text around it. If you convert a batch of documents from the same source and find that the top-level headings are H1 in some files and H2 in others, this is the reason — and it means you cannot fix it with a single rule, because the correction depends on the baseline computed for each page.

Bold headings are always missed

The most common complaint, and the most predictable failure. A document that uses bold text at the body size for its section headings — which is very common in reports, contracts and anything exported from a template that does not use larger type — produces no headings at all.

Output, verbatim, from a page with two bold 12pt headings among 12pt body text:

Bold Headings At Body Size
This paragraph is body text set in the regular weight.
It exists to establish what the body size of this page is.
Section One
The heading above is bold but exactly the same size as the
body text, which is the case this test is built to measure.
Section Two
A second bold heading, again at the body font size, to see
whether either of them is recognised as a heading at all.

"Section One" and "Section Two" are there, in the right place, as ordinary lines. The document's structure has been flattened into a wall of text with no hierarchy, which matters if the output is going anywhere that uses structure — a table of contents, a wiki, a documentation site, or a retrieval system that splits on headings.

There is no bold-heading recovery step in the current converter. The information needed to recognise those headings — that they are bold — is available in the PDF, but distinguishing "bold body text" from "a bold heading" reliably requires more context than a font-size comparison.

What good output looks like

For contrast, inspect the recorded single-column Markdown output: a larger title, larger section headings and body text, with the original output kept verbatim.

A 24pt title against 12pt body is a ratio of 2.0, comfortably over the 1.8 line, so it becomes an H1. The 18pt headings are a ratio of 1.5, which lands in the H2 band. The bullets were recognised as a list because they start with a hyphen or a bullet character. This is the shape to aim for, and if your document does not produce it, the cause is almost always that the type sizes are too close together.

How to get better headings out of your document

  • Check the size gap before converting. If your headings are less than about 15% larger than the body text, expect them to be missed. If you have the source, exporting its existing heading structure directly avoids this font-size inference; otherwise review the Markdown headings manually.
  • Do not rely on bold alone. If the source uses bold at body size, the headings will not survive. Plan to add them back by hand, or convert from the original document format instead of from the PDF.
  • Expect one level of drift, and normalise it. If everything comes out one level too deep or too shallow, a single find-and-replace on the leading # characters fixes the whole document.
  • Compare documents from the same source against each other, not against a fixed rule. Check the text-item sizes and resulting headings on each page; the same template does not guarantee an identical computed baseline.
  • Convert from the original format when you have it. A .docx or .html file carries real heading structure, so it may avoid reconstructing that structure from PDF geometry. A tagged PDF may also contain structure, but this writer does not read it.
Headers, footers and cleanup evidence

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

Convert PDF to README MD: Check the Running Header First

Last updated: 30 September 2026

Short answer: when you convert a PDF to a README.md, the text is not the only thing that comes across. Three items you never wrote can end up in the file — a running header, a page number, and a hyphen that existed only to break a line. The fixed corpus below shows each one with the raw output, so you can check your own file against a known result instead of reading it by eye.

A README has a small vocabulary: one title, a few sections, a bullet list, sometimes a table or a code block. That makes it a good target, because every structure is checkable. It also makes the trip from PDF risky, because PDFs are written for printing, and page furniture is part of the layout. Extraction reads text operators, and a printed header is text.

The fixtures this page uses

InputWhat it isolatesMeasured result
01-single-column.pdfA title, two subheadings and a bullet list — the shape of a simple README.Done, with an H1, two H2s and - bullets.
08-running-header-2-pages.pdfTwo pages that repeat the same header at the top and a page number at the bottom.Done. Both repeats arrive as ordinary paragraphs, with the header text and Page 1 of 2 / Page 2 of 2 in the output.
09-hyphenated-breaks.pdfWords broken across lines with a trailing hyphen.Done, with the hyphen and the line break both preserved.
10-toc-wide-gap.pdfContents lines: a label at the left margin, a page number at the right.Done. Each entry arrives as label plus number on one line, with no list structure.

What a README-shaped PDF gives you

Start with the clean case. 01-single-column.pdf is a single column with a title, two subheadings and a bullet list. Inspect its recorded Markdown output, shown in the compressed-stream evidence below.

The title became an H1, both subheadings became H2, and the bullet list kept its - markers. This is the part that usually works, and it is worth confirming before you look at anything else — if the skeleton is wrong, the details will be too.

The running header and footer arrive as body text

08-running-header-2-pages.pdf is two pages carrying the same header at the top and a page number at the bottom. The measured output is:

CONFIDENTIAL - INTERNAL DRAFT
This is the first page of a two page document.
It carries a running header at the top of every page.
It also carries a page number in the footer.
Page 1 of 2

---

CONFIDENTIAL - INTERNAL DRAFT
This is the second page of the same document.
The header and footer repeat here, exactly as before.
In Markdown output they arrive as ordinary paragraphs.
Page 2 of 2

Nothing in that output marks those lines as page furniture. They arrive as ordinary paragraphs, they repeat once per page, and the --- separator sits between the two runs. In a README this matters more than in a long document: a file that opens with CONFIDENTIAL - INTERNAL DRAFT and closes a section with Page 1 of 2 reads as content, and a reader cannot tell that the line came from the printer layout rather than from you.

The repair is mechanical, not editorial: delete the repeated first and last line of every page before you commit. Do it as a deliberate pass rather than by eye, because a running header is the same string on every page and is easy to skim past.

A hyphenated line break stays broken

09-hyphenated-breaks.pdf breaks three words across lines with a trailing hyphen. The measured output is:

## Hyphenated Line Breaks

The configuration file is stored in the applica-
tion directory, which is created on first launch
and can be relocated by setting the environ-
ment variable before the service starts.

The hyphen survives, so applica- and tion are still split in the Markdown. If that file goes into a repository as-is, a reader searching the README for “application” will not find it, and the rendered page shows a hyphen inside a word. Treat every line ending in a hyphen as something to check rather than something to fix blindly: two-column is a real hyphen, and the one in applica- is not. The corpus uses a small set of words so the pattern is easy to see; the same shape appears in any document where justified text or a narrow column forces a break.

A contents list loses its structure

10-toc-wide-gap.pdf writes four contents entries with a label at the left margin and a page number at the right. The measured output is:

## Table Of Contents

Introduction 3
Installation 11
Configuration 24
Troubleshooting 48

The leader dots and the column of page numbers are gone. Each entry is now one line of text, and the number reads as part of the label. Kept as a README, the list says Introduction 3 and Installation 11. Either drop the numbers or turn the entries into real Markdown list items — but do not leave a paragraph that happens to contain numbers where a reader expects a list.

A README checklist before you commit

  1. Confirm the title. The document's title line should be the only H1 in the file.
  2. Check the section headings. A heading that was only bold, at the same size as the body text, arrives as a plain paragraph — the Heading detection evidence on this page measures the size thresholds.
  3. Delete the page furniture. Every repeated first and last line is a header or a footer.
  4. Join the hyphenated breaks. Search the output for a hyphen at the end of a line and decide each one.
  5. Rebuild lists and tables. Contents lines and table rows both arrive as ordinary text — see the Table and column evidence on this page.
  6. Render the Markdown before you commit. A preview shows the structures that did not survive extraction.

The corpus is the same one the other guides use. make_pdfs.py writes the fixtures byte by byte, verify.py checks PDF invariants and text operators, and results.json holds the measured output quoted on this page.

On 30 September 2026, the local verifier reported 18 files, 0 failed. The PDFs and scripts are released under CC0 1.0, and the Zenodo record is the original public archive.

The entries in results.json are observations from one measured browser-side converter — pdfmdtools.com, using PDF.js 3.11.174, running client-side in the browser — recorded on 17 September 2026. They do not rank PDF-to-Markdown tools, measure OCR, establish a conversion percentage, or describe another service's retention policy. None of the fixtures is a real README, so the outputs above are structural evidence about headings, page furniture, hyphenation and contents lines, not a promise about your particular file. A different converter may keep the header, join the hyphen, or drop the contents numbers; the value of the corpus is that the inputs and the observed outputs can both be inspected.

Other cases in the same corpus

Scanned page evidence

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

The mixed-scan cases

InputWhat the PDF containsMeasured output
15-mixed-first-page-text.pdfPage 1 has a text layer; page 2 is a scan.Markdown contains the first page's heading and text, then a separator. The scanned page contributes no extracted text.
16-mixed-middle-page-text.pdfPage 1 is a scan, page 2 has text, and page 3 is a scan.Markdown contains a separator, the second page's heading and text, then another separator. The first and third pages have no extracted text.

The important detail is not that the converter returns an error. In the measured results.json, both mixed documents have status Done. Their output is simply the text that could be extracted. The missing scan content is not represented as an image or as a warning inside the Markdown block.

Why a successful status is not enough

PDF text extraction reads text operators from a page's content stream. A scanned page is different: it may contain an image or drawing commands but no usable text operators. The corpus makes that distinction explicit with 04-no-text-layer.pdf and 11-scan-styled.pdf. Both contain no text layer, and the measured converter reports: “This PDF has no text layer (it may be a scanned or image-based PDF). Cannot extract text.”

A mixed document makes the same boundary harder to see. The pages that do contain text produce plausible Markdown, so a person reviewing only the output may not notice that other pages are absent. The separator in the measured result shows a page boundary, but it does not restore the pixels from a scan or prove that the scanned page was OCRed.

The text-layer cases

InputWhat it isolatesMeasured result
04-no-text-layer.pdfA rectangle and nothing else — no text operators at all.This PDF has no text layer (it may be a scanned or image-based PDF). Cannot extract text. No Markdown output.
11-scan-styled.pdfGrey bars standing in for a scanned page; no text operators.The same no-text-layer error. No Markdown output.
15-mixed-first-page-text.pdfTwo pages: page 1 has text, page 2 is a scan.Done, but the output contains the first page's text and a separator. It does not describe the missing scan.
16-mixed-middle-page-text.pdfThree pages: page 1 is a scan, page 2 has text, page 3 is a scan.Done, but the output contains only the middle page's text and separators. Nothing in the output says that pages 1 and 3 were scans.

What the mixed-scan output actually says

The measured output for 15-mixed-first-page-text.pdf is:

## Mixed Document

This page has a real text layer.
It is the first page of a two page document.
The second page is a scan with no text at all.

---

The measured output for 16-mixed-middle-page-text.pdf is:

---

## Page Two

Only the middle page of this document has text.
The first and third pages are scans.
Nothing in the output tells you that.

---

Both files reported Done in results.json. That status tells you the extraction completed; it does not certify that all source pages contributed text. If a document contains scans, compare the page count and the raw Markdown yourself instead of treating a successful status as proof of complete conversion.

Scanned PDF to Markdown: What Actually Happens

The short answer: this homepage extracts an existing text layer and does not recognise text from page images. The historical tests below show why a mixed text-and-scan document needs a page-by-page completeness check. The current workflow adds previews and a no-text-layer warning; that warning is not OCR.

Both cases are measured below, with the exact output. Everything is from the converter on this site, run on 17 September 2026 against documents built to reproduce each situation.

Why a scan cannot be converted

A PDF made from a digital source stores glyphs: instructions that say "draw the character A here, at this size, in this font". Text extraction reads those instructions. It is a lookup, and it is reliable.

A scan stores pixels. There are no glyphs and no characters — there is a picture of a page, and the only thing in the file is a grid of colours. There is nothing to look up. Getting text out of it requires optical character recognition, which looks at the shapes in the image and guesses which letters they represent. That is a different technology with a different failure profile: it works well on clean, straight, high-contrast scans and degrades on everything else, and it produces text that is usually right and occasionally wrong in ways you have to read carefully to notice.

Text extraction reads existing characters; OCR recognises characters from an image. A tool can combine both steps, but this homepage implements only text extraction. An OCR result still needs proofreading.

Case one: the whole document is a scan — refused, correctly

I converted a PDF containing a page of drawn grey bars and no text layer, standing in for a scanned page. The result:

This PDF has no text layer (it may be a scanned or image-based PDF). Cannot extract text.

That is the right behaviour, and it is worth saying why it is right rather than merely convenient. The alternative — returning an empty result with no explanation — is worse in a specific and damaging way: you would download a blank file, assume the conversion worked, and discover the problem later, after the original had been moved or deleted.

In that recorded version, the output panel was hidden instead of offering an empty file. The current picker/drop workflow instead displays page previews and warns about pages with no text layer; those pages supply no recognised text.

The limitation is that this check is all-or-nothing. It asks whether the document contains any text at all. Which brings us to the case that matters.

Recorded case: mixed pages without a warning

This is the one to know about. I converted a two-page document where the first page was normal digital text and the second page was a scan with no text layer.

The status reported was Done, marked as a success. The second page is simply absent. There is no note, no count of skipped pages, and nothing in the output that says a page was dropped.

Then I tried a three-page document: a scan, then a page of digital text, then another scan.

Two of the three pages are gone, again with a success status. This output has one small clue if you are looking for it: it opens with a horizontal rule, because the first page contributed no text but still produced a page separator. That leading --- is a clue in this recorded output, not a reliable count of missing text. Empty pages can also leave separators inside a document.

The measured mixed-page fixtures demonstrate a completeness risk: readable text from some pages can hide missing text from others. Inspect every needed page rather than assuming that a successful status certifies complete extraction.

How to check your document before you rely on it

Inspect the source before conversion, then compare the extracted text with it.

TestWhat it tells you
Open the PDF and try to select a line of text with the mouseIf nothing highlights, investigate whether the page has a usable text layer; it may be a scan or have another extraction restriction.
Use your reader's search function and look for a word you can plainly see on the pageA failed search is a reason to inspect the text layer or encoding; it is not proof that the page is a scan.
Step through the document page by page, doing the select test on eachA useful page-by-page check. A mixed file can look normal in thumbnails; selection and search can also fail for reasons other than a scan.
Compare the file size against the page countA rough signal. Scans are usually far larger per page than digital text. Useful as a hint, not as proof.

The third row is the one people skip, and it is the one that catches the problem. A document that is mostly digital with three scanned pages in the middle looks uniform when you scroll through it quickly.

What to do about a scan

  • For a fully scanned document, use OCR. Nothing else will work. Expect to proofread the result, particularly numbers, proper nouns and anything in a small font — those are where recognition errors cluster.
  • For a partly scanned document, convert the digital pages and handle the scanned ones separately. Use the current page previews and selection to identify the pages you need. Handle pages without text through an OCR workflow, and compare the combined result with the source.
  • Check the page count. Compare the number of pages in your source with the number of sections in the output. A mismatch needs investigation. Separators alone cannot prove that a page contributed text; compare its content with the page previews.
  • Look for a leading or trailing horizontal rule in the output. These are clues to inspect, not proof of which pages contributed text; also inspect separators inside the document.
  • Keep the PDF. Whatever you do with the Markdown, the original is the only faithful copy of a scanned page. Do not delete it on the assumption that the conversion captured everything.

Making a scan searchable is a separate job

Many scanners and PDF tools can add a text layer to a scan — this is what "searchable PDF" means. The page still looks like a scan, but an invisible layer of recognised text sits on top of it, positioned to match the image. Once that layer exists, the document converts like any other, because it now has glyphs to read.

It is a genuinely useful option, and it is worth understanding what you are getting: the text layer is the output of recognition, so it carries recognition errors. Converting a searchable PDF gives you clean-looking Markdown with occasional wrong words that are much harder to spot than they would be in the original, because the surrounding text reads smoothly and nothing marks where the machine guessed.

So if you go this route, the proofreading does not go away. It moves to a later stage and becomes easier to skip.

Related guides

Test 4: a scanned document — there is nothing to extract

A PDF containing a scanned page image and no text layer at all.

Result: the converter refuses, with the message This PDF has no text layer (it may be a scanned or image-based PDF). Cannot extract text.

This is the correct behaviour, and it is worth understanding why. A scan is a picture. There is no text in it, only pixels that look like text. Getting text out requires optical character recognition, which is a completely different technology from PDF text extraction — and OCR introduces its own error rate, its own failure modes on poor scans and unusual fonts, and a need to correct the result afterwards.

A converter that quietly returns an empty result for a scan is worse than one that tells you it cannot help. If you are working with scans, you need an OCR tool, and you should expect to proofread the output. There is one case that is worse still — a document where only some pages are scans, because those convert successfully and drop the scanned pages without saying so. Scanned page evidence on this page covers that and how to check for it.

Image extraction limits

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

PDF to Markdown Images: What This Converter Actually Preserves

Last updated: 8 October 2026

Short answer: this browser converter does not extract PDF images into Markdown image files. It reads the PDF text layer and writes text, headings, lists, and page separators. A scanned page without a text layer supplies no extracted text; the current workflow warns about it and does not run OCR. If the images in your PDF carry meaning, keep the original PDF and use a converter that explicitly exports image assets.

PDF image conversion meanings

The query is ambiguous in a way that matters. You might mean a PDF containing photographs, diagrams, or charts that should become Markdown image references. Or you might mean a scanned PDF, where every visible letter is part of a page image and needs OCR before it can become text. Those are different jobs.

This homepage tool does neither image extraction nor OCR. It is a text-layer extractor. That is a narrower promise, but it is also a testable one: the page reads text items and turns those items into Markdown. It does not create an image folder, write ![alt text](...) references, or recognise pixels as characters.

What the code actually reads

The conversion path in the browser converter is visible in the page source:

  1. Read the selected PDF with file.arrayBuffer().
  2. Open it with pdfjsLib.getDocument({data:buf}).
  3. Get each page with pdf.getPage(p).
  4. Read that page's text with page.getTextContent().
  5. Group text items into lines, then write those lines as Markdown.

The output loop iterates over the returned text items. There is no call to getOperatorList() or another image-resource export path, and the generated string is assembled from item.str. That is why the output is text rather than a Markdown document accompanied by extracted image files.

The file control is narrow too: it accepts .pdf, and it does not have the multiple attribute. This page is a single-PDF text conversion, not a batch image-export workflow.

Embedded figure handling

If a text PDF contains a chart or a photograph, the text around it may still be extracted, but the image itself is not turned into a Markdown asset by this path. The output can therefore read as though the figure never existed.

That is not the same as saying every PDF image is deleted from the source. The original PDF is unchanged. It means only that this conversion result contains no generated image file or image link for the figure. If the figure is essential evidence, compare the Markdown with the source PDF before treating the conversion as complete.

A useful check is to list the things the output must contain: the surrounding heading, the paragraph before the figure, the paragraph after it, and an explicit image reference. The first three may be present; the fourth will not be supplied by this converter.

Scanned PDF handling

A scan is the harder case because it may contain no text operators at all. The corpus used for these guides includes two no-text-layer fixtures. The measured status for both is:

In that recorded run, output was null and the panel stayed hidden. The current picker/drop workflow instead shows previews and warns about pages without a text layer; it can show an empty text result for such pages.

The same boundary applies to a mixed document. A file can contain digital text on one page and a scanned image on another. In the measured 15-mixed-first-page-text.pdf case, the text page was returned with status Done, while the scanned page contributed no text. The output ended with a page separator, but there was no scan warning. For a three-page scan-text-scan document, only the middle page appeared in the output.

So “Done” does not prove that every visible page survived. Check the page count and inspect pages that contain signatures, screenshots, photographs, or scanned exhibits.

The measured cases behind that boundary

FixtureWhat it containsMeasured result
04-no-text-layer.pdfA rectangle and no text operators.No-text-layer error; no output.
11-scan-styled.pdfGrey bars standing in for a scanned page.The same no-text-layer error; no output.
15-mixed-first-page-text.pdfText on page 1, scan on page 2.Done; only the text page appears.
16-mixed-middle-page-text.pdfScan, text, scan.Done; only the middle page appears, with no warning naming the missing pages.

These results are from the site's recorded corpus output, measured with PDF.js 3.11.174 on 17 September 2026. They are observations about these named inputs, not a percentage accuracy claim and not a prediction about every other converter.

What the Markdown can still preserve

For a PDF with a usable text layer, the converter can return text lines, some headings based on font size, bullet lists, numbered lists, and page separators. That is enough for many reports and notes where the words matter more than the figures.

It does not reconstruct a page as an image-rich document. Tables can flatten, columns can interleave, and visual layout can disappear even when all the words are present. The Reading order evidence on this page and the Heading detection evidence on this page show those text-structure limits separately.

Images are therefore part of the completeness check, not a cosmetic detail. A Markdown file can be readable and still be missing the chart that makes a conclusion meaningful.

How to choose the next step

Your PDFWhat to do
Digital text, images are decorativeConvert the text, then review the Markdown against the PDF.
Digital text, figures are essentialUse a tool that explicitly documents image extraction and check its image references and asset files.
Fully scanned pagesUse OCR first, then proofread names, numbers, and labels.
Mixed text and scanned pagesCheck every page or split the file before conversion so skipped scans do not look like a complete result.

Do not run OCR over a clean text layer just because the PDF contains one photograph. OCR is a recognition step, not a replacement for reliable text extraction. Use the narrowest tool that matches the missing part of your document.

What this browser-only tool proves — and what it does not

  • It proves the file can be processed locally in the browser. The conversion path uses the selected file's bytes in the page and the self-hosted PDF.js library.
  • It does not prove image completeness. There is no image export step in the current Markdown writer.
  • It does not provide OCR. The explicit errors above are historical results. The current picker/drop workflow warns when a page has no text layer and does not recognise its pixels.
  • It does not change your source PDF. The missing image reference is a limitation of the Markdown output, not a modification of the input.

The full PDF-to-Markdown test corpus lists the fixtures and their verbatim results. The Repeatable test evidence on this page explains how to re-run a fixed corpus after a parser change. The Guides index groups these pages by workflow.

Annotation extraction limits

Last updated: 10 October 2026

Short answer: this browser converter does not extract PDF highlights, comments, or other annotation metadata into Markdown. It reads the PDF text layer and writes text, headings, lists, and page separators. A highlight may leave the underlying words readable, but the fact that those words were highlighted — or that a note was attached to them — is not carried into the Markdown output.

Annotation conversion meanings

Annotations are information layered over a PDF page rather than ordinary page text. A reader may use a highlight to mark a sentence, a sticky note to add a comment, or another markup tool to point at a passage. When someone asks for PDF to Markdown annotations, they may want the selected text, the note content, the author or date, the page number, or the visual markup preserved.

Those are separate preservation jobs. Extracting the visible text is not the same as extracting the objects attached to that text. A Markdown file can contain the sentence and still omit the annotation that explains why the sentence mattered.

Browser text extraction

  1. Read the selected PDF with file.arrayBuffer().
  2. Open it with pdfjsLib.getDocument({data:buf}).
  3. Get each page with pdf.getPage(p).
  4. Read the page text with page.getTextContent().
  5. Group the returned text items into lines and write those lines as Markdown.

The output is assembled from text items such as item.str. The current page source contains no call to getAnnotations(), getOutline(), or getOperatorList(). That is the code-backed boundary: the converter has a text extraction path, not a separate annotation, bookmark, or image-resource export path.

The file control is narrow too: it accepts .pdf, and it does not have the multiple attribute. This is a single-PDF text conversion, not a batch annotation-export workflow.

Highlighted text handling

If a highlighted sentence is part of the PDF text layer, the sentence itself may appear in the Markdown because it is ordinary extractable text. The highlight is a different question. This converter does not write a Markdown marker, note block, page label, author field, or source-position record for that highlight.

That distinction matters when the annotation carries the meaning. A research PDF may contain a short quote plus a long note explaining its relevance. The quote can survive as a paragraph while the note disappears from the result. Reading the Markdown alone would not tell you that the source page had been marked up.

Comment and sticky-note handling

Comments and sticky notes are not text paragraphs in the document's text layer. They are annotation data associated with a page or a location. Because the current conversion path only asks PDF.js for page text content, it does not add those comments to the Markdown output.

Do not infer from a successful status that annotations were preserved. “Done” means the text conversion completed for the selected file; it does not mean every layer of the PDF was exported. Keep the original PDF beside the Markdown whenever notes, highlights, review comments, or approval marks matter.

Readable output and missing annotations

Annotation loss is easy to miss because the main prose may look normal. Use a completeness check before replacing the source PDF:

  • Compare a page with highlighted passages against the same page in the Markdown.
  • Check whether comments or sticky-note text appear anywhere in the output.
  • Look for page numbers or source locations that let you return to the marked passage.
  • Keep the original PDF if the annotations are part of the review record, not just temporary decoration.

The same principle applies to other visual layers. The Image extraction limits on this page documents why embedded figures are not exported by this path, while the Reading order evidence on this page shows how text can remain present while its page structure changes.

Corpus evidence and limits

The site's recorded PDF-to-Markdown test corpus measures text extraction, headings, columns, tables, page separators, no-text-layer errors, mixed scan pages, and compressed streams. It does not include an annotated PDF fixture. Therefore there is no verbatim annotation result to quote from that corpus, and this page does not claim an annotation accuracy percentage.

The stronger, narrower conclusion comes from the source code: the converter requests text content and does not request annotation objects. That is enough to say that the current Markdown writer has no implemented annotation-export step. It is not a claim about every PDF converter or every kind of annotation in every PDF viewer.

Annotation-preserving workflows

If annotations are part of the deliverable, choose a workflow that explicitly documents annotation extraction and its output fields. Test it with a small PDF containing one highlight, one comment, and one page reference before converting a large review set.

A script-based workflow can also be appropriate when you need stable fields such as page, type, author, date, selected text, and comment body. Whatever tool you choose, compare the extracted records with the source PDF. Do not treat a clean Markdown text file as proof that the review layer was preserved.

Privacy and processing limits

This homepage processes the selected PDF in your browser rather than sending it to a conversion server. That describes where the conversion runs; it does not make the Markdown complete with respect to annotations, images, bookmarks, or other PDF layers. The page also does not provide OCR for scanned pages.

For the privacy boundary, see Local processing evidence on this page. For a repeatable check after a parser change, see the Repeatable test evidence on this page.

Related guides

Compressed stream evidence

Recorded evidence, not a new run. The corpus outputs and status strings below were recorded on 17 September 2026 with PDF.js 3.11.174. The current file-picker and drop workflow also shows page previews, page selection and a warning for pages without a text layer. It does not run OCR. Historical output is retained verbatim; it is not a promise of the current result for your file.

The compressed and uncompressed inputs

These fixtures contain different text. They check whether both kinds of stream can be read; they do not isolate compression as the only changed variable.

FileWhat it isolatesMeasured result
01-single-column.pdfA plain single-column page with a title, two subheadings and a bullet list. Content stream uncompressed.Done — 13 lines of Markdown.
17-compressed-stream.pdfThe same shape, but the page content stream is FlateDecode-compressed.Done — 8 lines of Markdown.

FlateDecode is the filter that ordinary PDF writers apply by default. A page written by a real word processor, a browser print dialog, or a report generator is compressed; a hand-written test PDF often is not. That asymmetry is why this pair belongs at the front of your checks: a converter can look perfect on hand-made samples and fail on everything produced by real software.

What the two raw outputs actually say

The measured output for 01-single-column.pdf is:

# Quarterly Report

This document is laid out in a single column, which is the
simplest case for any PDF-to-Markdown converter to handle.

## Key findings
- Revenue grew across all three regions.
- Headcount stayed flat for the second quarter.
- Support ticket volume dropped by a fifth.

## Next steps

The team will publish the full breakdown next month.

And the measured output for 17-compressed-stream.pdf is:

## Compressed Stream Document

The content stream of this page is FlateDecode-compressed,
which is what almost every real PDF in the world uses.

## Key findings
- Expansion happens before parsing, so results should match.
- A parser that mishandles the filter fails here and nowhere else.

Both files converted in the recorded run. That establishes successful extraction for these two inputs, but their different contents prevent attributing a difference solely to compression. A check that only ever passes tells you nothing; a check that has a known right answer tells you when something has gone wrong.

Why this is the case to run first

A PDF page does not contain a Markdown document. It contains drawing instructions and text operators inside a stream, and that stream is usually compressed with a filter. To extract anything, a converter has to expand the stream and then parse the operators inside it.

That gives two failure points instead of one:

  1. The filter step. If the stream is not expanded, there is nothing to parse. On a whole-document basis this looks like a converter that returns nothing useful for a PDF you can read perfectly well on screen.
  2. The parse step. If expansion succeeds but the operators are read incorrectly, text can come out in the wrong order, with lines joined together, or with words missing.

If one file converts and the other fails, investigate the filter, PDF structure, fonts and parsing path. Because the two inputs differ in content, these files alone cannot attribute the failure solely to compression.

How to run the pair yourself

  1. Convert 01-single-column.pdf. Read the raw Markdown, not the preview. Note the title line, the two subheadings and the three bullets.
  2. Convert 17-compressed-stream.pdf. Read the raw Markdown again.
  3. Compare the structure, not the wording. The inputs say different things and have different lengths. Check each output against its own source rather than expecting identical text or line counts.
  4. Look for the failure signature. No output at all, a truncated file, or lines run together in the compressed case only.
  5. Repeat on a PDF you actually care about. Export one page from your own document and run it. Inspect the resulting file rather than assuming which compression filters its writer used.

If one input fails, record the actual error and investigate it before relying on the workflow for your own documents.

Test 1: a single-column document — this works

A one-page document with a 24pt title, 18pt section headings, 12pt body text, and a bullet list. This is the recorded single-column baseline.

The recorded single-column output above shows the title, headings and bullets verbatim.

Three things went right, and they are the three things to check in any output: the title became an H1, the subheadings became H2 rather than another H1, and the bullets became a real Markdown list instead of three separate paragraphs. The recorded result used font-size-based heading inference. The current writer uses each page's text-item median, as explained in the heading evidence; this sample does not guarantee the result for another document.

Repeatable test evidence

The evidence below consolidates the former converter guides. Most corpus outputs were recorded on 17 September 2026 with PDF.js 3.11.174; the workflow section cites a separate 16 September 2026 run. These are historical observations, not new measurements of this release. Use the current page previews, selection and scan warning to inspect your own file.

How to convert PDF to Markdown without hiding the failure

  1. Keep the original PDF. Do not replace it with a screenshot or a re-export before testing.
  2. Run a small edge-case set. Include a column page, a table, a heading threshold case, a no-text-layer file, and a mixed scan.
  3. Save the raw Markdown. Do not judge only the preview; inspect the actual text around columns, tables and page boundaries.
  4. Separate extraction from OCR. A scan has pixels rather than a usable text layer. An empty extraction is not proof that the page was converted correctly.
  5. Repeat after changes. A fixed input set lets you see whether a converter release changed one behaviour.

Reproduce the corpus check

The GitHub corpus includes make_pdfs.py to write the fixtures byte by byte, verify.py to check PDF invariants and text operators, and results.json with the measured output used on this page. The verifier checks the PDF header and trailer, cross-reference offsets, page content references, declared stream lengths, compressed streams, and extracted text operators. Run against the 18 fixtures on 28 September 2026 it reported 18 files, 0 failed.

git clone https://github.com/GordonGuoJin/pdf-to-markdown-test-corpus
cd pdf-to-markdown-test-corpus
python3 verify.py

The PDFs and scripts are released under CC0 1.0, and the Zenodo record is the original public archive.

What this test does not prove

The results in results.json are observations from one measured browser-side converter — pdfmdtools.com, using PDF.js 3.11.174, running client-side in the browser — recorded on 17 September 2026. They do not rank all PDF-to-Markdown tools, they do not measure OCR, and they do not establish a universal conversion percentage. Another converter may handle compression differently, and a converter that fails this pair may still be the right choice for a different job. The fixed inputs let you compare later runs with their recorded outputs. They do not form a controlled one-variable compression experiment.

Open the full test corpus

PDF to Markdown Regression Test: A Fixed Corpus You Re-Run

Short answer: a PDF-to-Markdown regression test is a fixed set of PDFs plus the Markdown they produced, kept in a file so you can re-run the same inputs after any change and see exactly what moved. The tempting alternative — looking at the output and judging whether it seems right — does not work, because the two most common failures produce Markdown that reads as normal prose. This page uses an 18-file public corpus and its measured output to show what a usable test looks like, and what it still cannot tell you.

What “regression” means here

Extraction code changes. A parser library gets upgraded, a text-ordering heuristic is tuned, a filter is added. Each of those changes is supposed to fix one case, and the risk is that it quietly breaks another. A regression test is the thing that tells you.

It has three parts, and all three are load-bearing:

PartWhat it isWhat breaks without it
Fixed inputsSmall PDFs that each isolate one behaviour.A failure gives you a pile of text and no single cause to point at.
Recorded outputThe verbatim Markdown each input produced, stored beside the input.You have nothing to diff against, so “it looks fine” becomes the test.
A re-run triggerAny change to the parsing path — a new library version counts.The corpus exists but is never actually executed, which is the same as not having it.

The third row is the one usually skipped. A corpus on disk that nobody re-runs is documentation, not a test.

Why the obvious check — looking at the output — fails

Two PDFs in the corpus are visually indistinguishable. 14a-row-major.pdf and 14b-column-major.pdf have the same page size, the same font, the same coordinates, the same four left-column and four right-column strings, and the same nine text items in total. Open them side by side and you cannot tell which is which. The only difference is the order the text operators appear in the content stream.

Their measured output is not the same:

InputMeasured output shape
14a-row-major.pdfLeft column, line one. Right column, line one. — a space survives at the column boundary.
14b-column-major.pdfLeft column, line one.Right column, line one. — the two columns are fused with no space at all.

Both are wrong, but the second is the dangerous one. line one.Right column reads as a typo rather than as two columns that have been merged, so nobody proofreading the output catches it. A screenshot of the source page cannot reveal the difference either — the difference is not visible, it is textual.

The cause is not the geometry. PDF.js emits the spacing between two text runs as its own synthetic text item when the runs are written consecutively, and omits it otherwise. That is a property of the file's internal byte order, and it is exactly the kind of behaviour a fixed corpus catches and a visual review does not.

What is in the corpus

The PDF-to-Markdown Test Corpus is 18 small PDFs, each built to break a converter in one specific way, plus the measured output of one converter against all of them. Two rules apply to every file. Each fixture isolates one behaviour, so a surprising result points at a single cause. The 14a/14b pair isolates text-operator order. The compressed and uncompressed fixtures contain different text, so their comparison is a decoding check rather than a one-variable compression experiment.

FixtureWhat it isolatesMeasured result
01-single-column.pdfA plain single-column document: title, two subheadings, bullets.Done. Title as H1, subheadings as H2, list preserved.
02-two-column-shared-baseline.pdfTwo columns sharing the same four baselines.Done. Left and right text on the same lines, separated by a space.
03-table.pdfA four-row, three-column table.Cells flatten to Item Qty Unit price. No Markdown table is inferred.
04-no-text-layer.pdfA rectangle and no text operators at all.Reports no text layer and produces no output.
05-two-column-offset.pdfColumns that overlap for only three of five lines.Done, but only the overlapping lines fuse; the rest stay separate.
06-three-column.pdfThree columns of three lines, sharing baselines.Done. Columns separated on each line.
07-bold-headings-body-size.pdfHeadings marked out by weight only, at body size.Done, but no heading markup — the bold lines stay as body text.
08-running-header-2-pages.pdfThe same header and footer on every page.Done. Header and footer arrive as ordinary paragraphs on each page.
09-hyphenated-breaks.pdfWords split across lines with a trailing hyphen.Hyphens are preserved verbatim; applica- stays broken.
10-toc-wide-gap.pdfTable-of-contents lines: label left, page number right.Flattens to Introduction 3 with no leader or column.
11-scan-styled.pdfGrey bars standing in for a scanned page.Same no text layer error as 04.
12-mixed-worst-case.pdfA title, a two-column paragraph and a table on one page.Done. Columns fuse, the table flattens, the closing paragraph survives.
13-heading-thresholds.pdfOne line at each of six sizes around the usual heading thresholds.See the threshold table below.
14a-row-major.pdf / 14b-column-major.pdfIdentical geometry; only the content-stream operator order differs.One keeps a space at the boundary, the other removes it.
15-mixed-first-page-text.pdfPage 1 has text, page 2 is a scan.Done. Only the text page appears, followed by a separator.
16-mixed-middle-page-text.pdfScan, text, scan.Only the middle page contributes text. Nothing in the output says the other two were scans.
17-compressed-stream.pdfThe same shape as 01, but FlateDecode-compressed.Done. Compressed text was extracted; its wording differs from the uncompressed fixture.

The failures that matter are silent ones

Three rows above are worth pulling out, because each is a failure that reports success.

A scan page disappears without a warning. In 16-mixed-middle-page-text.pdf, pages 1 and 3 are scans and only page 2 has text. The measured output is the page-2 text between two separators — and the corpus README puts the problem plainly: nothing in the output tells you that. The tool status is Done. A three-page document silently becomes a one-page document, and the Markdown looks complete.

A missing text layer is an error, not an empty file. 04 and 11 return the message “This PDF has no text layer (it may be a scanned or image-based PDF). Cannot extract text.” and produce no output at all — the output panel stays hidden. That distinction matters for testing: an empty output box can be mistaken for a successful conversion of a document with nothing in it, whereas a reported error cannot. That was the recorded error path. This homepage still has no OCR, but its current picker/drop workflow shows previews and a warning for pages without text; it can display an empty text result for those pages.

Heading detection has hard thresholds. 13-heading-thresholds.pdf sets nine body lines at 12pt and then one line at each of six sizes. The measured mapping was:

Font sizeRatio to bodyMarkdown
13pt1.0833plain paragraph
15pt1.25H3
18pt1.5H2
21pt1.75H2
21.6pt1.8H2
22pt1.8333H1

Notice the last three rows: 21pt, 21.6pt and 22pt all produce different ratios but two of them land on H2 and only the largest reaches H1. A regression in the threshold logic would show up here as a one-row change — which is precisely what makes this fixture worth keeping. Related: Heading detection evidence on this page.

Run it in about a minute

No dependencies. Both scripts are standard library only.

Then open your converter, drop in the files from tests/, and compare against results.json.

verify.py is deliberately not a PDF parser. It checks the invariants a reader depends on — that startxref points at the xref table, that every xref entry points at a real object header, that the declared /Length matches the actual stream length, and that every page's /Contents resolves — and then pulls the text back out with a regular expression. That ordering is the point of a regression suite: if the fixtures themselves are malformed, a converter failure is unattributable. Verifying the inputs first is what makes a red result mean something.

The PDFs are written byte by byte rather than generated with a library, and make_pdfs.py regenerates tests/ byte-identically when run twice. So the input behind any result can be read directly instead of treated as a black box. The fixtures and scripts are CC0 1.0 — public domain, no attribution required.

Pin the parser version, because that is the thing that changes

The measured results in results.json were produced by PDF.js 3.11.174, running client-side in the browser, on 17 September 2026. That detail is not trivia — it is the regression test's anchor.

A PDF-to-Markdown tool's output is a function of the PDF and the parser. Change the parser and you have changed the function, even though none of your own code moved. When the bundled PDF.js is upgraded, the honest move is to re-run the corpus and diff, because the fixtures have not changed and therefore any difference is attributable to the upgrade. This is also why the corpus is more useful than a general “does it look right” pass: the recorded output was captured at a known version, so “what changed” has a definite answer.

What this test does not tell you

A regression suite is narrow by design, and it is worth being explicit about the edges.

  • It is not an accuracy score. Eighteen synthetic fixtures are not a percentage, a benchmark ranking or a quality grade. A different converter will produce different results against the same files — that is the point of publishing the inputs.
  • It is not an OCR test. The corpus tests what a converter recovers from the text layer. Scanned pages are represented as no-text-layer fixtures, which measure the error path, not recognition quality.
  • It does not cover every PDF. The README lists what is currently missing: forms and annotations, rotated pages, right-to-left text, embedded fonts with unusual encodings and incremental updates.
  • A green run is not a release gate on its own. It says the recorded behaviours still hold. It does not say the tool handles your document.

The boundary is the same one that applies to Local processing evidence on this page: the corpus is evidence about specific inputs, and it stays useful precisely because it does not pretend to be more.

Adapting the idea to your own documents

The corpus is a starting point, not the only valid set. The pattern transfers directly:

  1. Pick the five or six documents that have actually broken you — the two-column report, the scanned appendix, the PDF with the unusual font.
  2. Keep each one small, and keep each one isolating a single behaviour.
  3. Record the exact Markdown you accept as correct, in a file, beside the input.
  4. Re-run the whole set whenever the parsing path changes, and diff rather than eyeball.
  5. When you find a new failure, add a fixture for it. That is how the corpus grows without becoming unreadable.

If you would rather start from existing cases, the public set already covers the layout and text-layer failures that come up most often — Reading order evidence on this page, Scanned page evidence on this page, and the Local processing evidence on this page itself. The Guides index groups these by the problem they address rather than by keyword.

Annotations are not covered by the recorded fixtures. See Annotation extraction limits on this page before treating a successful text conversion as a complete export.

Convert a PDF in your browser

Local processing evidence

Historical network record. The request counts, sizes and source-search counts below describe the 17 September 2026 check. They are not a new network trace of this release. The current page also loads Google Analytics as described in the privacy policy.

The browser-side path, step by step

StepWhat happensWhat it rules out
1. Select a PDFThe page receives a browser File object from the file picker or drop zone.No form submission is needed for the normal conversion path.
2. Read it in memoryfile.arrayBuffer() creates a JavaScript buffer inside the browser.The normal path does not hand the file to a remote upload endpoint.
3. Parse locallypdfjsLib.getDocument({data:buf}) opens the PDF with the locally bundled PDF.js library.No LLM, API, or server-side PDF parser is involved.
4. Extract page textpage.getTextContent() supplies the text items used to build the Markdown output.The result depends on the PDF text layer; this path does not add OCR.
5. Generate MarkdownThe page assembles headings, paragraphs and list markers in the same browser tab.There is no server response to mistake for a locally produced result.

A quick test you can repeat on any converter

  1. Open the converter and wait until its page and conversion library have loaded.
  2. Open Developer Tools, choose the Network panel, clear the log, and select a small PDF.
  3. Look for a request that carries a body close to the size of your PDF. A request or connection carrying document data is evidence of transmission; do not judge by method or size alone.
  4. Then disconnect the network and convert a test PDF again. Successful offline conversion supports local processing for that run. Failure can also mean a required script or worker was not loaded yet; it does not prove server-side conversion.
  5. Read the page source as a second check. Search for upload-related paths and inspect what the normal file-selection handler actually calls.

This test checks handling, not output quality. A tool can avoid uploads and still lose page structure. Conversely, a server-side tool may offer OCR or heavier layout analysis at the cost of sending the document away.

No upload does not mean installable offline

After the page and its local PDF.js files have loaded, this converter can continue working with the network disconnected. That is a useful browser test, but it is not an installable offline app. The site has no service worker and no manifest, so do not confuse “loaded once, then usable without the network” with “installable and available from a cold start with no connection.”

Browser processing and file uploads

The scope of the check: this homepage reads the selected PDF in browser memory. A network log and source inspection can help verify that handling. Judge what requests contain and what the file-selection code does; a progress bar or a privacy slogan does not establish where conversion happens.

This page shows the measurement for this site's converter and gives you the exact procedure to run the same check on any other one. The measurement, the method and the limitations are all below, including the parts that are not in our favour.

What "runs in your browser" actually means

There are two ways an online converter can work, and they are easy to confuse.

  • Server-side. The page sends your file to a server, the server converts it, and the result comes back. A progress bar alone does not distinguish server-side work from local processing. Your document exists on someone else's computer for at least a few seconds.
  • Client-side. The page downloads the conversion code once, and then does the work inside your browser. Your file is read from your disk by the page, processed in memory, and never transmitted. The page is a real application rather than a form that posts a file somewhere.

Both kinds are described as "online" and "free", and both may say "we respect your privacy". The distinction only shows up in what the page does after you choose a file.

The measurement, and how to repeat it

I opened this site's converter in a browser with developer tools recording network activity, cleared the log, and selected a 1,401-byte PDF. Here is what the recorder showed.

Before selecting the file — six requests, 108,111 bytes total:

RequestWhat it is
pdfmdtools.com/The page itself
/styles.cssThe stylesheet
/lib/pdf.min.jsThe PDF parsing library
/favicon.svgThe tab icon
static.cloudflareinsights.com/beacon.min.jsPage-view analytics
pdfmdtools.com/cdn-cgi/rumPage-view analytics

After selecting the file — one additional request:

New requestCarries your file?
pdfmdtools.com/lib/pdf.worker.min.jsNo. It is our own copy of the parsing worker, served from this site.

The recorded log contained zero requests using any method other than GET. That describes the observation, not a universal upload test: document data can also be encoded in request URLs or sent through other network mechanisms. The relevant check is whether any request or connection transmits file data, combined with inspection of the conversion code.

To repeat the check, use a non-private test file, open Developer Tools, clear the Network log, then convert. Inspect request URLs, bodies and network connections for document data. A POST may be an analytics event rather than a file upload; a GET does not by itself prove that no data was sent. Compare the observation with the file-selection code.

The stronger test: disconnect and convert

An offline run is a useful additional check once all conversion assets, including the PDF worker, are loaded. It does not replace inspecting the code and requests.

Load the converter page and run a non-private file once to load the PDF worker, then turn off your network — disconnect the wifi, or unplug the cable. Now select a PDF and convert it.

I ran exactly this on 17 September 2026. With the browser reporting itself offline, the conversion completed normally and produced the correct output, including the same interleaved-column behaviour it produces when online. Nothing about the result changed, because nothing about the conversion depends on the network.

This test is not perfect — a page could in principle cache a file and send it later, when you reconnect — but combined with the request log above, it rules out the ordinary case. And it is the test you can run on any tool in the time it takes to toggle a switch.

Checking the source, if you want to go further

For this page, where conversion code is visible in the source, you can read the code. Open the page, view the source, and search for the strings that would be involved in sending a file somewhere.

Search forWhat it would mean if presentRecorded source count — 17 September 2026
XMLHttpRequestThe classic way to send data to a server0 occurrences
fetch(The modern way to send data to a server1 occurrence, explained below
FormDataWrapping a file for upload0 occurrences
sendBeaconFire-and-forget background transmission0 occurrences
WebSocket, EventSourceStreaming data out0 occurrences
localStorage, sessionStorage, document.cookieStoring something on your machine0 occurrences

The recorded fetch( count is worth being precise about, because a bare count is misleading. It is a testing hook: if you add ?autoload= to the address followed by a path, the page fetches that path and converts it, so a conversion can be automated. It only runs if you put that parameter in the URL yourself. It is not part of the normal path, and that hook is not a user-file upload. Page delivery and analytics have their own network requests.

What the normal path does is this: read the chosen file into memory with file.arrayBuffer(), and hand that buffer directly to the PDF parser. The buffer is a JavaScript object in your browser's memory. There is no step at which it is written to a request.

The parts that are not in our favour

A page that only lists the reassuring facts is not giving you a fair account, so here are the limits of what the measurement above proves.

  • The page and the library are still downloaded from a server. That is unavoidable — you have to fetch the application before it can run. What that means is that this site knows a page was loaded, from your IP address, at a certain time. It does not know which document you converted, or that you converted one at all.
  • There is analytics on the page. Two of the six requests above are Cloudflare's page-view measurement. That is about the page visit, not the document, and it is described in the privacy policy. The current page also loads Google Analytics, uses analytics cookies, and sends page-visit information as described in the privacy policy. The converter does not include selected filenames, document contents or Markdown results in those events. Blocking analytics does not stop local conversion.
  • This only covers this tool. The historical measurements concern this homepage conversion path. They say nothing about any other converter, including ones that look similar and make the same claims.
  • "Never uploaded" is not the same as "never left your machine". A browser extension, an operating system backup service, or a sync client can move a file that no website touched. That is outside any converter's control.

Why this matters more than it used to

Converting a PDF to Markdown used to be a formatting convenience. It is increasingly a step in a pipeline: documents get converted and then fed into a search index, a knowledge base or a language model. That changes what is at stake.

A server-side converter has a copy of the document. What happens to that copy afterwards is governed by a policy you have not read, on infrastructure you cannot see, for a retention period you were not told. For a public manual that is a shrug. For a contract, a medical record, an unpublished draft or anything under an NDA, it is the whole question.

If you are converting documents in bulk for that kind of pipeline, this is the criterion to choose tools on — before output quality, before speed, and before price. It is also the only one of those criteria that you can verify yourself, in two minutes, without taking anyone's word for it.

Frequently asked questions
Can I convert PDF to Markdown online for free?

Yes. Choose one PDF with a text layer, inspect the pages and download an .md file without an account. MD is the file extension for Markdown. Free access does not guarantee complete extraction: compare the result with the original PDF.

Is my PDF uploaded during conversion?

No. The normal file-picker and drop workflow reads the selected file in browser memory and parses it with self-hosted PDF.js. It does not upload the PDF or call a model API. The page can read the file you selected; local processing describes where that reading happens. See the local-processing evidence and limits.

Does the page collect analytics?

The page loads Cloudflare analytics and Google Analytics for page visits. Google Analytics uses analytics cookies. Selected filenames, document contents and Markdown results are not included in our analytics events. See the privacy policy.

Can I use it offline?

Load the page and conversion assets, including the PDF worker, before disconnecting. An already-loaded conversion can run locally, but this is not an installable offline app or a guarantee of cold-start access without a connection. Failure offline can mean a missing asset; it does not prove that conversion uses a server.

Does the converter save my document or history?

The converter reads the file into page memory and does not save conversion history in cookies or browser storage. Closing or reloading the tab clears the page's conversion state. Downloads you save remain on your device; analytics cookies are separate from document processing.

Can this homepage convert scanned pages?

It does not run OCR. The current workflow shows page previews and warns when a page has no text layer; those pages supply no recognised text. A mixed document may still produce text from its digital pages. If plain text is your goal, PDF to Text has a separate local OCR workflow. Review its supported languages and limits.

How do I check that every needed page contributed text?

Compare the page previews, selected-page count and extracted passages with the source. A selected scan can contribute no text, and a page separator does not prove completeness. Review the recorded mixed-page examples; their old status messages are distinct from the current warning.

Should I run a clean text PDF through OCR?

OCR is not a necessary first step for a usable text layer and can introduce recognition errors. Use text extraction for those pages. If text is missing or unusable, investigate the cause and use OCR where appropriate. OCR alone is not a guarantee of correct multi-column reading order.

Why did headings become plain text or the wrong level?

The current writer compares each line's largest font size with the median font size of text items on that page. It does not infer heading roles from bold weight alone or read the PDF structure tree. A ratio above 1.15 through 1.4 produces H3; above 1.4 through 1.8 produces H2; above 1.8 produces H1. See the heading evidence for the historical sample outputs.

Can tagged PDF headings be used instead?

Tagged PDFs can contain logical headings and other structure. This writer does not read that structure tree, so tags alone do not guarantee its output. When you have the original document, exporting its existing structure may avoid reconstructing it from PDF text positions.

How should I repair headings?

Compare each heading with the source and normalise its Markdown level. Do not assume a global find-and-replace fits every page. No repair time has been measured here; the work depends on document length and the errors present. Correct levels matter for tables of contents and systems that split text by headings.

Why are columns interleaved or table cells flattened?

This tool groups text items by approximate baseline and horizontal position. It does not reconstruct columns or a table model, so adjacent cells or passages may become one text line. See reading-order evidence and table evidence. These examples do not prove that every PDF or another converter has the same failure.

Can find-and-replace repair columns?

Only when you have verified a consistent pattern against the original. A line in the recorded output can contain both columns, so alternating odd and even lines is not a repair. Spanning headings, figures and tables can break a simple splitting rule.

Are figures and photographs included in the Markdown?

No image assets or Markdown image references are exported. Text-layer captions and nearby text may appear, but the figure itself will be absent. Keep the original and review the image-extraction limits if the figure carries meaning.

Are highlights, comments and sticky notes exported?

Underlying highlighted text may appear when it is in the PDF text layer. Highlight markings, attached comments and sticky notes are not exported. The source calls for page text, not annotation objects. There is no annotated fixture in the recorded corpus, so this conclusion is based on the code rather than a claimed annotation test. See annotation limits.

Does Done mean the result is complete?

It means the extraction workflow completed, not that every source element was preserved. Check pages, reading order, table relationships, headings and non-text content before relying on the Markdown. The public test corpus provides named inputs and historical raw outputs, not an accuracy score.

Which formatting should I expect to review?

The current output contains text lines, font-size-based headings, basic bullet markers and page separators. It does not reproduce page fonts, colours, margins or exact placement. Running headers, footers, hyphenated line breaks and contents numbers can remain as ordinary text; see the cleanup evidence. Numbered lines may remain text without reconstructed list structure.

Is Markdown suitable for keeping a text document?

Markdown is plain text and can be opened in a text editor. It is useful when readable text and structure matter more than a designed page layout. Keep the original PDF when appearance, figures or annotations are important.

Do I need a server-side converter for OCR or layout analysis?

Those capabilities depend on the implementation, not simply on whether it runs in a browser. This homepage has no OCR or layout-recovery step. For any alternative workflow, check its actual output, supported formats and file-handling policy separately.

Return to the PDF to Markdown tool · Browse tools and test guides

Already have Markdown? Convert a Markdown document to PDF in your browser, including a page exported from Notion.