Markdown to PDF
Convert .md files to PDF, with the headings kept as an outline.
This tool runs entirely in your browser. Your file is never uploaded, and you can verify that in your browser's network tab. Verify it yourself: open your browser's network tab and watch. You will see one small request asking whether you have tasks left - a tool name and a hash, never the file.
What this does
This reads a Markdown file and lays it out as a PDF directly, without going through HTML on the way. Headings, lists, tables, block quotes, links and fenced code blocks all come across, and the headings also become a real PDF outline. Markdown has no pages of its own, so the pagination is created here rather than reproduced from anywhere - the paper size, margins and theme you pick are what decide where the breaks fall.
Use it when the reader has no Markdown reader: a README that has to go into a tender pack, meeting notes an editor wants as an attachment, a specification circulating for comment, or documentation you want on paper with a table of contents that works.
How it works
- Drop your .md or .markdown files onto this page. Up to 20 at a time, each up to 50 MB.
- Pick a theme. Plain sets 11 pt with 1.45 line spacing, Book loosens to 11.5 pt and 1.6 for something read end to end, and Technical tightens to 10 pt and 1.35 for reference material that gets scanned rather than read.
- Choose the paper size, orientation and margins. Normal margins are 56 points on every side.
- Leave bookmarks from headings on so the finished PDF opens with a working outline, and turn page numbers off if the document already numbers itself.
- Under advanced options, decide whether YAML front matter at the top of the file should supply the document title.
- Press Convert. Each file becomes its own PDF and the downloads start on their own.
The parser walks Markdown into the document model directly and never renders it to HTML first. That sounds like an implementation detail and is not: a Markdown-to-HTML-to-PDF route escapes the content twice, and every escaping bug in that round trip shows up later as a stray ampersand or a visible line-break tag in somebody's finished document. Going straight to the model means the text you wrote is the text that gets measured.
Headings become the PDF outline, which is the thing that makes a long Markdown document usable as a PDF at all. A forty-page specification without an outline is a scroll bar and nothing else. One hash through six become outline entries at the matching depth, so the structure you already have in the file is the navigation the reader gets, with no extra step and nothing to maintain separately.
GitHub-flavoured extensions are on, so tables, strikethrough, task lists and bare URLs behave the way they do on GitHub rather than being left as literal punctuation. Fenced code blocks are set in Noto Sans Mono at 92 per cent of the body size, on a tinted wash, and a block longer than the remaining space is split across pages with the wash redrawn rather than being pushed whole onto the next sheet. Long code lines are folded, with the continuation indented to match the line it came from and the break preferred at a space so an identifier is not cut in half.
Images referenced by the Markdown are not embedded, and raw HTML blocks are not rendered. A Markdown file points at its pictures by path or by URL rather than containing them, and going out to fetch one would be exactly the outbound request this tool exists not to make. Convert the pictures separately with Images to PDF and join the results with Merge PDF if they need to be in the same document.
The Book theme asks for a serif face, and it is worth knowing what that gets you. With Embed a Unicode font on, which is the default, there is no Noto Serif in the embedded set, so serif borrows the sans faces and what you actually gain is the looser leading and the larger type. Turn embedding off and the text really is set in Times Roman, at the cost of every character outside the WinAnsi range.
What this tool cannot do
- Images referenced by the Markdown are not embedded. Fetching them would mean an outbound request; convert them with Images to PDF and combine the results instead.
- Raw HTML inside the Markdown is not rendered. Structure written as Markdown converts; structure written as HTML tags does not.
Questions people ask
- Which flavour of Markdown does it understand?
- CommonMark plus the GitHub extensions: tables, strikethrough, task lists and bare URLs that become links. Headings, ordered and unordered lists, nested lists, block quotes, horizontal rules, inline code and fenced code blocks are all handled. YAML front matter at the top of the file is read as the document title when that option is on, rather than being printed as a table.
- Do my headings become a table of contents?
- Yes. With bookmarks from headings on, one hash through six hashes become PDF outline entries at the matching depth, so the reader gets a navigation pane built from the structure already in your file. Nothing has to be added to the Markdown and nothing has to be kept in step by hand.
- Why are the images in my Markdown missing?
- Because a Markdown file references its pictures rather than containing them, and fetching them would mean this page making a request on your behalf - which is the one thing every tool here refuses to do. The text, tables, lists, links and code all convert. If the pictures matter, run them through Images to PDF and combine the two documents with Merge PDF.
- How are fenced code blocks set?
- In Noto Sans Mono at 92 per cent of the body size, on a tinted wash, with tabs expanded to four spaces before anything is measured. A line wider than the column is folded rather than clipped, the continuation is indented to line up with the line it came from, and the fold prefers a space so a long identifier stays in one piece.
- Is my document uploaded to convert it?
- No. The file is decoded, parsed and laid out in a Web Worker inside your browser, and the PDF is written there too. What the page fetches is the Noto font from this site's own origin, cached after the first use, and the small request that asks whether you have tasks left - a tool name and a hash, never your text.