Automated Notion backups

I’ve been using Gitlab for years to manage my notes. It is free, secure, resilient, trusted by thousands of companies. GitLab is based on git meaning zero effort synchronization with any git-based service or your local copy.

Recently I discovered Notion, which makes it so pleasant to edit content. And what made me comfortable moving all my notes to Notion is an “Export all workspace content” feature, which generates a decent quality markdown.

The only thing I was missing is a regular automatic backup. I did a bit of investigation on how Notion’s backup feature works and set up my own daily exports to GitLab. It’s been working fine for the last two weeks, so today I will show how you can set up your own in a couple of minutes.

Note: this method might not be the best if you embed a lot of large files in your workspace.

1. Register GitLab account

Go to https://gitlab.com/ and get a free account if you don’t have one yet, it should be enough to backup up to 10Gb of data.

Optional. If you want some extra security — set up 2FA.

2. Extract notion token and space id

This is probably the most complicated step. Since Notion doesn’t have API yet, we would need to mimic Notion behavior in our backup script. To do so we need to extract token_v2 and spaceId from “Export all workspace content” request.

I will explain how to do it in Google Chrome:

  • Open http://notion.so/, go to “Settings & Members” → “Settings”
  • Open Chrome DevTools by pressing Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS)
  • Go to Network tab, as shown on a screenshot below
  • Enable “XHR” filter (1), clear console (2), start the export (3), select “enqueueTask” (4)

In the opened “Headers” tab you would need to scroll down until you see “cookie:” and a lot of text, in this text you need to identify a part, which looks like(5):

token_v2=xxx;

Where xxx is a very long sequence of letters and digits and can span multiple lines. Copy everything between “token_v2=” and “;” and save it somewhere. Label it NOTION_TOKEN_V2, we will need it later.

Now scroll to the very bottom and under “Request Payload” section you will see something like (6):

spaceId: “4489c211-09d6-4069-ae3b-1665e25d6c03”

Save the value inside quotes, label it NOTION_SPACE_ID.

3. Create push token in GitLab

In order to allow a script to update your backup, we need to generate a token with appropriate rights. On GitLab go to Settings → Access Tokens and fill the form as shown on the screenshot.

Once you press “Create Personal access token” you will see “Your new personal access token” only once, copy and save it, label it CI_PUSH_TOKEN, we will need it later.

4. Create a GitLab repository to store a backup

Create New Project, choose any “Project name” you like, make sure “Private” box is selected, so only you can access your backup, click “Create Project”

5. Set up CI/CD script

Once you create a project you will be redirected to the empty project page. Click the “Set up CI/CD” button.

It will open an editor for the .gitlab-ci.yml file. Paste a script which I prepared for you: https://gitlab.com/aburtsev/notion-backup-script/-/raw/master/.gitlab-ci.yml

This script mimics the behavior of the Notion backup feature, but instead of downloading zip file to your computer, it will upload it to your GitLab project.

Press “Commit changes”

6. Schedule a backup job

Once the script is ready, from the left-hand side menu select “CI / CD” → “Schedules”.

Press “New schedule”

That will open “Schedule a new pipeline” form, let's go field by field.

  • Description: anything you like (e.g Notion Backup)
  • Interval pattern: when do you want to run a backup. For example, mine runs at 4 am daily. Please pick a random minute from 0 to 59 and an hour from 0 to 23 when you want to run the backup. For example, if you want it to run at 5:42 am you should put “42 5 * * *” in. Please don’t just copy-paste this value to make sure everyone doesn’t hit Notion servers at the same time. You might find this schedule editor helpfu.
  • Cron Timezone: just pick your timezone
  • Target Brance: leave a master
  • Variables: That’s the values we’ve been collecting so far, plus few constants:
NOTION_TOKEN_V2     paste token_v2 from step 2
NOTION_SPACE_ID paste spaceId from step 2
CI_PUSH_TOKEN paste token from step 3
EXPORT_FILENAME /tmp/export.zip
PYTHONUNBUFFERED 1
TZ pick yours from https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
("TZ database name" column)

That’s it, now you can “Save pipeline schedule” and the new pipeline will appear in the list.

Now press the “play” button to run it manually and make sure it works. Wait a couple of minutes until the progress circle is green.

Optional. If you want to follow logs you can press a link in the “Last Pipeline” column and then select a running job.

Once a backup job is finished you can go to the project home page and notice a backup folder, you can go there and navigate through your contents, generated by Notion.

If you reached up to this point—congrats! You have your automated backups set up and it will run daily at the selected time. I hope it was helpful.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store