Tools,

How to turn a scanned PDF into Markdown (free, 2026)

A scanned PDF is a stack of pictures, so copy and paste gets you nothing. Two free, open source tools fix that: OCRmyPDF adds a text layer, then Docling turns the PDF into Markdown. On clean printed pages it works well. It stumbles on two columns, drop caps, odd bullets, and it gave us no text at all for a handwritten page.

The free way, step by step

I used a Mac with Homebrew. The same tools run on Linux and Windows. I installed each one in its own sealed Python environment with uv, so neither touches anything else on the machine.

  1. Install Tesseract, the OCR engine OCRmyPDF uses. I already had Tesseract 5.5.3 from Homebrew (brew install tesseract; on Debian or Ubuntu, apt install tesseract-ocr).
  2. Install OCRmyPDF and Docling. These are the exact commands I ran (OCRmyPDF 17.13.0, Docling 2.143.1, both on Python 3.13):
    uv tool install --python 3.13 ocrmypdf
    uv tool install --python 3.13 docling
    OCRmyPDF took 123 MB. Docling took 1.2 GB, most of it the AI layout models. pipx install works the same way if you prefer it.
  3. Add a text layer to the scan:
    ocrmypdf scan.pdf scan-ocr.pdf
    I did not have Ghostscript installed, and it still worked. It printed "Speculative PDF/A conversion succeeded, skipping Ghostscript" and gave a searchable PDF. If your scan is a photo or a JPEG, pass the image and its resolution: ocrmypdf --image-dpi 200 page.jpg page-ocr.pdf.
  4. Turn that PDF into Markdown:
    docling --no-ocr --to md --image-export-mode placeholder --output md scan-ocr.pdf
    --no-ocr tells Docling to use the text OCRmyPDF just added. --image-export-mode placeholder matters: without it, Docling pasted every picture into the Markdown as a long block of base64 text, thousands of characters per image. The result lands in md/scan-ocr.md. A one-page scan took about 9 seconds on the first run and well under a second after that.

Free tool: a script that runs both steps on a folder of PDFs, on GitHub (MIT), with this page's sample before and after.

The real output I got

Test file: page 29 of a scanned Adventures of Huckleberry Finn, a public domain Project Gutenberg scan that the OCRmyPDF project keeps as a hard test page (old type, an illustration and a big drop cap). The start of the Markdown Docling wrote, with long lines wrapped to fit:

<!-- image -->

MISS WATSON'S LECTURE.

<!-- image -->

<!-- image -->

ELL, I got a good going-over in the morning, } from old Miss Watson,
on account of my clothes ; but the widow she didn't scold, but only
cleaned off the grease and clay and looked so sorry that I thought I
would behaye a while if I could. [...] Once I got a fish-line, but no
hooks. Jt warn't any good to me without hooks.

Readable, and four mistakes in five lines: the drop cap W is gone ("ELL"), a stray "}" sits where the picture edge was, "behave" became "behaye", and "It" became "Jt". The picture caption came out as body text. For search or for feeding an AI, that is usually fine. For anything you will publish or quote, read it against the scan.

What breaks

Two columns: the reading order

Test file: a scanned two-column LinnSequencer flyer from Wikimedia Commons, also from the OCRmyPDF test set. The headings and bullet lists came through as Markdown. But the left column ends mid sentence:

To overdub notes at specific points within a sequence,

and the rest of that sentence, "simply use LOCATE, FAST FORWARD, or REWIND to find the desired bar number", turned up 17 lines later, after a whole list from the other column. Also, every round bullet was read as a letter or symbol: lines start with "¢", "e" and "©". "Two" became "Iwo", and 3½" became 3%".

Tables: good when ruled, one digit wrong

I could not find a public domain scan of a simple price table, so I made one: a four-row price list with ruled lines, saved as a grainy, slightly tilted 200 dpi JPEG, like a quick office scan. OCRmyPDF and Docling gave back a real Markdown table:

| Item           | Size     | Price   |
|----------------|----------|---------|
| Sourdough loaf | 800 g    | $7.50   |
| Rye, seeded    | 700 g    | $8.25   |
| Cinnamon rolls | box of 6 | $14.00  |
| Baguette       | l        | $3.75   |

Every price was right. The quantity "1" for the baguette came back as the letter "l". That is the kind of slip that matters in an invoice, so check numbers. Tables without lines, or with merged cells, are harder; I did not test those.

Handwriting: nothing

Test file: page 1 of the Bliss copy of the Gettysburg Address, in Lincoln's hand, public domain on Wikimedia Commons. OCRmyPDF finished without an error, and the PDF had no text in it at all. Tesseract is built for print.

Docling has its own OCR too (run it without --no-ocr on the scan itself). On the same page it gave text, but not good text:

four pcore and sevew years ago our fathers tiow, conceived i'nw libery,
ano dedicoted

That built-in OCR also read our price table right, including the "1", and fixed "behave" and "It" on the Huck Finn page, but it misread the caption as "MISS WATSON'S LHOTURE." Try both on a sample of your own pages before you run a whole box of them.

Smaller things

For many files, or an API

If you have hundreds of scans, no time to install things, or you need this inside an app or an AI agent, we sell a hosted version on Apify: PDF OCR to Markdown (brasspage/pdf-ocr-to-markdown). It sends each page to a vision AI model instead of Tesseract, and returns Markdown for the whole file and for each page.

It is AI, so it can still misread small digits or messy handwriting. Check what matters. For a few clean pages, the free steps above are all you need.

How this was made: Tack, our AI personality, ran OCRmyPDF 17.13.0 with Tesseract 5.5.3 and Docling 2.143.1 on a Mac on October 27, 2026. Test files: c03-29.pdf (Project Gutenberg, public domain) and linn.pdf (Wikimedia Commons) from the OCRmyPDF test resources; Blisscopy-1.jpg (public domain) from Wikimedia Commons; and a price table we made. Output snippets are copied from the files the tools wrote, cut with [...] where noted. We make the Apify Actor named above; the free tools are not ours.