Syncing Obsidian Notes to Notion by Python Script (Part 1) - Append Content to Existing Pages
Introduction Recently, I started using an app called Obsidian to manage my notes. To explain the background a little, I used to rely entirely on Notion for note management. However, because Notion felt somewhat "uncomfortable for casual writing," and also because I wanted to try out a tool like Obsidian, I decided to stop writing notes directly in Notion. That said, I still continue to use Notion. My current workflow is to first jot down rough notes in Obsidian, then later organize and polish them before transferring them to Notion. Initially, for these rough, preliminary notes before moving them to Notion, I used apps like the Mac default Notes app and Stickies. However, I eventually found Obsidian much more convenient, and now I mainly rely on Obsidian for all my daily notes. Every week, I go through these notes, polish and clean them up, delete the unnecessary ones, and transfer only the important ones to Notion. However, I ran into one major issue: the process of organizing and polishing the notes was extremely time-consuming. While the act of refining notes itself is important for organizing thoughts, in practice, it involved a lot of meaningless administrative tasks such as: Copy-pasting notes back and forth between apps Manually entering a UID (unique ID) into Notion’s properties Marking the notes as "Transferred" after copying them These tasks caused a lot of unnecessary stress. Having an environment where you can casually capture thoughts and ideas is crucial for creative work and intellectual productivity. However, when unnecessary "noise" like this accumulates, it makes taking notes feel like a burden. Naturally, I began to think, "I want to automate as much of this as possible." At first, it was just a casual thought, but I started researching whether there was any way to address this issue using ChatGPT and other resources online. Through that process, I discovered that Python scripts could help automate the workflow. By introducing automation, I realized that it could dramatically reduce the workload, far beyond what I had initially expected. Over the past few days of experimenting, I was able to significantly cut down the time spent on note management and greatly improve my work environment! That said, it wasn't an easy journey. While I occasionally write simple articles on Dev.to about Python, I am mostly self-taught and still have a lot to learn. However, this project taught me a lot, and I wanted to document and share my experience — both as a personal record and in the hope that it might help others — by writing this article on Dev.to. Since the scripts I created have several different features, I plan to introduce them over multiple articles instead of covering everything at once. In this first article, I will introduce a Python script that automatically transfers notes written in Obsidian into a Notion database. What This Article Will Cover First, let me briefly explain my Notion setup. In Notion, I have a database called Daily Journal, where a new daily note is automatically created each morning. These notes follow a naming convention like "25/Apr/25." In this Daily Journal, I usually record: Important events or reflections from the day that I want to keep Ideas or inspirations that came to mind during the day I write these entries freely and casually (and if nothing noteworthy happens, I simply leave it blank for that day). Currently, while I sometimes write directly in Notion, as I mentioned earlier, most of my notes are captured in Obsidian. So once a week, I review the past week's notes, clean them up, delete unnecessary ones, and manually transfer the polished ones into Notion. Since my notes in Obsidian tend to be rough, almost like scribbles, the transfer process involves rewriting and polishing them before entering them into Notion. However, this manual process inevitably takes a lot of time and effort. Therefore, the goal of this article is to show how to automate the transfer process using a Python script. For the sake of explanation, I’ll use my Daily Journal database as the example here, but the approach is not limited to daily notes. The method of transferring content from Obsidian into an existing Notion database can easily be adapted for other use cases as well. Feel free to adjust the code and settings according to your own workflow. Setting Up Notion First, let's start by setting up Notion. In this script, we will directly edit and add notes to Notion through the Notion API. To do this, you’ll need to prepare the following on the Notion side: 1. Obtain the Notion Internal Integration Secret First, log in to Notion and access the Integration page. Click "+ New integration." Give it any name you like (e.g., "Obsidian Sync"). Select your own workspace under "Associated workspace" and follow the prompts to complete the submission. After registering, open the Integration you created and copy the Internal I

