ipynb to Script

Paste a Jupyter .ipynb notebook (its JSON) and get a clean Python script — code cells extracted in order, outputs and execution counts dropped. Optional Markdown export, # %% cell markers, and comment-kept markdown. Runs entirely in your browser, no upload, no sign-up.

Try:
Script

What this tool does

Paste a Jupyter notebook — the full contents of an .ipynb file, which is just JSON — and get back a clean, runnable Python script. It runs entirely in your browser with WebAssembly: nothing is uploaded, it works offline, and there's no sign-up.

The converter:

Options

OptionWhat it does
Output formatscript (default) — a .py file with code verbatim and markdown cells as # comments. markdown — a .md document with markdown cells verbatim and code in fenced blocks.
Keep markdown cellsOn by default. Markdown/raw cells become # comments (script) or stay verbatim (markdown). Turn it off for code only.
Include stored cell outputsOff by default — the whole point is dropping outputs. Turn it on to append each cell's stored text output under a # Output: comment (or a fenced block in markdown mode).
Add # %% cell markersOff by default. Emits a # %% marker before each cell so VS Code and Jupytext see cell boundaries in the .py. Ignored in Markdown mode.

Worked example

Given this notebook (two cells — one markdown, one code with a stored output):

{
  "cells": [
    {"cell_type": "markdown", "source": ["# Demo notebook\n", "\n", "Load and greet."]},
    {"cell_type": "code", "execution_count": 1,
     "outputs": [{"output_type": "stream", "name": "stdout", "text": ["hi\n"]}],
     "source": ["import sys\n", "print('hi')"]}
  ],
  "metadata": {"language_info": {"name": "python"}},
  "nbformat": 4, "nbformat_minor": 5
}

the default script output is:

# # Demo notebook
#
# Load and greet.

import sys
print('hi')

The execution_count and the stored hi output are gone; the markdown cell became # comments. Turn on Add # %% cell markers and each cell is prefixed with # %% (# %% [markdown] for prose) so VS Code shows cell boundaries. Turn on Include stored cell outputs and a # Output: / # hi comment is appended after the code.

Limits & edge cases

FAQ

Is it free and private?

Yes. The conversion runs locally in your browser with WebAssembly — your notebook never leaves your device, and the page keeps working offline once it has loaded. There's no account and nothing is uploaded.

How is this different from jupyter nbconvert --to python?

Same core idea — code cells become Python, markdown cells become # comments — but the output is deliberately leaner. This tool omits nbconvert's #!/usr/bin/env python shebang, # coding: utf-8 line, and per-cell # In[N]: execution-count markers, so you get a clean, diff-friendly script. You can opt into # %% VS Code / Jupytext markers instead.

Why is my print() output missing?

That's the point of the tool — outputs and execution counts are dropped so you get source code, not a run log. If you do want the stored text outputs kept, turn on Include stored cell outputs and they're appended under a # Output: comment.

Can I get Markdown instead of a Python file?

Yes. Set Output format to markdown. Markdown cells are kept verbatim and code cells are wrapped in fenced code blocks (using the notebook's language, e.g. ```python). It's handy for turning a notebook into a readable document.

Does it work with R, Julia, or old notebooks?

Yes. Any language works — code cells are copied verbatim, and Markdown mode fences them with the notebook's own language metadata. Both nbformat v4 (top-level cells) and older v3 notebooks (worksheets) are supported.

How do I keep cell boundaries for VS Code or Jupytext?

Turn on Add # %% cell markers. Each cell is prefixed with # %% (# %% [markdown] for prose cells), which VS Code's Python extension and Jupytext recognize as cell boundaries — so you can still run the .py cell-by-cell.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool ipynb-to-script "{
  \"cells\": [
    {\"cell_type\": \"markdown\", \"source\": [\"# Demo\"]},
    {\"cell_type\": \"code\", \"execution_count\": 1, \"outputs\": [], \"source\": [\"print('hi')\"]}
  ],
  \"metadata\": {\"language_info\": {\"name\": \"python\"}},
  \"nbformat\": 4, \"nbformat_minor\": 5
}"

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/ipynb-to-script/?notebook=%7B%0A%20%20%22cells%22%3A%20%5B%0A%20%20%20%20%7B%22cell_type%22%3A%20%22markdown%22%2C%20%22source%22%3A%20%5B%22%23%20Demo%22%5D%7D%2C%0A%20%20%20%20%7B%22cell_type%22%3A%20%22code%22%2C%20%22execution_count%22%3A%201%2C%20%22outputs%22%3A%20%5B%5D%2C%20%22source%22%3A%20%5B%22print%28%27hi%27%29%22%5D%7D%0A%20%20%5D%2C%0A%20%20%22metadata%22%3A%20%7B%22language_info%22%3A%20%7B%22name%22%3A%20%22python%22%7D%7D%2C%0A%20%20%22nbformat%22%3A%204%2C%20%22nbformat_minor%22%3A%205%0A%7D&output=script&include_markdown=true&include_outputs=true&cell_markers=true

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.