Skip to main content

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) — sets DeletedAt timestamp; the note is hidden but recoverable via restore_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:

  1. Reads notes directly from the Note table via sqlite3.
  2. Parses the internal text format — each paragraph is prefixed with a \id=<uuid> block marker which is stripped on read and regenerated on write.
  3. Converts timestamps from Windows FILETIME (100-nanosecond ticks since 1601-01-01) to Python datetime objects.
  4. After writing, kills Microsoft.Notes.exe and relaunches the app via explorer.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

winotes-0.1.0.tar.gz (7.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

winotes-0.1.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

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

Hashes for winotes-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bfc9caaeef8cded6ee3481507d892f4ba71db3cc4c787b22719ff6a3f8de97fc
MD5 790ae0afd0e17ab7d66abdae2cb6a13d
BLAKE2b-256 b1a3df599023e0671520b88e5d514439b8a6821758bef8f374efc90efdeb3eb7

See more details on using hashes here.

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

Hashes for winotes-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7a788b959737125f8e1b8e545ef78e74b26c54ebc1b119adb5cf30b8b03035b6
MD5 e24e6a5d02577c67e1824ff6a186d96a
BLAKE2b-256 23f60f1aba8390ebf18b48d849b879690f6fe140ef776b4a8fab1072364f0342

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page