Yankun Yang

Integrating Zotero with Obsidian: A Practical Guide for Zotero 8

This post is written with the assistance of Claude Sonnet 4.5(Anthropic).


When taking research notes, I wanted to browse my Zotero library directly within Obsidian and insert citations into Markdown files. Most tutorials online target older versions and don't account for the breaking changes in Zotero 8. This post documents a working setup as of 2025.

Choosing a Plugin

There are three main approaches for Obsidian × Zotero integration:

This guide uses the Citations plugin.

Requirements


Step 1: Install Better BibTeX

BBT is a Zotero plugin that generates stable citekeys and handles .bib exports.

  1. Go to the BBT Releases page and download the latest .xpi file
  2. In Zotero, go to Tools → Add-ons → click the gear icon in the top right → Install Add-on From File, and select the downloaded .xpi
  3. Restart Zotero

Step 2: Configure BBT to Auto-generate Citekeys

Under Zotero 8, BBT does not automatically generate citekeys for existing entries. You need to trigger this once manually, and then enable automatic generation going forward.

Bulk-generate citekeys for existing entries:

  1. Select My Library in the Zotero left panel
  2. Press Ctrl+A to select all entries
  3. Right-click → Better BibTeX → Refresh Citation Key

Enable automatic citekey generation for new entries:

Zotero → Edit → Settings → Better BibTeX → Citation Keys
→ Check "Regenerate citation key when item changes"

With this enabled, BBT will automatically generate a citekey whenever a new item is added to your library.

Step 3: Export Your Library as a .bib File

  1. Select My Library in the Zotero left panel
  2. File → Export Library
  3. Set the format to Better BibLaTeX
  4. Check Keep updated (this keeps the file in sync as you add new entries)
  5. Save it somewhere convenient, e.g. ~/references.bib

Step 4: Install the Citations Plugin in Obsidian

  1. In Obsidian, go to Settings → Community Plugins → disable Restricted Mode → Browse
  2. Search for Citations (by hans), install and enable it

Step 5: Configure the Citations Plugin

Go to Settings → Citations:

Close settings and restart Obsidian.

Step 6: Set Up a Literature Note Template

You can configure a template for the notes that Citations generates automatically.

Example Literature note content template:

---
title: |
  {{title}}
authors: |
  {{authorString}}
year: |
  {{year}}
url: |
  {{URL}}
---

## Abstract

{{abstract}}

Note: Putting abstract inside the YAML frontmatter (between ---) often causes parse failures because abstracts frequently contain colons, quotes, and other YAML-special characters. Keep it outside the frontmatter and use a ## Abstract heading instead.

Basic Usage

The search box supports queries by title, author, or citekey. Leaving it empty and pressing Enter shows all entries.


Troubleshooting

The search box only shows one entry

This is the most common issue. The root cause is almost always that citekey parsing fails, causing all entries to map to the same key and overwrite each other, leaving only one.

Cause 1: Citekeys are missing from the .bib file

Under Zotero 8, BBT sometimes fails to generate citekeys, producing entries like:

@article{   title = {...},

There is no citekey between @article{ and the first field. Fix this by following Step 2 — select all entries and run Refresh Citation Key.

Cause 2: Unsupported TeX commands such as \textbraceleft

The Citations plugin's BibTeX parser does not handle certain TeX commands and silently drops all subsequent entries when it encounters one. You can spot this in Obsidian's developer console (Ctrl+Shift+I → Console):

Citation plugin: non-fatal error loading BibLaTeX entry: TeXError: Unhandled command: textbraceleft

The fix is to exclude the abstract field from BBT exports, since abstracts are the most common source of problematic characters:

Zotero → Edit → Settings → Better BibTeX → Export
→ Fields to omit from export: abstract

Alternatively, switch to CSL-JSON export format, which bypasses the BibTeX parser entirely.

Cause 3: CSL-JSON entries are missing the id field

If you switch to CSL-JSON, BBT under Zotero 8 sometimes omits the id field from each record. Without it, Citations cannot read the citekey and the same overwrite problem occurs. The following script patches the file:

import json, re

with open('/home/yourname/references.json', encoding='utf-8') as f:
    data = json.load(f)

for item in data:
    if 'id' not in item:
        author = item.get('author', [{}])
        family = re.sub(r'[^a-z]', '', author[0].get('family', 'unknown').lower())
        issued = item.get('issued', {}).get('date-parts', [['']])
        year = str(issued[0][0]) if issued and issued[0] else ''
        title_words = item.get('title', '').split()
        word = re.sub(r'[^a-zA-Z]', '', title_words[0]).lower() if title_words else 'untitled'
        item['id'] = f'{family}{year}{word}'

with open('/home/yourname/references.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

print(f'Done, {len(data)} entries processed')

YAML frontmatter fails to parse in Literature Notes

Abstracts and titles often contain colons, quotes, or other characters that break YAML parsing when placed inside the frontmatter block. Move abstract outside the frontmatter as shown in the template in Step 6.


Summary

Once everything is set up, the workflow is seamless: add a paper in Zotero, BBT updates the .bib file automatically, and Ctrl+Shift+O in Obsidian lets you search and generate a literature note instantly. Most of the friction comes from BBT's compatibility with Zotero 8 — the steps above work around all the known issues.