An unofficial Python wrapper for Windows Sticky Notes
Project description
winotes
An unofficial Python wrapper for Windows Sticky Notes, built by reverse-engineering the app's local SQLite database (plum.sqlite). No official API exists — this talks directly to the database and automatically restarts the app after every write so changes appear instantly.
Requirements
- Windows 10 / 11 with the Sticky Notes app installed
- Python 3.10+
- No third-party packages — stdlib only (
sqlite3,subprocess,uuid, etc.)
Installation
pip install winotes
Quick Start
from winotes import Winotes
sn = Winotes()
# List all notes
for note in sn.list_notes():
print(note["id"], note["theme"], note["text_plain"])
# Create a note
sn.create_note("Buy milk", theme="Blue")
# Update a note
sn.update_note(note_id, text="Buy oat milk", theme="Green")
# Delete a note (soft delete by default — recoverable)
sn.delete_note(note_id)
# Search notes
results = sn.search_notes("milk")
After any write, the app is automatically killed and relaunched so you see the changes immediately.
Custom DB Path
By default the wrapper finds the database at:
%LOCALAPPDATA%\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqlite
You can override this if needed:
sn = Winotes(db_path=r"C:\Users\you\...\plum.sqlite")
API Reference
Winotes(db_path=DEFAULT_DB_PATH)
Creates the wrapper. Raises FileNotFoundError if the database can't be found.
list_notes(include_deleted=False) → list[dict]
Returns all active notes. Pass include_deleted=True to also return soft-deleted notes.
Each note dict contains:
| Key | Type | Description |
|---|---|---|
id |
str |
UUID of the note |
text_plain |
str |
Content with internal block markers stripped |
text_raw |
str |
Raw content as stored in the DB |
theme |
str |
Colour theme (see themes below) |
is_open |
bool |
Whether the note window is open |
is_always_on_top |
bool |
Whether the note is pinned on top |
created_at |
datetime |
Creation time (UTC) |
updated_at |
datetime |
Last modified time (UTC) |
deleted_at |
datetime | None |
Deletion time, or None if active |
window_position |
str | None |
Raw window position string |
parent_id |
str |
ID of the parent user record |
get_note(note_id) → dict | None
Returns a single note by its ID, or None if not found.
create_note(text, theme="Yellow", is_open=True, is_always_on_top=False) → dict
Creates a new note and returns it. Restarts the app.
sn.create_note("hello world", theme="Pink")
sn.create_note("line one\nline two", theme="Blue", is_always_on_top=True)
update_note(note_id, text=None, theme=None, is_open=None, is_always_on_top=None) → dict | None
Updates any combination of fields on an existing note. Only the arguments you pass are changed. Returns the updated note, or None if not found. Restarts the app.
sn.update_note(note_id, text="updated content")
sn.update_note(note_id, theme="Charcoal", is_always_on_top=True)
delete_note(note_id, soft=True) → bool
Deletes a note. Returns True if a note was affected. Restarts the app.
soft=True(default) — setsDeletedAttimestamp; the note is hidden but recoverable viarestore_note().soft=False— permanently removes the row from the database.
restore_note(note_id) → dict | None
Clears the DeletedAt timestamp on a soft-deleted note, making it active again.
search_notes(query, case_sensitive=False) → list[dict]
Returns all active notes whose plain text contains query.
results = sn.search_notes("TODO")
results = sn.search_notes("API", case_sensitive=True)
Themes
The valid theme values are:
Yellow · Blue · Green · Pink · Purple · Gray · Charcoal
CLI Demo
Running the script directly prints a summary of all current notes:
python -m winotes
============================================================
WINOTES — current notes
============================================================
[Yellow ] 8b154dd4-a795-4c3e-b2cf-6aa7010e0937
Created : 2026-02-28 10:49
Preview : Hello!
How It Works
Windows Sticky Notes stores all data in a SQLite database (plum.sqlite) with no official access API. This wrapper:
- Reads notes directly from the
Notetable viasqlite3. - Parses the internal text format — each paragraph is prefixed with a
\id=<uuid>block marker which is stripped on read and regenerated on write. - Converts timestamps from Windows FILETIME (100-nanosecond ticks since 1601-01-01) to Python
datetimeobjects. - After writing, kills
Microsoft.Notes.exeand relaunches the app viaexplorer.exe shell:AppsFolder\...so it re-reads the database cleanly.
Caveats
- This relies on undocumented internals and could break if Microsoft changes the database schema in a future update.
- If Sticky Notes is syncing with a Microsoft account, externally created/modified notes may be overwritten by the next sync cycle.
- Hard-deleting a note (
soft=False) that exists on the server may cause sync conflicts.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file winotes-0.1.0.tar.gz.
File metadata
- Download URL: winotes-0.1.0.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bfc9caaeef8cded6ee3481507d892f4ba71db3cc4c787b22719ff6a3f8de97fc
|
|
| MD5 |
790ae0afd0e17ab7d66abdae2cb6a13d
|
|
| BLAKE2b-256 |
b1a3df599023e0671520b88e5d514439b8a6821758bef8f374efc90efdeb3eb7
|
File details
Details for the file winotes-0.1.0-py3-none-any.whl.
File metadata
- Download URL: winotes-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a788b959737125f8e1b8e545ef78e74b26c54ebc1b119adb5cf30b8b03035b6
|
|
| MD5 |
e24e6a5d02577c67e1824ff6a186d96a
|
|
| BLAKE2b-256 |
23f60f1aba8390ebf18b48d849b879690f6fe140ef776b4a8fab1072364f0342
|