Tutorial
Convert Markdown to PDF with Pandoc (Command Line)
Pandoc is the Swiss Army knife of document conversion. If you live in the terminal and want repeatable, scriptable Markdown-to-PDF output — with a table of contents, custom margins, syntax-highlighted code, and proper Unicode — this is the tool. This guide walks you through installing Pandoc and a PDF engine, running your first conversion, tuning the output, and batch-converting whole folders.
What is Pandoc?
Pandoc is a free, open-source command-line program that converts documents between dozens of formats: Markdown, HTML, LaTeX, DOCX, EPUB, and more. It does not produce PDFs on its own, though. Instead, it hands your document to a PDF engine — usually a LaTeX distribution — which renders the final file. That is the one detail that trips up most newcomers, so we will install both pieces.
Installing Pandoc
Pick the command for your operating system.
# macOS (Homebrew)
brew install pandoc
# Ubuntu / Debian
sudo apt update && sudo apt install pandoc
# Windows (Chocolatey)
choco install pandoc
# Windows (winget)
winget install --id JohnMacFarlane.Pandoc
Confirm it works:
pandoc --version
Note that the apt package on older Ubuntu releases can be a year or two behind. If you need the newest features, grab the latest .deb from the Pandoc releases page instead.
Installing a PDF engine
Pandoc needs a LaTeX engine to build PDFs. You have three practical choices.
TinyTeX is the lightest LaTeX option and the one we recommend for most people. It installs only what you need and grows on demand:
# Install TinyTeX via the quarto CLI (cross-platform)
quarto install tinytex
# Or install the standalone TinyTeX distribution
# macOS / Linux:
curl -sL "https://yihui.org/tinytex/install-bin-unix.sh" | sh
Full TeX Live / MacTeX is the heavyweight option (several gigabytes) but includes every package, so you rarely hit a "missing .sty file" error:
# macOS
brew install --cask mactex-no-gui
# Ubuntu / Debian
sudo apt install texlive-latex-recommended texlive-xetex texlive-fonts-recommended
HTML-based engines skip LaTeX entirely. If you would rather render through a browser engine, install WeasyPrint or wkhtmltopdf and point Pandoc at it with --pdf-engine. These handle CSS well but support fewer typesetting features:
pip install weasyprint
pandoc report.md -o report.pdf --pdf-engine=weasyprint
Your first conversion
With Pandoc and an engine installed, the basic command is refreshingly short:
pandoc report.md -o report.pdf
Pandoc reads report.md, renders it through your default LaTeX engine, and writes report.pdf. That is the whole workflow. Everything below is optional polish.
Useful options
Real documents usually need a few flags. Here are the ones you will reach for most:
| Option | What it does |
|---|---|
--toc |
Generates a table of contents from your headings |
--toc-depth=2 |
Limits the contents to H1–H2 |
-V geometry:margin=1in |
Sets page margins |
--pdf-engine=xelatex |
Uses XeLaTeX (required for Unicode / non-Latin scripts) |
-V mainfont="Georgia" |
Sets the body font (XeLaTeX or LuaLaTeX only) |
--highlight-style=tango |
Chooses a syntax-highlighting theme for code |
-V colorlinks=true |
Colors links instead of boxing them |
--template=custom.tex |
Uses your own LaTeX template |
A well-rounded command for a professional report looks like this:
pandoc report.md -o report.pdf \
--toc --toc-depth=2 \
--pdf-engine=xelatex \
-V geometry:margin=1in \
-V mainfont="Georgia" \
-V colorlinks=true \
--highlight-style=tango
The backslashes let you spread one command across several lines for readability — omit them and put everything on a single line if you prefer.
If you use the HTML route with WeasyPrint, you can style output with CSS instead of LaTeX variables:
pandoc report.md -o report.pdf \
--pdf-engine=weasyprint \
--css=style.css
Batch-converting a folder
Once your command works for one file, scripting the whole folder is trivial. This bash loop converts every .md file in the current directory:
for f in *.md; do
pandoc "$f" -o "${f%.md}.pdf" --toc --pdf-engine=xelatex
done
The ${f%.md}.pdf expression strips the .md extension and appends .pdf, so notes.md becomes notes.pdf. To recurse into subfolders, swap the loop for find:
find . -name "*.md" -exec pandoc {} -o {}.pdf --pdf-engine=xelatex \;
Quoting the variable ("$f") matters — it keeps filenames with spaces from breaking the loop.
Common errors and fixes
A few problems come up again and again. Here is how to clear them fast.
pdflatex not found (or xelatex not found). Pandoc found no PDF engine. Install one — TinyTeX, TeX Live, or MacTeX from the section above — or point Pandoc at an HTML engine with --pdf-engine=weasyprint.
Unicode or emoji characters fail to render. The default pdflatex engine cannot handle arbitrary Unicode. Switch to XeLaTeX or LuaLaTeX, which read fonts directly from your system:
pandoc doc.md -o doc.pdf --pdf-engine=xelatex
A .sty file is missing (common with TinyTeX). Install the package on demand:
tlmgr install <package-name>
Non-Latin scripts show blank boxes. You need a font that covers those glyphs. Combine XeLaTeX with a suitable mainfont, for example -V mainfont="Noto Serif".
When NOT to use Pandoc
Pandoc is fantastic for repeatable, automated pipelines — but the LaTeX setup is real overhead. If you just need to turn one Markdown file into a clean PDF right now, installing a multi-gigabyte TeX distribution is overkill.
For a quick, private, zero-setup conversion, use a browser tool instead. ConvertMDapp runs entirely in your browser — no install, no signup, no watermark — with a live preview so you see the result as you type. Because everything happens on your device, your files never leave your machine, which is ideal for confidential documents. Draft or spot-check there, then reach for Pandoc when you are ready to script the whole folder. You can convert Markdown to PDF online here in seconds.
For more background on formats and workflows, see the pillar guide on how to convert Markdown to PDF. If you would rather stay inside your editor, the walkthrough on Markdown to PDF in VS Code covers extensions and keyboard-driven exports.
FAQ
Do I really need LaTeX to use Pandoc for PDFs?
For the default engine, yes — Pandoc renders PDFs through a LaTeX engine like XeLaTeX. You can avoid LaTeX entirely by using --pdf-engine=weasyprint or --pdf-engine=wkhtmltopdf, which render through an HTML/CSS engine instead.
Why does my PDF fail on non-English text?
The default pdflatex engine has limited Unicode support. Add --pdf-engine=xelatex (or lualatex) and set a font that covers your script with -V mainfont="..." to fix broken or blank characters.
Can I control fonts and margins without a template?
Yes. Use -V geometry:margin=1in for margins and -V mainfont="Georgia" for the body font (the font variable requires XeLaTeX or LuaLaTeX). Reach for a custom --template only when you need layout control beyond what these variables offer.