user = os.environ['ANKI_USER']
passw = os.environ['ANKI_PASS']Core API
OO API
data_path
data_path ()
Return the default Anki data folder for this OS.
data_path()Path('/app/data/.local/share/Anki2')
profiles
profiles ()
List available Anki profile names.
profiles()['User 1']
Collection.open
Collection.open (profile='User 1')
Open a collection by profile name (creates if needed).
Class method to open a collection by profile name. Handles backend reuse, creates profile folder if needed, and stores profile_path for auth persistence.
col = Collection.open()
col.profile_pathPath('/app/data/.local/share/Anki2/User 1')
Collection.load_auth
Collection.load_auth ()
Load SyncAuth from profile folder, or None if not found.
Collection.save_auth
Collection.save_auth (auth)
Persist SyncAuth to profile folder.
Auth persistence methods: save_auth writes the SyncAuth protobuf to disk, load_auth reads it back. The endpoint is crucial — AnkiWeb may redirect you to a different sync server.
Collection.sync
Collection.sync (user=None, passw=None, media=True)
Full sync implementation: loads saved auth (or logs in), handles endpoint changes, re-authenticates on failure, and manages full upload/download when required.
# First sync requires credentials
col.sync(user=user, passw=passw)
# Subsequent syncs use saved auth
col.sync()close_all
close_all ()
Close all open Anki backends (nuclear option for crash recovery).
Nuclear option for crash recovery — scans all Python objects to find and close any open Rust backends.
col.models- Basic
- Basic (and reversed card)
- Basic (optional reversed card)
- Basic (type in the answer)
- Cloze
- Image Occlusion
Markdown representations for decks. DeckManager lists deck names, DeckNameId shows name/id, DeckTreeNode shows name with due counts.
col.sched.deck_due_tree().children[0]Default: 2 new, 0 learn, 0 review
col.decks- Default
Enables dict-style access: col.models['Basic'] returns the model dict, col.decks['Default'] returns the deck id.
mdl = col.models['Basic']
mdl['id']1764648511131
Note.__repr__
Note.__repr__ ()
Return repr(self).
note = col.new_note(mdl)
note['Front'], note['Back'] = 'hola', 'hello'
noteFront: hola | Back: hello
Deck
Deck (col, name)
Initialize self. See help(type(self)) for accurate signature.
Wrapper class for a deck with convenient .add(), .due (new/learn/review counts), and .cards (list of card ids).
DeckManager.__getitem__
DeckManager.__getitem__ (name)
Collection.add
Collection.add (model='Basic', deck='Default', tags=None, **fields)
Add a note with the given fields.
Convenient method to add a note with keyword arguments for fields. Defaults to Basic model and Default deck.
note2 = col.add(Front='hola', Back='hello', tags=['spanish'])Collection.add_deck
Collection.add_deck (name)
Create a deck (use :: for nesting).
Creates a new deck. Use :: for nested decks (e.g. "Spanish::Vocab" creates Vocab inside Spanish).
col.add_deck('Spanish::Vocab')changes {
deck: true
browser_table: true
browser_sidebar: true
study_queues: true
mtime: true
}
id: 1764727764420
deck = col.decks['Spanish::Vocab']
deck.add(Front='adiós', Back='goodbye')
deck.dueVocab: 1 new, 0 learn, 0 review
col.remove_notes([note2.id])✓ 1 change(s)
col.decks.remove([col.decks.id_for_name('Spanish')])✓ 1 change(s)
col.sync()host_number: 5
Deck.__repr__
Deck.__repr__ ()
Return repr(self).
Card.__repr__
Card.__repr__ ()
Return repr(self).
OpChangesWithCount.__repr__
OpChangesWithCount.__repr__ ()
Return repr(self).
DeckTreeNode.__repr__
DeckTreeNode.__repr__ ()
Return repr(self).
DeckNameId.__repr__
DeckNameId.__repr__ ()
Return repr(self).
DeckManager.__repr__
DeckManager.__repr__ ()
Return repr(self).
NotetypeNameId.__repr__
NotetypeNameId.__repr__ ()
Return repr(self).
ModelManager.__repr__
ModelManager.__repr__ ()
Return repr(self).
col.close()Functional API
Collection.__exit__
Collection.__exit__ (*args)
Collection.__enter__
Collection.__enter__ ()
You can use Collection with Python’s with statement. This ensures the collection is always properly closed, even if an error occurs during your operations. No more orphaned database locks or forgotten cleanup calls.
with Collection.open() as col: note = col.add(Front='hola', Back='hello')add_card
add_card (profile='User 1', model='Basic', deck='Default', tags=None, **fields)
Add a card.
add_card lets you create a new card with a single function call. Just pass your field values as keyword arguments. By default it uses the Basic note type and Default deck, but you can specify any model, deck, or tags you like.
notezh = add_card(Front='你好', Back='hello')add_fb_card
add_fb_card (front:str, back:str, profile:str='User 1', model:str='Basic', deck:str='Default', tags:str=None)
Add a card with a Front and Back and return the id.
find_cards
find_cards (query:str, profile:str='User 1')
Find cards matching query string. Returns list of Note objects.
find_cards searches your collection and returns a list of Card objects. Pass any Anki search query as the first argument. Common query patterns: - deck:Spanish — cards in a specific deck - tag:vocab — cards with a tag - front:hello — match field content - is:due — cards due for review - added:7 — added in the last 7 days
Combine with spaces (AND) or OR: deck:Spanish tag:verb finds Spanish cards tagged “verb”.
cards = find_cards("deck:Default")
cards[Card(1764724348706, nid=1764724348705, due=40, ivl=0, queue=0),
Card(1764724348737, nid=1764724348737, due=41, ivl=0, queue=0),
Card(1764727786774, nid=1764727786773, due=44, ivl=0, queue=0),
Card(1764727801198, nid=1764727801198, due=45, ivl=0, queue=0)]
cards[0]Card 1764724348706 (nid: 1764724348705, due: 40, ivl: 0d, queue: 0)
find_card_ids
find_card_ids (query:str, profile:str='User 1')
Find card ids matching query string.
find_card_ids("deck:Default")[1764724348706, 1764724348737, 1764727786774, 1764727801198]
find_notes
find_notes (query:str, profile:str='User 1')
Find notes matching query string. Returns list of Note objects.
find_notes searches your collection and returns a list of Note objects (rather than Card objects). The query language is the same as find_cards — all the same search patterns work. The difference is that find_notes returns one result per note, while find_cards may return multiple cards if a note generates more than one card (e.g., with Cloze or Basic-and-Reversed note types).
notes = find_notes("hello")
notes[Note(1764727786773, Front='hola', Back='hello', tags=[]),
Note(1764727801198, Front='你好', Back='hello', tags=[])]
note = notes[0]
noteFront: hola | Back: hello
find_note_ids
find_note_ids (query:str, profile:str='User 1')
Find note ids matching query string.
find_note_ids("hello")[1764727786773, 1764727801198]
update_note
update_note (note:int, profile:str='User 1', tags:str=None, add_tags:str=None, **fields)
Update an existing note’s fields and/or tags. Pass a Note object or note ID.
update_note modifies an existing note’s fields and/or tags. Pass either a Note object or a note ID, along with any fields you want to change as keyword arguments. For tags: - tags=['a','b'] — replaces all tags - add_tags='newtag' — adds without removing existing tags
update_note(note, Back="updated answer", tags='testtag')Front: hola | Back: updated answer | 🏷️ testtag
update_note(note, add_tags='moretagz')Front: hola | Back: updated answer | 🏷️ testtag, moretagz
update_fb_note
update_fb_note (note_id:int, front:str='', back:str='', profile:str='User 1', tags:str=None, add_tags:str=None)
Update an existing note’s front/back fields and/or tags. Pass a Note object or note ID.
update_fb_note(note, front='I am new')Front: I am new | Back: updated answer | 🏷️ testtag, moretagz
get_note
get_note (note_id:int, profile:str='User 1')
Retrieve a note by ID.
get_note(note.id)Front: I am new | Back: updated answer | 🏷️ moretagz, testtag
del_card
del_card (notes:int, profile:str='User 1')
Delete card(s) by Note(s) or note id(s).
del_card([notezh, note])✓ 2 change(s)
sync
sync (profile:str='User 1', user:str=None, passw:str=None, media:bool=True)
Sync collection, handling open/close automatically.
sync handles the entire sync lifecycle for you — opening the collection, authenticating with AnkiWeb, syncing, and closing up afterwards. The first time you sync, pass your AnkiWeb credentials; they’ll be saved for future use.
sync(user=user, passw=passw) # First time
# sync() # after thathost_number: 5
anki_tools
anki_tools ()