← Back to all guides

Diagram showing how to convert Jupyter Notebook ipynb file to Markdown md format online

Written by Alex Chen, Lead Data Systems Engineer β€” specializing in Jupyter toolchains, AST document parsers, and LLM data ingestion.

The fastest way to convert Jupyter to Markdown is the online Jupyter to Markdown converter β€” drag in your .ipynb, no install needed. For automation or batch jobs, use the CLI: jupyter nbconvert --to markdown notebook.ipynb. Both preserve code cells and outputs cleanly.

Why Convert a Jupyter Notebook to Markdown?

A .ipynb file is really a JSON blob under the hood β€” that's how Project Jupyter stores cells, metadata, and outputs together β€” which makes it clumsy for anything outside the notebook environment. Markdown, on the other hand, renders natively almost everywhere developers actually publish their work.

You'll typically need this conversion when:

  • Writing a GitHub README β€” notebooks don't render cleanly as project documentation, but a .md export does.
  • Publishing technical blog posts on Hugo, Jekyll, Gatsby, or any static site generator that expects Markdown source files.
  • Feeding docs into a wiki or knowledge base (Notion, Confluence, GitBook) that ingests Markdown but chokes on raw notebook JSON.
  • Sharing analysis with non-technical stakeholders who just need to read the narrative and see the outputs, not open Jupyter.
  • Compiling a finished report downstream β€” once your notebook is clean Markdown, it's a straightforward hop to a polished PDF or Word document; see our guide to converting Markdown to PDF, Word, and HTML for that leg of the pipeline.
  • Working the pipeline in reverse β€” if your notebook started life as code pulled out of a research paper, our PDF to Markdown guide covers extracting that text and code before it ever reaches a notebook.

The good news: you've got five solid ways to do it, and none of them require deep Python expertise.

How to Convert / Export a Jupyter Notebook to Markdown (5 Methods)

Whether you're working on a single notebook or scripting a batch export, one of these five methods will fit your workflow.

Method 1: Instant Online Tool (Zero-Setup)

If you just need to export a Jupyter notebook to Markdown once β€” no CI pipeline, no repeated automation β€” skip the terminal entirely.

⚑ Fastest Method: Online Jupyter to Markdown Converter

Three steps, no terminal required:

  1. Upload your .ipynb β€” drag the file into the browser window, or click to select it.
  2. Instant browser parsing β€” the tool reads the notebook's JSON structure client-side and converts code cells, outputs, and images on the spot.
  3. Download clean .md β€” grab the finished Markdown file, ready to drop into a README, static site, or wiki.

It works identically on Windows, macOS, or Linux β€” useful if you're on a locked-down work laptop where pip install isn't an option.

This is the method to reach for when a colleague sends you a notebook and asks "can you just get me the Markdown version," and you don't want to spin up a virtual environment for a thirty-second task.

Method 2: Command Line Using nbconvert

For anyone converting notebooks regularly, jupyter nbconvert markdown is the standard tool. It ships with most Jupyter installations, and it's scriptable, which matters if you're generating docs as part of a build pipeline. Full flag reference lives in the official nbconvert documentation.

bash

# Install nbconvert (skip if it's already bundled with your Jupyter install)
pip install nbconvert

# Convert a single notebook to Markdown
jupyter nbconvert --to markdown notebook.ipynb

# Re-run every cell first, so the Markdown reflects fresh calculations rather than stale saved outputs
jupyter nbconvert --to markdown --execute notebook.ipynb

# Send the output to a specific folder instead of the notebook's directory
jupyter nbconvert --to markdown notebook.ipynb --output-dir ./docs

# Convert every notebook in a folder in one pass
jupyter nbconvert --to markdown *.ipynb

Running this command creates notebook.md alongside a folder (usually notebook_files/) holding any extracted images. Keep that folder β€” more on why in the troubleshooting section below.

Cleaning Up Output with a Custom Jinja Template

By default, nbconvert's Markdown exporter is fairly clean, but if you're feeding the output into a documentation wiki, you may still want to strip execution-count prompts like In [1]: that survive from the notebook's cell metadata. nbconvert renders every format through Jinja2 templates, and the Markdown exporter's base template lives at markdown/index.md.j2 β€” you extend it rather than edit it in place.

Create a small custom template:

jinja

