Simple Evernote client powered by a browser-captured web session
Project description
sloppynotes
A small Python library and CLI that reuses an authenticated Evernote web session without API keys.
Install the PyPI distribution as sloppynotes.
What this package does
This project reuses an already authenticated Evernote web session and then talks to Evernote's legacy NoteStore APIs.
How login works, and how this package avoids a separate API login
This package does not ask for Evernote API keys and does not implement a separate username/password login flow. Instead, it reuses the login state that already exists in a Chromium-based browser.
High-level flow:
- Launch or reuse a CDP-enabled Chromium/Chrome browser profile.
- Check whether Evernote is already logged in in that browser.
- Read the Evernote
authcookie from the logged-in browser session. - Extract the legacy monolith auth token and shard from that cookie.
- Save them to a local
evernote-auth.jsonfile.
Reverse-engineered details:
- The Evernote web client exchanges auth at:
https://accounts.evernote.com/auth/token
- That response contains tokens such as:
access_tokenrefresh_tokenid_token
- The
access_tokenpayload containsmono_authn_token, which is the legacy auth token used by older Evernote services. - The same monolith token is also available in the
authcookie for*.evernote.com. - This package reads that browser cookie and saves the minimal auth data needed for later API calls.
How this package reads notebooks and notes
After saving the auth token and shard, the package talks to Evernote's legacy NoteStore service.
The shard tells us which Evernote service URL to call, and the saved monolith token is used to authenticate those requests.
That is how the library and CLI can call methods such as:
listNotebooksfindNotesMetadatagetNote
Playwright is only needed for the browser side of the flow.
It connects to a Chromium-based browser over CDP so this package can detect the logged-in Evernote session and read the auth cookie.
Once evernote-auth.json has been saved, the later NoteStore API calls do not depend on Playwright; they use the saved auth together with the Thrift client code.
A short introduction to Thrift
Thrift is a remote procedure call and serialization system.
In practice, that means a client can call named backend methods such as listNotebooks and send structured request data in a format the server understands.
Evernote's older APIs use Thrift for services such as NoteStore and UserStore.
This project uses Python Thrift support to serialize those requests and parse the responses.
Legacy Evernote NoteStore/UserStore model:
Usage
Install
uv run --with sloppynotes -- evernote login
Login flow
For Faltoobot, reuse the shared browser so Evernote cookies come from the same browser session:
faltoobot browser https://www.evernote.com/client/web
uv run --with sloppynotes -- evernote login --use-existing-browser
You can also let evernote login launch its own browser profile when you are not using Faltoobot:
evernote login # saves login credentials to ~/.sloppynotes/evernote-auth.json
Usage from Python
from evernote.client import get_note, get_notes, get_notebooks, search_notes
notebooks = get_notebooks()
matching_notes = search_notes('intitle:"Project"')
notes = get_notes(notebooks[0])
note = get_note(notes[0])
These helpers return plain Python dictionaries. Typical shapes look like this:
notebooks = get_notebooks()
notebook = notebooks[0]
print(notebook)
# {
# "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
# "guid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
# "name": "Work",
# "defaultNotebook": False,
# "serviceCreated": 1710000000000,
# "serviceUpdated": 1710000000000,
# "updateSequenceNum": 12345,
# }
notes = get_notes(notebook)
note_summary = notes[0]
print(note_summary)
# {
# "id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
# "guid": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
# "title": "Project plan",
# "contentLength": 2048,
# "created": 1710000000000,
# "updated": 1710003600000,
# "notebookGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
# "tagGuids": ["zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz"],
# "updateSequenceNum": 23456,
# }
note = get_note(note_summary)
print(note)
# {
# "id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
# "guid": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
# "title": "Project plan",
# "content": "<?xml version=...>",
# "content_text": "Project plan\n- task 1\n- task 2",
# "contentLength": 2048,
# "created": 1710000000000,
# "updated": 1710003600000,
# "notebookGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
# "tagGuids": ["zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz"],
# "updateSequenceNum": 23456,
# }
Some optional keys may be missing when Evernote does not return them.
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 sloppynotes-2.0.0.tar.gz.
File metadata
- Download URL: sloppynotes-2.0.0.tar.gz
- Upload date:
- Size: 15.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf8068125dee5f39ebf5ab15b423c15bcf02c20e7b4f8bb76831e0309454b791
|
|
| MD5 |
0b0f4a97935284bccd271c54a4b6479d
|
|
| BLAKE2b-256 |
d71524f000f5b69d5b66873671841c32982ef3d3a504d4bd9bcb0409b792b21a
|
File details
Details for the file sloppynotes-2.0.0-py3-none-any.whl.
File metadata
- Download URL: sloppynotes-2.0.0-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a548fee4bd9ff10afb2dda5587184a19cc60cddf40dccbd0733d39b4ae9fb07a
|
|
| MD5 |
149d9e6f6d4e31858de30f65b958e862
|
|
| BLAKE2b-256 |
bd721f6844720e627fa042b29021c88f861e4dc55ce6c57373929f80860e7455
|