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.
Metadata
Release files for winotes 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| winotes-0.1.0.tar.gz | 7.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| winotes-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.2 kB
Release files / winotes-0.1.0.tar.gz
| Download URL | winotes-0.1.0.tar.gz |
|---|---|
| Size | 7.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bfc9caaeef8cded6ee3481507d892f4ba71db3cc4c787b22719ff6a3f8de97fc
|
|
BLAKE2b-256 checksum How to use checksums |
b1a3df599023e0671520b88e5d514439b8a6821758bef8f374efc90efdeb3eb7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Release files / winotes-0.1.0-py3-none-any.whl
| Download URL | winotes-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7a788b959737125f8e1b8e545ef78e74b26c54ebc1b119adb5cf30b8b03035b6
|
|
BLAKE2b-256 checksum How to use checksums |
23f60f1aba8390ebf18b48d849b879690f6fe140ef776b4a8fab1072364f0342
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|