Convert Jupyter Notebook to Markdown — Free & Private

Turn an .ipynb notebook into clean Markdown in your browser. Keeps prose and code, drops the base64 images and execution metadata that bloat the raw JSON.

Jupyter Notebook to Markdown: Keeping the Narrative, Dropping the Wrapper

A notebook is two documents wearing one filename. There is the thing you wrote — headings, explanation, code, the printed result that made the point — and there is the JSON envelope the format stores it in. Open an .ipynb in a text editor and you see the envelope: every prose line split into its own string, "execution_count": 7 on every cell, empty "metadata": {} objects everywhere, and somewhere in the middle a quarter of a megabyte of base64 that renders as one small scatter plot.

Converting to Markdown throws away the envelope and keeps the document. Your markdown cells were already Markdown, so they pass through untouched. Code cells become fenced blocks tagged with the kernel language, which is the form every model, every README and every static site generator already understands. Drop an .ipynb above and the conversion happens in this browser tab — the file is never uploaded.

Where the Weight Actually Is

People assume a big notebook is big because of the code. It almost never is. The weight sits in four places, in descending order:

  • Base64 image output. Every plt.show() writes the rendered PNG into the file as base64 text. One figure is commonly 200 to 400 KB of characters. A notebook with a dozen plots is mostly plot. None of it means anything to a reader of the text.
  • HTML representations of dataframes. Pandas emits both text/plain and text/html for the same result. The HTML version carries inline styles and a <table> with a tag per cell, so it can be twenty times the size of the plain version while saying exactly the same thing.
  • Progress bar frames. A tqdm loop writes a new line for every refresh, separated by carriage returns. The file ends up with hundreds of copies of a bar that only ever displayed once.
  • Per-cell metadata. Individually trivial, collectively not: cell ids, execution counts, collapsed flags and empty metadata objects across a few hundred cells add up.

The conversion above deals with each of these. Media payloads are counted and replaced by a single placeholder line so you can still see where a figure was. When a result offers both plain text and HTML, the plain text wins. Carriage-return sequences collapse to the final state of the line. Metadata is dropped entirely. The tool reports what it removed, so the saving is visible rather than claimed.

Why Fenced Blocks Matter More Than They Look

The single most useful thing Markdown does for a notebook is mark the boundary between prose and code explicitly. In the raw JSON that boundary exists only as a "cell_type" field several lines above the content. Flattened carelessly, an explanation and the code it describes run together, and a reader — human or model — has to infer which is which from syntax alone.

A fence tagged with the language removes the guesswork. It also carries the kernel language forward: the converter reads language_info from the notebook metadata, falling back to the kernelspec, so an R or Julia notebook is fenced as R or Julia rather than being silently labelled Python. Outputs get their own untagged fence beneath the cell that produced them, prefixed with a plain Output: line, which keeps the causal relationship visible without inventing syntax that Markdown does not have.

Tracebacks Are Worth Keeping

There is a temptation to strip error output along with everything else. It is usually the wrong call. If you are handing a notebook to a model and asking why a cell fails, the traceback is the entire question. What makes tracebacks unpleasant in raw form is not the content but the ANSI colour codes IPython wraps them in — escape sequences that render as readable colour in a terminal and as ESC[0;31m garbage anywhere else.

Those sequences are stripped and the traceback text kept. Long ones are shortened from the middle rather than the end, because in a deep stack the useful frames are the first few and the last few, and the two hundred lines of library internals between them are what you would skip anyway.

Notebooks in a Repository Dump

The same conversion runs inside the GitHub, GitLab and local folder tools on this site. Select an .ipynb in a repository and it lands in the output as readable cells rather than as a wall of JSON. This matters more than it sounds: in a data science repository the notebooks are often where the actual reasoning lives, and before this they were the files you had to deselect to keep the output usable.

In that context the output limit is tighter than on this page, because a repository dump is context for a model and cell output is the least valuable part of it per token. A note in the converted text records how much was removed, so nothing disappears silently.

Older Notebooks Still Work

Format version 4 puts cells in a top-level cells array. Version 3, which is still scattered across public repositories from the early 2010s, nests them one level deeper inside worksheets and names the source field input rather than source. Both shapes are read. So is the pyout output type that version 3 used where version 4 says execute_result.

Two things are deliberately not attempted. Notebook widgets — interactive sliders and plots backed by ipywidgets — store their state in a separate metadata block and render to nothing useful as text; the placeholder tells you one was there. And cell execution order is preserved as it appears in the file, not sorted by execution count, because the order you read a notebook in is the order it is written.

Nothing Is Uploaded

Notebooks carry things people forget about: an API key pasted into a cell during debugging, a database connection string, a slice of production data printed to check a join. The conversion runs in JavaScript in this tab. There is no upload step, no server copy, and no request to delete afterwards. Close the tab and it is gone.

If you want plain text instead of Markdown — no fences, no structure, just the prose and the code — the notebook to text converter produces that, and the file you have selected carries across.