{"id":13689324,"url":"https://github.com/urschrei/pyzotero","last_synced_at":"2026-04-02T14:46:22.433Z","repository":{"id":1399785,"uuid":"1423403","full_name":"urschrei/pyzotero","owner":"urschrei","description":"Pyzotero: a Python client for the Zotero API","archived":false,"fork":false,"pushed_at":"2026-03-21T22:03:01.000Z","size":5807,"stargazers_count":1240,"open_issues_count":20,"forks_count":121,"subscribers_count":18,"default_branch":"main","last_synced_at":"2026-03-22T10:37:07.163Z","etag":null,"topics":["citations","digital-humanities","zotero"],"latest_commit_sha":null,"homepage":"https://pyzotero.readthedocs.org","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/urschrei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2011-02-28T21:31:44.000Z","updated_at":"2026-03-22T08:10:32.000Z","dependencies_parsed_at":"2023-10-01T17:24:27.664Z","dependency_job_id":"8064e020-b625-453d-852e-3113384e87da","html_url":"https://github.com/urschrei/pyzotero","commit_stats":{"total_commits":1165,"total_committers":30,"mean_commits":"38.833333333333336","dds":0.06437768240343344,"last_synced_commit":"6fde617d82e7e5d365e30e566170a70e4f04376b"},"previous_names":[],"tags_count":176,"template":false,"template_full_name":null,"purl":"pkg:github/urschrei/pyzotero","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urschrei%2Fpyzotero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urschrei%2Fpyzotero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urschrei%2Fpyzotero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urschrei%2Fpyzotero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/urschrei","download_url":"https://codeload.github.com/urschrei/pyzotero/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urschrei%2Fpyzotero/sbom","scorecard":{"id":912103,"data":{"date":"2025-08-11","repo":{"name":"github.com/urschrei/pyzotero","commit":"7c93e47671b1e03692e7191992056782261c3bbf"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.1,"checks":[{"name":"Code-Review","score":0,"reason":"Found 2/27 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/tests.yml:93","Warn: no topLevel permission defined: .github/workflows/tests.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":7,"reason":"6 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:69: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:96: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:100: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:106: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:113: update your workflow using https://app.stepsecurity.io/secureworkflow/urschrei/pyzotero/tests.yml/main?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   5 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: 'allow deletion' enabled on branch 'main'","Warn: 'force pushes' enabled on branch 'main'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'main'","Warn: 'stale review dismissal' is disabled on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is not required on branch 'main'","Warn: 'last push approval' is disabled on branch 'main'","Info: 'up-to-date branches' is required to merge on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.6.11 not signed: https://api.github.com/repos/urschrei/pyzotero/releases/207307857","Warn: release artifact v1.6.10 not signed: https://api.github.com/repos/urschrei/pyzotero/releases/207017782","Warn: release artifact v1.6.9 not signed: https://api.github.com/repos/urschrei/pyzotero/releases/200931333","Warn: release artifact v1.6.8 not signed: https://api.github.com/repos/urschrei/pyzotero/releases/196544484","Warn: release artifact v1.6.7 not signed: https://api.github.com/repos/urschrei/pyzotero/releases/196522073","Warn: release artifact v1.6.11 does not have provenance: https://api.github.com/repos/urschrei/pyzotero/releases/207307857","Warn: release artifact v1.6.10 does not have provenance: https://api.github.com/repos/urschrei/pyzotero/releases/207017782","Warn: release artifact v1.6.9 does not have provenance: https://api.github.com/repos/urschrei/pyzotero/releases/200931333","Warn: release artifact v1.6.8 does not have provenance: https://api.github.com/repos/urschrei/pyzotero/releases/196544484","Warn: release artifact v1.6.7 does not have provenance: https://api.github.com/repos/urschrei/pyzotero/releases/196522073"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/tests.yml:84"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-24T19:35:21.550Z","repository_id":1399785,"created_at":"2025-08-24T19:35:21.550Z","updated_at":"2025-08-24T19:35:21.550Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31308392,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["citations","digital-humanities","zotero"],"created_at":"2024-08-02T15:01:43.542Z","updated_at":"2026-04-02T14:46:22.424Z","avatar_url":"https://github.com/urschrei.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"[![Supported Python versions](https://img.shields.io/pypi/pyversions/Pyzotero.svg?style=flat)](https://pypi.python.org/pypi/Pyzotero/) [![Docs](https://readthedocs.org/projects/pyzotero/badge/?version=latest)](http://pyzotero.readthedocs.org/en/latest/?badge=latest) [![PyPI Version](https://img.shields.io/pypi/v/Pyzotero.svg)](https://pypi.python.org/pypi/Pyzotero) [![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyzotero/badges/version.svg)](https://anaconda.org/conda-forge/pyzotero) [![Downloads](https://pepy.tech/badge/pyzotero)](https://pepy.tech/project/pyzotero)\n\n# Pyzotero: An API Client for the Zotero API\n\n# Quickstart\n\n1. `uv add pyzotero` **or** `pip install pyzotero` **or** `conda install conda-forge::pyzotero`\n2. You'll need the ID of the personal or group library you want to access:\n    - Your **personal library ID** is available [here](https://www.zotero.org/settings/keys), in the section `Your userID for use in API calls`\n    - For **group libraries**, the ID can be found by opening the group's page: `https://www.zotero.org/groups/groupname`, and hovering over the `group settings` link. The ID is the integer after `/groups/`\n3. You'll also need\u003csup\u003e†\u003c/sup\u003e to get an **API key** [here][2]\n4. Are you accessing your own Zotero library? `library_type` is `'user'`\n5. Are you accessing a shared group library? `library_type` is `'group'`.\n\nThen:\n\n``` python\nfrom pyzotero import Zotero\nzot = Zotero(library_id, library_type, api_key)  # local=True for read access to local Zotero\nitems = zot.top(limit=5)\n# we've retrieved the latest five top-level items in our library\n# we can print each item's item type and ID\nfor item in items:\n    print(f\"Item: {item['data']['itemType']} | Key: {item['data']['key']}\")\n```\n\n# Documentation\n\nFull documentation of available Pyzotero methods, code examples, and sample output is available on [Read The Docs][3].\n\n# Installation\n\n* Using [uv][11]: `uv add pyzotero`\n* Using [pip][10]: `pip install pyzotero`\n* Using Anaconda: `conda install conda-forge::pyzotero`\n\nPyzotero also provides an optional [CLI](#command-line-interface) and [MCP server](#mcp-server) for working with a local Zotero library. Both require Zotero 7 with local API access enabled: Zotero \u003e Settings \u003e Advanced \u003e \"Allow other applications on this computer to communicate with Zotero\".\n\n# Command-Line Interface\n\nPyzotero includes an optional CLI for searching and querying your local Zotero library.\n\n## Installing the CLI\n\n* Using [uv][11]: `uv add \"pyzotero[cli]\"`\n* Using [pip][10]: `pip install \"pyzotero[cli]\"`\n\nOr run it directly without installing:\n\n* Using [uvx][11]: `uvx --from \"pyzotero[cli]\" pyzotero search -q \"your query\"`\n* Using [pipx][10]: `pipx run --spec \"pyzotero[cli]\" pyzotero search -q \"your query\"`\n\n## Usage\n\n```bash\n# Search for top-level items\npyzotero search -q \"machine learning\"\n\n# Search with full-text mode\npyzotero search -q \"climate change\" --fulltext\n\n# Filter by item type\npyzotero search -q \"methodology\" --itemtype book --itemtype journalArticle\n\n# Search for top-level items within a collection\npyzotero search --collection ABC123 -q \"test\"\n\n# Output as JSON for machine processing\npyzotero search -q \"climate\" --json\n\n# List all collections\npyzotero listcollections\n\n# List available item types\npyzotero itemtypes\n```\n\n## Search Behaviour\n\nBy default, `pyzotero search` searches only top-level item titles and metadata fields.\n\nWhen the `--fulltext` flag is used, the search expands to include all full-text indexed content, including PDFs and other attachments. Since most full-text content comes from PDF attachments rather than top-level items, the CLI automatically retrieves the parent bibliographic items for any matching attachments. This ensures you receive useful bibliographic records (journal articles, books, etc.) rather than raw attachment items.\n\n## Output Format\n\nBy default, the CLI outputs human-readable text with a subset of metadata including:\n- Title, authors, date, publication\n- Volume, issue, DOI, URL\n- PDF attachments (with local file paths)\n\nUse the `--json` flag to output structured JSON.\n\n# MCP Server\n\nPyzotero includes an optional [MCP](https://modelcontextprotocol.io) server that exposes your local Zotero library and Semantic Scholar integration as tools for LLMs. This lets sandboxed applications such as Claude Desktop access your Zotero library without needing direct CLI access.\n\n## Installing the MCP server\n\n* Using [uv][11]: `uv add \"pyzotero[mcp]\"`\n* Using [pip][10]: `pip install \"pyzotero[mcp]\"`\n* As a standalone tool: `uv tool install \"pyzotero[mcp]\"`\n\n## Claude Desktop Configuration\n\nAdd the following to your Claude Desktop configuration file:\n\nIf `pyzotero-mcp` is installed:\n\n```json\n{\n  \"mcpServers\": {\n    \"zotero\": {\n      \"command\": \"pyzotero-mcp\"\n    }\n  }\n}\n```\n\nOr, without installing, using uvx:\n\n```json\n{\n  \"mcpServers\": {\n    \"zotero\": {\n      \"command\": \"uvx\",\n      \"args\": [\"--from\", \"pyzotero[mcp]\", \"pyzotero-mcp\"]\n    }\n  }\n}\n```\n\n## Available Tools\n\n### Zotero Library Tools\n\n| Tool | Description |\n|------|-------------|\n| `search` | Search the local Zotero library by query, item type, collection, tag, or full-text content |\n| `get_item` | Get a single Zotero item by its key |\n| `get_children` | Get child items (attachments, notes) of a Zotero item |\n| `list_collections` | List all collections in the library |\n| `list_tags` | List all tags, optionally filtered by collection |\n| `get_fulltext` | Get full-text content of a PDF or other attachment |\n\n### Semantic Scholar Tools\n\n| Tool | Description |\n|------|-------------|\n| `find_related` | Find semantically similar papers using SPECTER2 embeddings |\n| `get_citations` | Find papers that cite a given paper |\n| `get_references` | Find papers referenced by a given paper |\n| `search_semantic_scholar` | Search across Semantic Scholar's paper index |\n\nThe Semantic Scholar tools can optionally check whether results already exist in your local Zotero library (enabled by default via the `check_library` parameter).\n\n# Development\n\n## Installing from Source\n\n``` bash\ngit clone git://github.com/urschrei/pyzotero.git\ncd pyzotero\ngit checkout main\n# specify --dev if you're planning on running tests\nuv sync\n```\n\n## Testing\n\nRun `pytest .` from the top-level directory. This requires the `dev` dependency group to be installed: `uv sync --dev` / `pip install --group dev`\n\n## Issues\n\nThe latest commits can be found on the [main branch][9], although new features are currently rare. If you encounter an error, please open an issue.\n\n## Pull Requests\n\nPull requests are welcomed. Please read the [contribution guidelines](CONTRIBUTING.md). In particular, please **base your PR on the `main` branch**.\n\n## Versioning\n\nAs of v1.0.0, Pyzotero is versioned according to [Semver](http://semver.org); version increments are performed as follows:\n\n1. MAJOR version will increment with incompatible API changes,\n2. MINOR version will increment when functionality is added in a backwards-compatible manner, and\n3. PATCH version will increment with backwards-compatible bug fixes.\n\n# Citation\n\nPyzotero has a DOI:\n[![DOI](https://zenodo.org/badge/1423403.svg)](https://zenodo.org/badge/latestdoi/1423403)\nYou may also cite Pyzotero using [CITATION.cff](CITATION.cff).\nA sample citation (APA 6th edition) might look like:\n\u003e Stephan Hügel, The Pyzotero Authors (2019, May 18). urschrei/pyzotero: Version v1.3.15. http://doi.org/10.5281/zenodo.2917290\n\n# License\n\nPyzotero is licensed under the [Blue Oak Model Licence 1.0.0][8]. See [LICENSE.md](LICENSE.md) for details.\n\n[1]: https://www.zotero.org/support/dev/web_api/v3/start\n[2]: https://www.zotero.org/settings/keys/new\n[3]: http://pyzotero.readthedocs.org/en/latest/\n[7]: https://nose2.readthedocs.io/en/latest/\n[8]: https://opensource.org/license/blue-oak-model-license\n[9]: https://github.com/urschrei/pyzotero/tree/main\n[10]: http://www.pip-installer.org/en/latest/index.html\n[11]: https://docs.astral.sh/uv\n† This isn't strictly true: you only need an API key for personal libraries and non-public group libraries.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furschrei%2Fpyzotero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Furschrei%2Fpyzotero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furschrei%2Fpyzotero/lists"}