Automate Publishing of Jupyter Notebooks as Medium Blog Posts with jupyter_to_medium

jupyter notebook Jun 02, 2020

I am very excited to announce the official release of jupyter_to_medium, a Python package that extends Jupyter Notebooks, allowing you to automate the process of publishing them as Medium blog posts.


I've published dozens of blog posts on Medium myself with all of them beginning as Jupyter Notebooks. Manually converting them to Medium posts was a fairly lengthy, painstaking process. One particularly painful process was inserting tables, which Medium does not support, into my posts. Nearly all of my posts contain numerous pandas DataFrames (such as this one, which has 40! DataFrames) which are represented as HTML tables within a notebook. I'd take screenshots of each one to insert them into my Medium posts.

jupyter_to_medium automates the process of converting Jupyter Notebooks to Medium blog posts allowing you to save a substantial amount of time.


Install from PyPI with the following command:

pip install jupyter_to_medium

After installation, fire up a Jupyter Notebook that you'd like to publish on Medium. Make sure you start a brand new notebook session. Even if you don't have a notebook that is ready to publish, you can still test this extension and publish as a draft so that it remains private.

Deploy as Medium Post

Once you open your notebook, head into the File menu and notice that you'll have a new option Deploy as -> Medium Post.

Menu Option


If 'Deploy as' option is missing

This new option should automatically show up in your notebook without doing anything. If it is missing, run the follow command to enable it.

jupyter bundlerextension enable --py jupyter_to_medium._bundler --sys-prefix

Fill out form

Clicking on Deploy as -> Medium Post triggers a new browser tab with a short form that needs to be filled out before posting.


Medium Integration Token

Before you can post to Medium, you'll need to request an integration token from them. Do this by emailing them at [email protected]. Please read the entire instructions on how to get your integration token.

Once your request is granted, navigate to your Medium settings page. Towards the bottom of the page exists the section on Integration Tokens. Enter a description for the token (jupyter_to_medium is a good choice) and then create the token.

Save your integration token

Once you have your integration token, create the folder and file .jupyter_to_medium/integration_token in your home directory and save the token there. If you don't save it, you'll need to access it every time you wish to make a new post.

Complete form

Once you have your integration token, you can complete the rest of the form. Note that the 'Title' text box is not the actual title of the post, but a title that Medium uses for SEO purposes. Use an H1 Markdown header in the first cell of your notebook to create the actual title of your post.


Once you've completed the form, click the Publish button. At this time, only publishing as a 'draft' is allowed as you probably want to review what your post looks like before publishing it publicly.



If your post was successful, you'll see the following screen with the URL of your post.

Finalize on Medium

As stated, jupyter_to_medium only allows for publishing as a draft. To make your post public, go to your post on Medium and publish there.



There are several features that jupyter_to_medium provides to ensure that your notebook appears in the

All images in Markdown are found and uploaded to Medium

All images in the Markdown cells, such as the five above are found and uploaded to Markdown. Medium limits the image types to png, jpeg, gif, and tiff.

Pandas DataFrames are converted to images

Medium does not support tables, such as those produced in output cells by pandas DataFrames. As a workaround, these tables are uploaded as images captured by the Chrome browser's screenshot ability. In the following code cell, the bar_chart_race package is used to import a pandas DataFrame containing deaths from COVID-19 in several countries. It is embedded in the Medium post as an image.

In [1]:
import bar_chart_race as bcr
df = bcr.load_dataset('covid19')
df = df.iloc[-15:-10, ::3]
  Belgium China India Ireland Netherlands Sweden USA
2020-04-08 2240.0 3337.0 178.0 235.0 2255.0 687.0 14704.0
2020-04-09 2523.0 3339.0 226.0 263.0 2403.0 793.0 16553.0
2020-04-10 3019.0 3340.0 246.0 287.0 2520.0 870.0 18595.0
2020-04-11 3346.0 3343.0 288.0 320.0 2653.0 887.0 20471.0
2020-04-12 3600.0 3343.0 331.0 334.0 2747.0 899.0 22032.0

Styled pandas DataFrames

Styled pandas DataFrames are also embedded in your post as images.

In [2]:
  Belgium China India Ireland Netherlands Sweden USA
2020-04-08 00:00:00 2240.000000 3337.000000 178.000000 235.000000 2255.000000 687.000000 14704.000000
2020-04-09 00:00:00 2523.000000 3339.000000 226.000000 263.000000 2403.000000 793.000000 16553.000000
2020-04-10 00:00:00 3019.000000 3340.000000 246.000000 287.000000 2520.000000 870.000000 18595.000000
2020-04-11 00:00:00 3346.000000 3343.000000 288.000000 320.000000 2653.000000 887.000000 20471.000000
2020-04-12 00:00:00 3600.000000 3343.000000 331.000000 334.000000 2747.000000 899.000000 22032.000000

Matplotlib Plots

All matplotlib plots, along with any other command that outputs an image will be safely embedded in your post.

In [3]:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(4, 2.5), dpi=144)
df.loc['2020-04-12'].sort_values().plot(kind='barh', ax=ax, width=.8);

Animated gifs

Even animated gifs are supported by Medium. This one created by the bar_chart_race function.

In [4]:
from IPython.display import Image
bcr.bar_chart_race(df, 'docs/images/covid19.gif', figsize=(4, 2.5))
<IPython.core.display.Image object>

Citing Jupyter to Medium

If you do use jupyter_to_medium, please mention in the post that you've used it, so that others can find out about it.

Master Python, Data Science and Machine Learning

Immerse yourself in my comprehensive path for mastering data science and machine learning with Python. Purchase the All Access Pass to get lifetime access to all current and future courses. Some of the courses it contains:

Get the All Access Pass now! 


Register for a free account

Upon registration, you'll get access to the following free courses:

  • Python Installation
  • Intro to Jupyter Notebooks
  • Intro to Pandas
  • Python  and Pandas Challenges