How to convert a Jupyter notebook to PDF

There are five routes from .ipynb to PDF. They differ mostly in what you have to install first, and in how badly they fail when something is missing.

1. Use an online converter

The fastest route if you do not want to install anything. Drop the file on the converter on the home page, check the preview, and save. The notebook is parsed by JavaScript in your own browser, so nothing is uploaded and no TeX distribution is involved.

Worth knowing: the final PDF is written by your browser’s print engine, so you pick Save as PDF as the destination in the print dialog. The upside is that the text stays selectable and searchable instead of being flattened into a picture.

2. Jupyter’s own menu

In JupyterLab: File → Save and Export Notebook As → PDF. In classic Notebook: File → Download as → PDF via LaTeX.

This calls nbconvert behind the scenes, which calls LaTeX. On a fresh machine it usually fails, because a full TeX distribution is roughly a 2 GB install that Jupyter does not ship with. If you got here after seeing 500 : Internal Server Error or nbconvert failed: xelatex not found, that is why — see fixing nbconvert PDF errors.

Fix common nbconvert PDF errors

The standard --to pdf exporter writes LaTeX and then runs a TeX engine. Read the exact error below; when you do not need LaTeX typesetting, the --to webpdf route above avoids that toolchain.

nbconvert failed: xelatex not found on PATH

No LaTeX engine is installed or visible to the shell running Jupyter. Install a TeX distribution (MiKTeX on Windows, MacTeX on macOS, or TeX Live on Linux), then reopen the terminal or Jupyter server so it picks up the updated PATH.

500 : Internal Server Error while exporting from Jupyter

The web interface can hide the specific exporter error. Check the terminal where the Jupyter server is running; it usually reports the missing executable or package that caused the failure.

pandoc: command not found

Pandoc is a separate program; installing nbconvert with pip does not install it. Install Pandoc from the official instructions or with conda install -c conda-forge pandoc.

Undefined control sequence or garbled CJK text

LaTeX may be encountering a character or font it cannot typeset. Check the TeX log for the failing line; emoji, box-drawing characters, or a default font without Chinese, Japanese, or Korean glyphs are common causes. Use a CJK-capable template when LaTeX output is required, or export with webpdf to use browser fonts instead.

If you must use LaTeX, inspect the generated file

Export the intermediate .tex file, then run XeLaTeX directly. Its log points to the failing line and character more clearly than nbconvert’s wrapper:

jupyter nbconvert --to latex notebook.ipynb
xelatex notebook.tex

3. nbconvert on the command line

The classic LaTeX route:

jupyter nbconvert --to pdf notebook.ipynb

Requires nbconvert, Pandoc, and XeLaTeX. It produces genuinely beautiful, typeset output — the best of any option here — and it is the right choice for a thesis or a paper. It is the wrong choice when you just need to hand a notebook to someone this afternoon.

4. nbconvert’s webpdf exporter

Same tool, no LaTeX — it drives a headless Chromium instead:

pip install "nbconvert[webpdf]"
jupyter nbconvert --to webpdf --allow-chromium-download notebook.ipynb

This is the most reliable command-line option and the one to reach for when the LaTeX route keeps failing. It downloads a browser on first use, so the first run is slow and needs network access.

5. VS Code

VS Code can open .ipynb files natively, but its export menu also leans on nbconvert, so it inherits the same LaTeX dependency. The workaround that always works is Export → HTML, then open the HTML file in a browser and print it to PDF.

Which one should you use

Getting a clean-looking PDF

Whichever route you take, a few things make the result read better. Restart the kernel and run all cells before exporting, so the numbering is consistent and no stale output sneaks in. Clear any cell that dumps hundreds of rows — a truncated head() reads far better on paper. And if the audience does not need the implementation, hide the code cells entirely: the converter has a toggle for that, and the result reads like a report rather than a transcript.