How to clean a notebook before you share it
Outputs, execution counts, tokens, and printed data are part of the file. A checklist for what to strip, what to keep, and how to search before you send an .ipynb.
Updated
A notebook you are willing to keep on your own laptop is not automatically a notebook you should email, commit, or upload to a course site. The file is JSON. Everything in a cell’s source and everything in its saved outputs is copied to whoever receives the file. Cleaning is the step where you decide which of those bytes are part of the work and which are leftovers from how you ran it.
This is a checklist, not a product tour. You can do every step with Jupyter, with a text editor, or with a utility that rewrites the JSON. The point is to know what you are removing and why. The public sample notebook is already clean: no secrets, one trivial output, no images. Use it as a picture of a small honest file, then compare it with a real notebook from a project before you share that project.
What actually gets copied
When you attach analysis.ipynb to an email, the recipient gets:
- Every Markdown cell, including notes you meant as private (“fix the client name before sending”).
- Every code cell, including commented-out keys, tokens pasted into a string, and paths like
/home/you/clients/acme/. - Every saved output: printed dataframes, tracebacks with server paths, HTML from a widget, and base64 images.
- Notebook metadata, which sometimes includes the username of the kernel environment or a working directory.
They do not get your terminal history unless you pasted it into a cell. They do not get files that the code loaded from disk unless those files are embedded as outputs or attached. People forget the second half of that sentence. A printed dataframe of customer rows is the data, even though the CSV stayed on your machine.
Outputs
Outputs are a recording of a past run. They are useful when the point of sharing is “here is what this cell printed.” They are harmful when the point is “here is the code” and the output is a 40 MB plot, a dump of a table, or an error from a machine path you do not want to publish.
Strip outputs when:
- You are committing to Git and reviewers should see source changes, not a new base64 blob every time you re-run.
- The output contains rows, tokens, or tracebacks you did not intend to publish.
- The file is too large to email and the size is images, not code.
Keep outputs when:
- The reader cannot run the notebook and still needs the numbers or the figure.
- You are exporting to PDF or Word specifically so those saved figures appear.
- A grade or a paper depends on the displayed result, and you have checked that the result matches the source currently in the cell.
Clearing outputs does not delete the code. It sets outputs to an empty list and usually resets execution_count to null. The next person can run the cell if they have the environment. If they do not, they will see code and no result. Say that in the email if it matters.
A practical order: duplicate the file first, strip the copy you will publish, and keep your working notebook with outputs if you still need them. Do not clean your only copy five minutes before a deadline and then discover you needed the figure that was only stored as an output.
Execution counts
The number in [7] is not part of the science. It changes whenever you run cells. In a diff it looks like every code cell changed. Resetting counts is reasonable before a commit. It does not hide secrets. It does not prove the cells were run in order. A notebook can show [1], [2], [3] from top to bottom and still have been edited after those runs.
If you need to claim “this output came from this source,” the reliable method is to restart the kernel and run all cells once, then save, on a machine with the right packages. Resetting counts without re-running only makes the brackets empty. It does not refresh results.
Secrets and identifiers
Search the file as text before you share it. The patterns that show up in real notebooks:
- API keys, bearer tokens, and connection strings assigned to variables “just for this session.”
- Passwords in a Markdown note at the top of the lab.
.envcontents pasted into a cell.- Printed headers from an HTTP response that include an authorization value.
- Tracebacks that include a full path with a person’s home directory, a customer name, or a hostname.
- Query results that were a sample of production data and are still sitting in an output.
Removing the line from the code is not enough if you already ran the cell and the value was printed. Clear that output too, or remove the output object. Then search again. JSON escapes and line-splitting mean a secret can be split across source array elements. Searching the raw file still finds it if you search for a distinctive substring.
Do not “clean” a secret by renaming the file. The bytes are inside. Do not rely on a converter to strip secrets. An export keeps whatever text it was asked to keep. If the token is in the source, it can appear in the PDF, the Word file, the Markdown, and the Python script.
If a secret was committed or emailed, rotating the credential matters more than editing the notebook afterward. The old file may already have been copied.
Personal data and bulky outputs
A notebook for a class example should use toy data. A notebook from a work analysis often does not. Before you upload it anywhere, including a converter you trust, decide whether the outputs are allowed to leave your machine. Processing a file to build a download does not change your obligation to the data. If the dataframe should not be pasted into chat, it should not be pasted into an .ipynb you then upload.
Large images have a simpler failure mode: the file becomes tens of megabytes, diffs become useless, and mail servers reject the attachment. Compress or strip plots you do not need in the shared copy. Keep one copy with figures if the figure is the result.
Metadata you did not mean to publish
Kernel display names are usually harmless. Widget state, cell tags, and custom metadata can contain ids from an extension or a platform. You rarely need to scrub kernelspec. You should look if an extension stored something under a key you do not recognize and the notebook came from a system that handles private data.
Slideshow metadata and collapsed flags are not secrets. Leave them unless you know an export is misreading them.
A sequence that wastes less time
- Save your working notebook under its current name.
- Make the copy you intend to share.
- Search that copy for tokens, passwords, customer identifiers, and home-directory paths.
- Decide whether outputs stay. If they stay, restart and run all, then read the outputs once as if you were the recipient.
- If they go, strip outputs on the copy only.
- Open the cleaned file in a viewer or a text editor and confirm the cells you expect are still there. Stripping outputs must not delete Markdown or code.
- Export from the cleaned copy if you also owe someone a PDF or a Word file. Exporting first and cleaning later leaves the secret in the PDF.
The sample notebook is what step 6 looks like when the file was written to be public: three cells, a stdout stream that only prints a title and 4, and metadata that says Python 3. Your file will be longer. The checks are the same.
If the notebook is already a mess of merged student submissions or a file that will not parse, fix structure before you polish. A notebook that does not parse cannot be reliably stripped, because a tool cannot see the cells. Repair is a different problem from cleaning: one restores JSON, the other chooses which valid fields to keep.
After the file is safe to share, the format question is the one in what exports keep and drop. Cleaning does not pick the format. It only makes sure every format you might produce is a format you are willing to hand to someone else.