{# templates/basic/index.md.j2 #}
{% extends 'markdown/index.md.j2' %}

{% block in_prompt %}{% endblock in_prompt %}
{% block output_prompt %}{% endblock output_prompt %}

Overriding in_prompt and output_prompt with empty blocks removes the In [1]: / Out[1]: markers entirely, leaving just the code and its rendered output. Point nbconvert at the folder containing it by name:

bash

jupyter nbconvert --to markdown --template=basic notebook.ipynb

Note that basic here is the name of your template folder, not something nbconvert ships out of the box β€” the built-in named templates (lab, classic, reveal) are for the HTML exporter. For Markdown output, you're always extending the base markdown/index.md.j2 template yourself, which is exactly what makes this approach flexible: you decide what gets stripped.

Method 3: JupyterLab / Classic Notebook UI

Already have the notebook open? You don't need the terminal at all.

  1. Open your notebook in JupyterLab or the classic Notebook interface.
  2. Go to File β†’ Save and Export Notebook As… (classic Notebook: File β†’ Download as).
  3. Select Markdown (.md).
  4. The file downloads directly to your browser's default download folder.

It's slower than the CLI for bulk jobs, but it's convenient when you're already mid-session and just need one clean export.

Method 4: Inside VS Code

If your workflow lives in VS Code with the Jupyter extension installed, exporting takes two clicks.

  1. Open the .ipynb file in VS Code.
  2. Click the Export icon in the notebook toolbar (or open the Command Palette with Ctrl+Shift+P / Cmd+Shift+P and search "Export").
  3. Choose Markdown as the export format.
  4. VS Code writes the .md file to the same directory, images included.

This keeps you in one editor for the entire workflow β€” write code, run cells, export docs β€” without switching windows.

Method 5: Quarto CLI (Modern, Reproducible Workflows)

If you're working with computational notebooks in 2026, there's a good chance Quarto is already part of your stack β€” it's the open-source publishing system built on Pandoc that grew out of the R Markdown ecosystem and now handles Jupyter notebooks natively. It's worth reaching for when plain nbconvert isn't enough: you need fresh output on every render, a custom template, or GitHub Flavored Markdown specifically (rather than nbconvert's default flavor).

bash

# Render a notebook straight to GitHub Flavored Markdown
quarto render analysis.ipynb --to gfm

# Re-execute every code cell before rendering, so outputs are never stale
quarto render analysis.ipynb --to gfm --execute

# Apply a custom Pandoc template instead of Quarto's default
quarto render analysis.ipynb --to gfm --template=basic

The --execute flag matters more than it looks: without it, Quarto renders whatever outputs are already saved in the .ipynb file, which is fine for a notebook you just ran, but stale if you're rendering an older file in a CI job. Full flag reference and format options are in the GFM output guide in Quarto's docs.

Like nbconvert, Quarto extracts figures and images into a sibling directory rather than inlining them β€” the naming convention just differs slightly. A rendered analysis.ipynb produces a tree like this:

project/
β”œβ”€β”€ analysis.ipynb
β”œβ”€β”€ analysis.md
└── analysis_files/
    └── figure-gfm/
        β”œβ”€β”€ cell-3-output-1.png
        └── cell-7-output-1.png

Same rule applies as with nbconvert's notebook_files/ folder: move analysis.md, and analysis_files/ has to travel with it or every image reference breaks.

Mastering Markdown Inside Jupyter Notebooks

Converting notebooks is only half the picture. Most developers also want to know how to Markdown in Jupyter Notebook cells themselves, so the narrative reads well before it's ever exported.

How to Create a Markdown Cell in Jupyter Notebook

There are two ways to add a Markdown cell, and the keyboard shortcut is worth memorizing if you write a lot of documentation inline.

  • Keyboard shortcut: Click a cell to select it, press Esc to enter command mode, then press M. The cell switches from Code to Markdown instantly.
  • Toolbar/GUI: Use the cell-type dropdown in the toolbar (it usually reads "Code" by default) and select Markdown from the list. In JupyterLab, you can also use the + Markdown button below any existing cell.

Press Shift+Enter to render the cell once you're done editing it.

Core Markdown Formatting Syntax

Standard Markdown syntax works inside Jupyter's Markdown cells:

markdown

# Header 1
## Header 2
### Header 3

**bold text**
*italic text*

> This is a blockquote β€” useful for callouts or quoted material.

`inline code`

​```python
# fenced code block with syntax highlighting
def hello():
    print("Hello, notebook!")
​```

| Column A | Column B |
|----------|----------|
| Value 1  | Value 2  |

Tables and code fences render exactly the way you'd expect on GitHub, so there's no learning curve if you've written Markdown anywhere else.

How to Underline in Markdown Jupyter Notebook

Here's a gap that trips up a lot of people: standard Markdown has no native underline syntax. Asterisks give you bold and italics, but there's nothing built in for underlining.

The workaround is to drop into raw HTML, which Jupyter's Markdown renderer supports directly inside the same cell:

html

<u>This text is underlined</u>

<ins>This also renders as underlined</ins>

Both tags work. <u> is the more common choice; <ins> carries slightly different semantic meaning (it signals "inserted text") but renders identically in the notebook.

How to Add an Image to Jupyter Notebook Markdown

You've got three practical options here, depending on whether you need a quick embed or precise control over sizing.

1. Standard Markdown syntax (relative path):

markdown

![Alt Text](images/plot.png)

This is the cleanest option and the one that survives export to Markdown or GitHub without modification.

2. HTML syntax for custom width or height:

html

<img src="images/plot.png" width="500"/>

Reach for this when the default image size is too large for the surrounding text, or when you need consistent dimensions across multiple images in the same document.