Introduction
Recently, I started using an app called Obsidian to manage my notes. To explain the background a little, I used to rely entirely on Notion for note management. However, because Notion felt somewhat "uncomfortable for casual writing," and also because I wanted to try out a tool like Obsidian, I decided to stop writing notes directly in Notion.
That said, I still continue to use Notion. My current workflow is to first jot down rough notes in Obsidian, then later organize and polish them before transferring them to Notion.
Initially, for these rough, preliminary notes before moving them to Notion, I used apps like the Mac default Notes app and Stickies. However, I eventually found Obsidian much more convenient, and now I mainly rely on Obsidian for all my daily notes. Every week, I go through these notes, polish and clean them up, delete the unnecessary ones, and transfer only the important ones to Notion.
However, I ran into one major issue: the process of organizing and polishing the notes was extremely time-consuming.
While the act of refining notes itself is important for organizing thoughts, in practice, it involved a lot of meaningless administrative tasks such as:
Copy-pasting notes back and forth between apps
Manually entering a UID (unique ID) into Notion’s properties
Marking the notes as "Transferred" after copying them
These tasks caused a lot of unnecessary stress. Having an environment where you can casually capture thoughts and ideas is crucial for creative work and intellectual productivity. However, when unnecessary "noise" like this accumulates, it makes taking notes feel like a burden. Naturally, I began to think, "I want to automate as much of this as possible."
At first, it was just a casual thought, but I started researching whether there was any way to address this issue using ChatGPT and other resources online. Through that process, I discovered that Python scripts could help automate the workflow. By introducing automation, I realized that it could dramatically reduce the workload, far beyond what I had initially expected. Over the past few days of experimenting, I was able to significantly cut down the time spent on note management and greatly improve my work environment!
That said, it wasn't an easy journey. While I occasionally write simple articles on Dev.to about Python, I am mostly self-taught and still have a lot to learn. However, this project taught me a lot, and I wanted to document and share my experience — both as a personal record and in the hope that it might help others — by writing this article on Dev.to.
Since the scripts I created have several different features, I plan to introduce them over multiple articles instead of covering everything at once.
In this first article, I will introduce a Python script that automatically transfers notes written in Obsidian into a Notion database.
What This Article Will Cover
First, let me briefly explain my Notion setup. In Notion, I have a database called Daily Journal, where a new daily note is automatically created each morning. These notes follow a naming convention like "25/Apr/25."
In this Daily Journal, I usually record:
- Important events or reflections from the day that I want to keep
- Ideas or inspirations that came to mind during the day
I write these entries freely and casually (and if nothing noteworthy happens, I simply leave it blank for that day).
Currently, while I sometimes write directly in Notion, as I mentioned earlier, most of my notes are captured in Obsidian. So once a week, I review the past week's notes, clean them up, delete unnecessary ones, and manually transfer the polished ones into Notion. Since my notes in Obsidian tend to be rough, almost like scribbles, the transfer process involves rewriting and polishing them before entering them into Notion.
However, this manual process inevitably takes a lot of time and effort.
Therefore, the goal of this article is to show how to automate the transfer process using a Python script.
For the sake of explanation, I’ll use my Daily Journal database as the example here, but the approach is not limited to daily notes. The method of transferring content from Obsidian into an existing Notion database can easily be adapted for other use cases as well. Feel free to adjust the code and settings according to your own workflow.
Setting Up Notion
First, let's start by setting up Notion.
In this script, we will directly edit and add notes to Notion through the Notion API.
To do this, you’ll need to prepare the following on the Notion side:
1. Obtain the Notion Internal Integration Secret
First, log in to Notion and access the Integration page.
- Click "+ New integration."
- Give it any name you like (e.g., "Obsidian Sync").
- Select your own workspace under "Associated workspace" and follow the prompts to complete the submission.
- After registering, open the Integration you created and copy the Internal Integration Secret (like a token) displayed there.
Example:
ntn_xxxxxxxxxxxxxxxxxxxxx
This is like a password for using the API, so be sure to store it securely.
2. Obtain the Notion Database ID
Step 1 (Check from the URL)
Next, let's get the Database ID.
In my case, I want to access my Daily Journal DB, so I open its URL in Notion.
- Open the relevant database in Notion.
- Example URL:
https://www.notion.so/workspace/25Apr25-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- The xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx part is your Database ID.
Step 2 (Confirm the Connection to the Integration)
- Open the page for the relevant database in Notion.
- Click "..." at the top right → "Add Connections" → Select the Integration you created.
- Once connected, your Integration will have permission to read and write to that database.
With these steps, you should now have:
- The Integration Secret
- The Database ID
- Proper permissions granted to the Integration
Please note that minor differences may occur depending on updates, and this reflects the process at the time of writing.
Always refer to the official Notion documentation for the latest instructions.
Setting Up Obsidian
No special plugins or complicated configurations are needed on the Obsidian side to use this Python script.
You only need two things:
Save the notes (Markdown files) you want to send into a specific Inbox folder.
Add a YAML Frontmatter (metadata wrapped between ---) at the beginning of each note.
Example structure of an Obsidian note:
---
uid: 20250425150201
title: Test Note
tags:
- WIP
- ToDaily
created: April 25, 2025 6:45 AM
updated: April 25, 2025 6:46 AM
---
The main body of the note goes here.
Key Points:
uid is a unique identifier (you can just use a timestamp).
Include WIP in the tags to indicate the note has not yet been transferred (after transfer, it can be replaced with DONE).
The destination database will be determined based on the tags.
(In this article’s example, we use the ToDaily tag.)
In my case, I usually set the filename of the Markdown file to match the uid (you can automate this with a plugin or do it manually), and I set the visible title in the title metadata.
For this article, I’m using a simple folder structure for Obsidian:
/
├── Inbox ← Where you save your notes (Markdown files)
└── Archives ← Where you move notes after transferring them
Normally, you collect notes in the Inbox.
Then, at regular intervals (e.g., once a week), you review, clean up, delete unnecessary notes, and polish the rest — before executing the script to transfer them to Notion.
This setup is based on my own workflow but simplified for this article.
Feel free to customize it as needed to suit your own environment.
Python Side: About the Script
Now, let's move on to the actual Python code.
This script performs the following steps:
- Read each
.md
file stored in the Inbox folder in Obsidian. - Separate the YAML metadata from the body content.
- Use the Notion API to create an entry in the Daily Journals database.
- Depending on the tags in the Obsidian note, determine which Notion database to send the content to.
(In this article’s case, if the note has the
ToDaily
tag, it will be transferred to the Daily Journals database.) - After the transfer is complete, update the tag in the original file to
DONE
and move the file to the Archive folder.
Summary Diagram of the Overall Flow
- Obsidian (Inbox folder)
↓
- Run Python Script
↓
- Add an entry to Daily Journals
↓
- Move file to Obsidian (Archive folder)
Running the Python Script
Now, let's move on to creating and running the actual script.
In this article, we'll keep things simple and focus solely on "automatically transferring notes from Obsidian to Notion," introducing only the minimum necessary code without detailed explanations.
As a preparation step, you will need to store the Notion Integration information (like API keys) in an environment variable file (.env
).
Once that's done, save the following Python script as a .py
file.
import os
import shutil
import requests
from datetime import datetime
from dotenv import load_dotenv
# === Load environment variables ===
load_dotenv()
NOTION_TOKEN = os.getenv("NOTION_TOKEN")
DAILY_DB = os.getenv("DAILY_DB")
OBSIDIAN_INBOX = os.getenv("OBSIDIAN_INBOX")
OBSIDIAN_ARCHIVE = os.getenv("OBSIDIAN_ARCHIVE")
headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
def get_target_date_from_filename(filename):
date_obj = datetime.strptime(filename[:8], "%Y%m%d")
return date_obj.strftime("%d/%b/%y")
def query_notion_page_by_title(database_id, target_title):
url = f"https://api.notion.com/v1/databases/{database_id}/query"
query = {
"filter": {
"property": "Name",
"title": {
"equals": target_title
}
}
}
response = requests.post(url, headers=headers, json=query)
if response.status_code != 200:
print(f"[Error] Notion API error: {response.status_code} / {response.text}")
return None
data = response.json()
if data.get("results"):
return data["results"][0]["id"]
return None
def append_toggle_to_page(page_id, uid, body):
block = {
"object": "block",
"type": "toggle",
"toggle": {
"rich_text": [{
"type": "text",
"text": {"content": f"OBS_LOG : {uid}"}
}],
"children": [{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{
"type": "text",
"text": {"content": body[:2000]}
}]
}
}]
}
}
url = f"https://api.notion.com/v1/blocks/{page_id}/children"
response = requests.patch(url, headers=headers, json={"children": [block]})
return response.status_code == 200
def main():
for filename in os.listdir(OBSIDIAN_INBOX):
if not filename.endswith(".md"):
continue
filepath = os.path.join(OBSIDIAN_INBOX, filename)
with open(filepath, "r", encoding="utf-8") as f:
note_content = f.read()
if "WIP" not in note_content:
print(f"[Skip] {filename} (no WIP tag)")
continue
uid = filename.split(".")[0]
date_title = get_target_date_from_filename(filename)
# Add content to Daily Journal
daily_page_id = query_notion_page_by_title(DAILY_DB, date_title)
if daily_page_id:
success = append_toggle_to_page(daily_page_id, uid, note_content)
if success:
print(f"[Daily] {filename} → {date_title}")
# Only on successful transcription WIP to DONE and archive
updated_content = note_content.replace("WIP", "DONE")
with open(filepath, "w", encoding="utf-8") as f:
f.write(updated_content)
shutil.move(filepath, os.path.join(OBSIDIAN_ARCHIVE, filename))
print(f"[Archive] {filename} moved to Archive")
else:
print(f"[Error] Failed to append {filename} to Notion.")
else:
print(f"[Error] Daily Journal not found for {filename}")
if __name__ == "__main__":
main()
By running this script, it will:
- Scan the
.md
files stored in Obsidian’s Inbox folder - Extract the date (e.g.,
20250425
) from the filename and search for the corresponding Daily Journal page in Notion - If a matching page is found, append only the body text to that Daily Journal
- Ensure that Obsidian notes have the
WIP
tag; notes withoutWIP
will be skipped - (Only if the transfer is successful) Update the
WIP
tag toDONE
- (Only if the transfer is successful) Move the file to the Archive folder
All of these actions will be handled automatically!
Conclusion
This article may have been a little more complex than usual, and some parts might have been difficult to follow — I apologize for that.
Obsidian and Notion are both extremely popular tools today. However, there may not be many people who actively combine and integrate the two, like I do.
I hope this article can offer some ideas or inspiration to those exploring similar workflows.
Even though I am still a beginner in Python, I was able to successfully build this system by leveraging ChatGPT and doing research.
The setup is also relatively easy to customize according to your own needs, so if you're interested, I encourage you to give it a try!
As I mentioned at the beginning, I have been working on several other scripts to make Obsidian and Notion even more convenient to use together.
This time, I introduced just one of them, but if I get another opportunity, I would love to share more of my experiments and projects.
Thank you very much for reading to the end!