Fetching contributors…
Cannot retrieve contributors at this time
977 lines (607 sloc) 36.6 KB


Pyzotero is a Python wrapper for the Zotero API (v3).

Getting started (short version)

  1. In a shell / prompt: pip install pyzotero
  2. You'll need the ID of the personal or group library you want to access:
  • Your personal library ID is available here, in the section Your userID for use in API calls
  • For group libraries, the ID can be found by opening the group's page:, and hovering over the group settings link. The ID is the integer after /groups/
  1. You'll also need [*] to get an API key from the Zotero site
  2. Are you accessing your own Zotero library? library_type is user
  3. Are you accessing a shared group library? library_type is group

Refer to the :ref:`read` and :ref:`write`.

Installation, testing, usage (longer version)


Using pip: pip install pyzotero As of v1.0.0, Pyzotero is also available as a wheel.

From a local clone, if you wish to install Pyzotero from a specific branch:

git clone git://
cd pyzotero
git checkout dev
pip install .

The Pyzotero source tarball is also available from PyPI

The feedparser (>= 0.5.1), pytz , and Requests libraries are required. They will be automatically installed when installing Pyzotero using pip. For versions of Python below 2.7, the ordereddict module is also required. This optional dependency can be included with Pyzotero with the command pip install pyzotero[ordereddict].

Installing development versions

Pyzotero remains in development as of February 2015. Unstable development versions can be found on the Github dev branch, and installed directly from there using pip: pip install -e git+, or from the checked-out dev branch on a local clone, as in the example above.


Testing requires the Nose, HTTPretty, and Python-Dateutil packages.

Run in the pyzotero/test directory, or, using Nose, nosetests from the top-level directory. If you wish to see coverage statistics, run nosetests --with-coverage --cover-package=pyzotero.

Building Documentation

If you wish to build Pyzotero's documentation for offline use, it can be built from the doc directory of a local git repo by running make followed by the desired output format(s) (html, epub, latexpdf etc.)

This functionality requires Sphinx. See the Sphinx documentation for full details.

Reporting issues

If you encounter an error while using Pyzotero, please open an issue on its Github issues page.

General Usage


A given Zotero instance is bound to the library or group used to create it. Thus, if you create a Zotero instance with a library_id of 67 and a library_type of group, its item methods will only operate upon that group. Similarly, if you create a Zotero instance with your own library_id and a library_type of user, the instance will be bound to your Zotero library.

First, create a new Zotero instance:


Read API Methods


All search/request parameters inside square brackets are optional. Methods such as :py:meth:``, :py:meth:`Zotero.items()` etc. can be called with no additional parameters if you wish.


