Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/zotero/zotero-connectors/llms.txt

Use this file to discover all available pages before exploring further.

When the Zotero desktop application is running, it exposes a local HTTP server on localhost:23119. The browser extension calls this server to save items, retrieve translator code, check the client’s availability, and exchange preferences. All communication is JSON-based and versioned via a dedicated API version header. The Zotero.Connector singleton (src/common/connector.js) is the single entry point through which the extension reaches this server.

API Version and Request Headers

Every request sent to the connector server includes three standard headers:
const CONNECTOR_API_VERSION = 3;

headers = {
  "Content-Type":                  "application/json",
  "X-Zotero-Version":              Zotero.version,        // e.g. "6.0.27"
  "X-Zotero-Connector-API-Version": CONNECTOR_API_VERSION  // always 3
}
The X-Zotero-Version header lets the server detect version mismatches and respond with HTTP 412.

Zotero.Connector.callMethod(options, data, tab)

The primary method for making connector API calls:
this.callMethod = async function(options, data = null, tab = null) {
  if (typeof options == 'string') {
    options = {method: options};
  }
  var method   = options.method;
  var timeout  = "timeout" in options ? options.timeout : 15000;
  var uri = Zotero.Prefs.get('connector.url') + "connector/" + method + queryString;
  // ...
  let httpMethod = data === null ? "GET" : "POST";
  // ...
}
options
string | object
required
Either a method name string or an options object with the following keys:
  • method — the API endpoint name (e.g. "ping", "saveItems")
  • headers — additional HTTP headers merged onto the defaults
  • queryString — raw query string appended to the URL (without leading ?)
  • timeout — request timeout in milliseconds (default 15000)
data
object | null
Request body. When null, a GET request is sent. When an object, it is JSON.stringify-ed and sent as a POST.
tab
object | null
The browser tab object. Used by the Google Docs integration to detect if the tab has been discarded during a long-running document/ operation.
Returns: The parsed JSON response body, or the raw responseText for non-JSON responses.

Connectivity State: isOnline

Zotero.Connector.isOnline tracks the live connection state:
ValueMeaning
nullUnknown (Chrome initial state — will be determined on first request)
falseDesktop client is offline (default for Firefox and Safari)
trueDesktop client is reachable
Transitions in isOnline trigger Zotero.Connector.onStateChange(version):
this.onStateChange = function(version) {
  Zotero.Connector_Browser?.onStateChange(version);
  Zotero.UpdaterFix?.onStateChange(version);
}

Zotero.Connector.checkIsOnline()

Sends a ping and returns true or false. A non-zero HTTP error status is treated as “online with an error” rather than offline:
this.checkIsOnline = async function() {
  try {
    await this.ping({});
    return true;
  } catch (e) {
    if (e.status != 0) return true;  // server responded, just with an error
    return false;
  }
}

Zotero.Connector.ping(payload)

Checks availability and processes server-side preferences in a single round trip:
this.ping = async function(payload={}) {
  let response = await Zotero.Connector.callMethod("ping", payload);
  if (response && 'prefs' in response) {
    this._processPreferences(response.prefs);
    this._processTranslatorHash(response.prefs);
  }
  return response || {};
}
The extension also calls ping with { activeURL: url } whenever the user navigates, allowing the desktop client to update its “active URL” display.

Preferences Processed from Ping

_processPreferences() reads the following boolean flags from response.prefs and stores them in Zotero.Connector.prefs:
const PREF_KEYS = [
  'downloadAssociatedFiles',
  'reportActiveURL',
  'automaticSnapshots',
  'googleDocsAddAnnotationEnabled',
  'googleDocsCitationExplorerEnabled',
  'supportsAttachmentUpload',
  'supportsTagsAutocomplete',
  'canUserAddNote'
];

Translator Hash Check

_processTranslatorHash() compares the hash returned in response.prefs.translatorsHash (or sortedTranslatorHash) against the connector’s locally computed hash. On mismatch, it immediately calls Zotero.Translators.updateFromRemote():
if (remoteHash != translatorsHash) {
  Zotero.debug("Zotero Ping: Translator hash mismatch detected. Updating translators from Zotero")
  return Zotero.Translators.updateFromRemote();
}

API Endpoints

ping

POST /connector/ping — Availability check. Returns prefs object including translator hash, feature flags, and user preferences. Also accepts { activeURL } to report the current tab URL.

saveItems

POST /connector/saveItems — Save one or more translated items. Payload includes sessionID, uri, items array, cookie/detailedCookies, and an optional proxy.

saveSnapshot / saveSingleFile

POST /connector/saveSnapshot or POST /connector/saveSingleFile — Save a full-page HTML snapshot captured by SingleFile. The saveSingleFile endpoint accepts snapshotContent in the body.

getTranslatorCode

POST /connector/getTranslatorCode — Retrieve the JavaScript source for a translator by { translatorID }. Used as the first-choice code source before falling back to the remote repository.

getTranslators

POST /connector/getTranslators — Returns the full translator metadata list from the desktop client. Used by Zotero.Repo.getTranslatorMetadataFromZotero().

sessionProgress

POST /connector/sessionProgress — Polls attachment download progress for a given sessionID. Returns { items, done }.

document/execCommand

POST /connector/document/execCommand — Google Docs integration: sends a word-processor command (e.g. insertCitation) to the desktop client.

document/respond

POST /connector/document/respond — Returns the document-side response to a pending integration command. Used in the integration loop until command equals complete.

Error Handling

callMethod maps HTTP status codes to typed errors:
if (xhr.status === 0) {
  // Network error / client offline
  Zotero.Connector.isOnline = false;
  throw new Zotero.Connector.CommunicationError('Connector: Zotero is offline');
}
else if (xhr.status === 412) {
  // Version mismatch — connector and client APIs are incompatible
  Zotero.Connector_Browser.onIncompatibleStandaloneVersion(connectorVer, standaloneVer);
  throw new Zotero.Connector.CommunicationError(`Version mismatch ...`, 412, val);
}
else if (xhr.status >= 400) {
  throw new Zotero.Connector.CommunicationError(`Method ${method} failed`, xhr.status, val);
}

Zotero.Connector.CommunicationError

Zotero.Connector.CommunicationError = function(message, status=0, value='') {
  this.name    = 'Connector Communication Error';
  this.message = message;
  this.status  = status;  // HTTP status, or 0 for network error
  this.value   = value;   // parsed response body (if any)
}
Zotero.Connector.CommunicationError.prototype = new Error;
StatusMeaning
0Network error / desktop client not running
400–499Client-side error (bad request, not authorised, etc.)
412Connector/client version mismatch
500+Server-side error in the desktop client

For save operations that may involve authenticated attachment downloads, the connector uses callMethodWithCookies() instead of the plain callMethod(). It collects the current tab’s cookies via browser.cookies.getAll() and adds them to the payload as detailedCookies and uri:
data.detailedCookies = cookieHeader.substr(1);
data.uri = tab.url;
return this.callMethod(options, data, tab);
This allows the Zotero desktop client to construct a proper cookie sandbox when it fetches attachments on behalf of the extension.

Further Reading

The official connector server protocol documentation — including the full list of endpoints, request/response schemas, and authentication requirements — is published at https://www.zotero.org/support/dev/client_coding/connector_http_server.

Build docs developers (and LLMs) love