3. Cell attachment (drag-and-drop):

Double-click a Markdown cell to enter edit mode, then drag an image file straight from your file explorer into the cell. Jupyter embeds it as a base64-encoded attachment inside the notebook's JSON β€” no separate image file to manage. It's convenient, but worth knowing: attached images bloat the .ipynb file size and can behave inconsistently once exported, since some converters don't unpack attachments the same way they handle linked files.

Companion folder vs. inline data URI β€” which should you actually use? This comes up constantly once you're past a single example image. A companion folder (notebook_files/, analysis_files/) keeps the Markdown source small and lets Git diff cleanly β€” you can see exactly which figure changed between commits, and the images are cacheable as separate HTTP requests if you're publishing to a static site. The trade-off is that the .md file is no longer self-contained; move it without the folder and every image breaks, which is precisely the failure mode covered below. Inline Base64 data URIs (![alt](data:image/png;base64,iVBORw0KG...)) solve the portability problem β€” one file, nothing to lose in transit β€” at the cost of a Markdown source that's borderline unreadable in a diff or a plain-text editor, and a file size that balloons fast with more than a couple of plots. As a rule of thumb: use companion folders for anything that lives in version control or gets published, and reserve inline Base64 for one-off exports you're pasting into a single Slack message or email where portability trumps everything else.

Writing Math Equations

Jupyter renders LaTeX through MathJax, right inside Markdown cells:

markdown

Inline equation: $E = mc^2$

Display equation:
$$
\int_{a}^{b} f(x) \, dx = F(b) - F(a)
$$

Single dollar signs render inline with the surrounding text; double dollar signs center the equation on its own line. This is standard for anyone documenting a data science or research notebook where the math itself is part of the explanation.

Common Pitfalls & Troubleshooting

Even a straightforward export can go sideways. Here's what usually breaks, and how to fix it.

Broken images after export. When nbconvert pulls inline or attached images out of a notebook, it dumps them into a sibling folder β€” typically notebook_files/. If you move the .md file without that folder, every image link breaks. Keep the folder in the same relative location, or update the image paths manually after moving files.

Raw cells vs. code cell formatting. Raw NBConvert cells pass through to the Markdown output completely unformatted β€” no code fences, no syntax highlighting. If a section of your export looks oddly plain compared to the rest, check whether that cell was set to "Raw" instead of "Code" in the original notebook.

The nbconvert / Pandoc dependency error. A common one: running jupyter nbconvert --to markdown throws Pandoc wasn't found or a similar NoSuchFile error, because some export paths lean on a separate Pandoc binary that pip doesn't install automatically. Fixing it means installing Pandoc system-wide (apt install pandoc, brew install pandoc, or the Windows installer) and making sure it's on your PATH β€” an extra dependency most people don't expect. The online converter sidesteps this entirely, since there's no local environment or missing binary to debug in the first place.

Mixed-format documentation projects. Notebooks rarely exist in isolation β€” most teams are also converting PDFs, Word docs, or LaTeX files into the same documentation set. If that's your situation, it's worth knowing the free Markdown conversion tools suite handles this too: the platform hosts 16 specialized conversion tools for developers, covering HTML, PDF, DOCX, and LaTeX to Markdown, so you're not juggling five different tools for one documentation pipeline.

Method Comparison: Which Should You Use?

Method Speed Installation Required Ideal Use Case
Online Tool (MD-Convert) Instant None One-off conversions, no dev environment, locked-down machines
CLI (nbconvert) Fast (seconds) Python + pip install nbconvert Automation, batch conversion, CI/CD pipelines
JupyterLab / Notebook UI Fast Already bundled with Jupyter Exporting while already working in the notebook
VS Code Extension Fast VS Code + Jupyter extension Developers who live in VS Code all day
Quarto CLI Fast (seconds) Quarto install Reproducible pipelines, fresh output on every run, custom templates

Frequently Asked Questions

How do I convert .ipynb to .md without installing Python?

Use an online Jupyter to Markdown converter β€” upload the .ipynb file in your browser and download the converted Markdown directly. No Python environment, no pip install, and it works the same across Windows, macOS, and Linux.

How do you underline text in Jupyter Markdown?

Standard Markdown doesn't support underlining, so you need raw HTML inside the Markdown cell: <u>your text</u> or <ins>your text</ins>. Both tags render as underlined text once the cell is executed.

Why are my images broken after exporting to Markdown?

nbconvert extracts images into a separate folder (commonly notebook_files/) alongside the .md file. If that folder gets left behind or moved separately from the Markdown file, every image reference breaks. Always move the folder and the .md file together.

How do I switch a code cell to a Markdown cell quickly?

Select the cell, press Esc to enter command mode, then press M. The cell type switches from Code to Markdown immediately, and you can start typing standard Markdown syntax right away.

Do I need nbconvert if I just want a quick one-time conversion?

No β€” installing nbconvert only makes sense if you're converting notebooks repeatedly or scripting the process. For a single file, the online converter does the job in seconds without any setup.

Data & Tables