The Read API returns 25 results by default (the API documentation claims 50). In the interests of usability, Pyzotero returns 100 items by default, by setting the API limit parameter to 100, unless it's set by the user. If you wish to retrieve e.g. all top-level items without specifiying a limit parameter, you'll have to wrap your call with :py:meth:`Zotero.everything()`: results = zot.everything(

Retrieving Items


In contrast to the v1 API, a great deal of additional metadata is now returned. In most cases, simply accessing items by referring to their item['data'] key will suffice.

The following methods will retrieve either user or group items, depending on the value (user or group) used to create the Zotero instance:

Example of returned item data:

[{u'data': {u'ISBN': u'0810116820',
           u'abstractNote': u'',
           u'accessDate': u'',
           u'archive': u'',
           u'archiveLocation': u'',
           u'callNumber': u'HIB 828.912 BEC:3g N9',
           u'collections': [u'2UNGXMU9'],
           u'creators': [{u'creatorType': u'author',
                          u'firstName': u'Daniel',
                          u'lastName': u'Katz'}],
           u'date': u'1999',
           u'dateAdded': u'2010-01-04T14:50:40Z',
           u'dateModified': u'2014-08-06T11:28:41Z',
           u'edition': u'',
           u'extra': u'',
           u'itemType': u'book',
           u'key': u'VDNIEAPH',
           u'language': u'',
           u'libraryCatalog': u' Library Catalog',
           u'numPages': u'',
           u'numberOfVolumes': u'',
           u'place': u'Evanston, Ill',
           u'publisher': u'Northwestern University Press',
           u'relations': {u'dc:replaces': u''},
           u'rights': u'',
           u'series': u'',
           u'seriesNumber': u'',
           u'shortTitle': u'Saying I No More',
           u'tags': [{u'tag': u'Beckett, Samuel', u'type': 1},
                     {u'tag': u'Consciousness in literature', u'type': 1},
                     {u'tag': u'English prose literature', u'type': 1},
                     {u'tag': u'Ireland', u'type': 1},
                     {u'tag': u'Irish authors', u'type': 1},
                     {u'tag': u'Modernism (Literature)', u'type': 1},
                     {u'tag': u'Prose', u'type': 1},
                     {u'tag': u'Self in literature', u'type': 1},
                     {u'tag': u'Subjectivity in literature', u'type': 1}],
           u'title': u'Saying I No More: Subjectivity and Consciousness in The Prose of Samuel Beckett',
           u'url': u'',
           u'version': 792,
           u'volume': u''},
 u'key': u'VDNIEAPH',
 u'library': {u'id': 436,
              u'links': {u'alternate': {u'href': u'',
                                        u'type': u'text/html'}},
              u'name': u'urschrei',
              u'type': u'user'},
 u'links': {u'alternate': {u'href': u'',
                           u'type': u'text/html'},
            u'self': {u'href': u'',
                      u'type': u'application/json'}},
 u'meta': {u'creatorSummary': u'Katz',
           u'numChildren': 0,
           u'parsedDate': u'1999-00-00'},
 u'version': 792}]

See :ref:`'Hello World' <hello-world>` example, above

Retrieving Files

File retrieval and dumping should work for most common document, audio and video file formats. If you encounter an error, please open an issue.

Retrieving Collections

Example of returned collection data:

[{u'data': {u'key': u'5TSDXJG6',
            u'name': u'Critical GIS',
            u'parentCollection': False,
            u'relations': {},
            u'version': 778},
  u'key': u'5TSDXJG6',
  u'library': {u'id': 436,
               u'links': {u'alternate': {u'href': u'',
                                         u'type': u'text/html'}},
               u'name': u'urschrei',
               u'type': u'user'},
  u'links': {u'alternate': {u'href': u'',
                            u'type': u'text/html'},
             u'self': {u'href': u'',
                       u'type': u'application/json'}},
  u'meta': {u'numCollections': 0, u'numItems': 1},
  u'version': 778}]

Retrieving groups

Example of returned group data:

[{u'data': {u'description': u'',
            u'fileEditing': u'admins',
            u'hasImage': 1,
            u'id': 169947,
            u'libraryEditing': u'admins',
            u'libraryReading': u'members',
            u'members': [1177919, 1408658],
            u'name': u'smart_cities',
            u'owner': 436,
            u'type': u'Private',
            u'url': u'',
            u'version': 0},
  u'id': 169947,
  u'links': {u'alternate': {u'href': u'',
                            u'type': u'text/html'},
             u'self': {u'href': u'',
                       u'type': u'application/json'}},
  u'meta': {u'created': u'2013-05-22T11:22:46Z',
            u'lastModified': u'2013-05-22T11:26:50Z',
            u'numItems': 817},
  u'version': 0}]

Retrieving Tags

Example of returned tag data:

['Authority in literature', 'Errata']

Retrieving Version Information

The Zotero API recommends requesting version information for all (or all changed) items and collections when implementing syncing. The following convenience methods (which by default return an unlimited number of responses) simplify this process.

The return values of these methods associate each item / collection with the last version (or greater) at which the item / collection was modified. By passing the keyword argument since=versionNum only items / collections which have been modified since versionNum are included in the response. Thus, an application which previously sucessfully synced with the server at versionNum can use these methods to determine which items / collections need to be retrieved from the server.

Example of returned version data:

{'C9KW275P': 3915, 'IB489TKM': 4025 }

Full–Text Content

These methods allow the retrieval of full–text content for given library items

Returns a dict containing item keys and library versions newer than since (a library version string, e.g. "1085")

rtype:dict: string -> integer

Example of returned data:

    u'229QED6I': 747,
    u'22TGJFS2': 769,
    u'23SZWREM': 764

Returns a dict containing full-text data for the given attachment item. indexedChars and totalChars are used for text documents, while indexedPages and totalPages are used for PDFs.

Example of returned data:

"content": "This is full-text content.",
"indexedPages": 50,
"totalPages": 50

Set full-text data for an item


itemID should correspond to an existing attachment item.

payload: a dict containing three keys:

content: the full-text content, and either

For text documents, indexedChars and totalChars OR

For PDFs, indexedPages and totalPages.

Example payload:

"content": "This is full-text content.",
"indexedPages": 50,
"totalPages": 50

The follow(), and everything() methods

These methods (currently experimental) aim to make Pyzotero a little more RESTful. Following any Read API call which can retrieve multiple items, calling follow() will repeat that call, but for the next x number of items, where x is either a number set by the user for the original call, or 50 by default. Each subsequent call to follow() will extend the offset.


from pyzotero import zotero
zot = zotero.Zotero(library_id, library_type, api_key)
# only retrieve a single item
# this will retrieve the most recently added/modified top-level item
first_item =
# now we can start retrieving subsequent items
next_item = zot.follow()
third_item = zot.follow()


from pyzotero import zotero
zot = zotero.Zotero(library_id, library_type, api_key)
# retrieve all top-level items
toplevel = zot.everything(

The everything() method should work with all Pyzotero Read API calls which can return multiple items, but has not yet been extensively tested. Feedback is welcomed.

Related generator methods

The :py:meth:`Zotero.iterfollow()` and :py:meth:`Zotero.makeiter()` methods are available for users who prefer to work directly with generators:


z =
lazy = zot.iterfollow() # the next() call has returned the next five items


gen = zot.makeiter( # this will return the first five items # this will return the next five items


The follow(), everything() and makeiter() methods are only valid for methods which can return multiple library items. For instance, you cannot use follow() after an item() call. The generator methods will raise a StopIteration error when all available items retrievable by your chosen API call have been exhausted.

Retrieving item counts

If you wish to retrieve item counts for subsets of a library, you can use the following methods:

Retrieving last modified version

If you wish to retrieve the last modified version of a library, you can use the following method:

Search / Request Parameters for Read API calls

Additional parameters may be set on Read API methods following any required parameters, or set using the :py:meth:`Zotero.add_parameters()` method detailed below.

The following two examples produce the same result:

# set parameters on the call itself
z =, start=3)

# set parameters using explicit method
zot.add_parameters(limit=7, start=3)
z =

The following parameters are are optional.

You may also set a search term here, using the 'itemType', 'q', 'qmode', or 'tag' parameters.

This area of the Zotero Read API is under development, and may change frequently. See the API documentation for the most up-to-date details of search syntax usage and export format details.


Any parameters you set will be valid for the next call only. Any parameters set using add_parameters() will be overridden by parameters you pass in the call itself.

A note on the content and style parameters:


zot.add_parameters(content='bib', style='mla')

If these are set, the return value is a list of UTF-8 formatted HTML div elements, each containing an item:

['<div class="csl-entry">(content)</div>'].

You may also set content='citation' if you wish to retrieve citations. Similar to bib, the result will be a list of one or more HTML span elements.

If you select one of the available export formats as the content parameter, pyzotero will in most cases return a list of unicode strings in the format you specified. The exception is the csljson format, which is parsed into a list of dicts. Please note that you must provide a limit parameter if you specify one of these export formats. Multiple simultaneous retrieval of particular formats, e.g. content="json,coins" is not currently supported.

If you set format='keys', a newline-delimited string containing item keys will be returned

Write API Methods

Item Methods

Creating items


template = zot.item_template('book')
template['creators'][0]['firstName'] = 'Monty'
template['creators'][0]['lastName'] = 'Cantsin'
template['title'] = 'Maris Kundzins: A Life'
resp = zot.create_items([template])

If successful, resp will be a dict containing the creation status of each item:

{'failed': {}, 'success': {'0': 'ABC123'}, 'unchanged': {}}


i = zot.items()
# see above for example of returned item structure
# modify the latest item which was added to your library
i[0]['data']['title'] = 'The Sheltering Sky'
i[0]['data']['creators'][0]['firstName'] = 'Paul'
i[0]['data']['creators'][0]['lastName'] = 'Bowles'

Uploading files


Attachment methods are in beta.

Deleting items

Deleting tags

Adding tags


z =
# we've now retrieved the most recent top-level item
updated = zot.add_tags(z[0], 'tag1', 'tag2', 'tag3')
# updated now contains a representation of the updated server item

Collection Methods


# get existing collections, which will return a list of dicts
c = zot.collections()
# rename the last collection created in the library
c[0]['name'] = 'Whither Digital Humanities?'
# update collection name on the server


Most Read API methods return lists of dicts or, in the case of tag methods, lists of strings. Most Write API methods return either True if successful, or raise an error. See for a full listing of these.


URL parameters will supersede API calls which should return e.g. a single item: will return 10 items beginning at position 50, even though ABC does not exist. Be aware of this, and don't pass URL parameters which do not apply to a given API method.


Pyzotero is licensed under the MIT license.

Cat Picture

This is The Grinch.



[*]This isn't strictly true: you only need an API key for personal libraries and non-public group libraries.