Introducing notion-py, an unofficial Python API wrapper for

Jamie Alexandre
3 min readJan 18, 2019

Hello! My name is Jamie Alexandre, and I’m an API addict. I’m always hesitant to pick up a new tool if it doesn’t have some way for me to interact with it in my native language: code. APIs are the lifeblood of interoperability and data portability, and enable automation of the tedious, so that we can focus on the glorious.

When my team introduced me to Notion, it was love at first sight. Notion brings together the best aspects of Trello, spreadsheets, relational databases, rich WYSIWYG Markdown editing, TODO lists, and more, into a single, seamless, flexible, and intuitive system. One problem: there was no documented API. The Notion team has posted about plans for an official API, and Krzysztof Kowalczyk posted a blog and code (in Go) last summer that could pull content from the internal Notion API to generate HTML. But I wanted something that a) gave me full read-write control over my Notion data, and b) was written in my language of choice, Python.

Thus was born notion-py, an unofficial Python wrapper for the internal Notion v3 API. It turns out the Notion frontend is backed by a fairly intuitive and elegant API that was fun to reverse-engineer, and the result is both powerful and magical (hopefully in the best sense of the word). In addition to being able to read, write, and traverse most objects in Notion, I also integrated with the “push” system that makes the Notion UI so quick to update, resulting in two-way reactive data-binding that looks like this:

By this point, my mind was reeling at the potential. Notion was no longer just a productivity tool. It was now a general-purpose widget-rich responsive UI layer and data store that could serve as a dashboard, control panel, task manager, or a CRM system with mail-merge. It’s the holy grail of API-lovers: a central system, with a great UI and flexible schemas, into which all-the-things can be integrated.

As an example of how we’ll be using this at Learning Equality (plug: we’re currently hiring engineers and other roles!), one of the things we do is scrape open educational content from around the web, to distribute for use by communities with limited Internet, via Kolibri. We maintain dozens of scrapers that we re-run on a regular basis to keep our content repository up-to-date. We need to monitor the status of these long-running processes, and cross-reference them with other Notion databases like our task management system and roadmap. Happily, we can do ridiculous things like the following, powered by notion-py (source), using checkboxes as buttons and a code block as a real-time log viewer:

If you want to get started, it’s as simple as pip install notion— and I’ve included lots of examples and explanations on the GitHub README and the in the smoke tests. Contributions, suggestions, and questions are very welcome!

And if you love working on cool tech while also helping disadvantaged children and youth around the world to achieve a quality education, consider applying for one of our open jobs!

Thanks also to Notion for generously providing us with a free nonprofit account — we appreciate your support of our mission!

· · · · ·



Jamie Alexandre

Executive Director at @LearnEQ, makers of Kolibri: building #edtech to help offline learners and teachers succeed