Page tree
Skip to end of metadata
Go to start of metadata

The Python client allows to interact with Cytomine-core through the RESTful API using Python.


First, setup a Python environment using Miniconda installer, i.e. get the installer script, run it, and add the Anaconda binary directory to your PATH variable.  Here is the example for Linux installation:

chmod +x ./
./ -b -p $HOME/miniconda2
export PATH="$HOME/miniconda2/bin:$PATH"

Follow the installer instructions and when installed, create a Python environment with required client dependencies. The Python client supports Python 2.7 and Python > 3.6 but we recommend to use it in its Python 3 version as the end of support for Python 2 is announced by 2020.

Python 2.7

conda create -c conda-forge -n cytomine python=2.7 requests requests-toolbelt cachecontrol shapely numpy opencv six future

Python 3.6

conda create -c conda-forge -n cytomine python=3.6 requests requests-toolbelt cachecontrol shapely numpy opencv six future

The easiest way to get the Python client is to clone it from Github. If you don't have git on your machine, install it

sudo apt-get install git

Clone the Cytomine Python client from our repository

source activate cytomine
mkdir Cytomine/ ; cd Cytomine/
git clone
cd Cytomine-python-client/

Install the basic Cytomine client with basic functions to communicate with the Cytomine-Core. Pay attention you are in the "cytomine" Python environment.

python build
python install

The client is installed.

Usage and Examples

This Section illustrates how to use the Cytomine-Python-Client to manipulate (import/export/create/delete/...) Cytomine data. Additional examples are available in the Examples Section on the Github repository.


You need 3 parameters to connect to a Cytomine instance :

  1. The host URL (example:
  2. Your public key
  3. Your private key

It is recommended to use the with statement to establish the HTTP session between the client and the sever. The "with statement" block is a Python feature to efficiently deal with data flows.

import logging
from cytomine import Cytomine

host = ""
public_key = "XXX" # check your own keys from your account page in the web interface
private_key = "XXX"
with Cytomine(host=host, public_key=public_key, private_key=private_key,
              verbose=logging.INFO) as conn:

The verbose parameter allows to change the verbosity level. By default, it is set to INFO, which prints a summary of a resource when fetched, saved, updated or deleted. See the Python standard logging module for more information.

Another possibility to connect, especially for short scripts is to use the connect() method:

cytomine = Cytomine.connect(host, public_key, private_key)

It is still possible to connect by simply instantiate the Cytomine class for backwards compatibility reasons but is deprecated.


A Cytomine resource (e.g. a project A) is an instance of a domain (e.g. Project). In the client, a resource is a Python object which is an instance of a model class describing its domain. Each object (an instance of model):

  • has a set of attributes corresponding to resource attributes
  • is managed itself through fetch(), save(), update() and delete() methods that communicate with the Cytomine-core server
  • has some utilities to be serialized to JSON
  • a dictionary of query parameters that will appear in the request: resource.json?param1=value1 (seldom used for models)

A simple example with a project resource:

from cytomine.models import Project

# ... Assume we are connected
id_ontology = 0
# Add a new project
# The save() method makes the appropriate HTTP POST request.
# Option 1
my_new_project = Project("my project name", id_ontology).save()
# Option 2
my_new_project = Project() = "my project name"
my_new_project.ontology = id_ontology
# Get the project from server. 
# The fetch() method makes the appropriate HTTP GET request.
# Option 1
my_new_project2 = Project().fetch(
# Option 2
my_new_project2 = Project() =
# Update a project
# The update() method makes the appropriate HTTP PUT request.
# Option 1 = "Another name"
# Option 2
my_new_project.update(name="Another name")
# Delete a project
# The delete() method makes the appropriate HTTP DELETE request.
# Option 1
# Option 2

Supplementary actions

In some cases, the server provides supplementary actions for some resources. These actions are encapsulated in additional methods for the model.

Example 1

Download the original file behind an abstract image. 

id_image = 0
image = AbstractImage().fetch(id_image)"/tmp/{originalFilename}")

The download() method will get the image and copy it into the temporary directory. The name of the file is the original filename stored into Cytomine-core because the destination path is parsed, and every model attribute can be used. For example, it is possible to save the image with a filename which contains its Cytomine ID, its width and height:"/tmp/{id}_{width}px_{height}px.jpg")

Example 2

Get the spectrum for a given pixel in an Image Group HDF5.

id_image_group_hdf5 = 0
ighdf5 = ImageGroupHDF5().fetch(id_image_group_hdf5)
spectrum = ighdf5.pixel(100, 100)
print(spectrum) # Print spectrum (Numpy array) at position (100, 100)

The pixel request makes the appropriate GET request in background.


A collection is a list of objects that have the same model. A collection is fetched with fetch() method.

For example, to get the list of all projects you have access to:

projects = ProjectCollection().fetch()
for project in projects:


The Collection class extends the Python MutableSequence class. You can thus work with a collection like with any Python list:

projects = ProjectCollection().fetch()
print([ for project in projects])


The API often allows to filter a list of resources with an other resource, by specifiying it in the URI. The filtering by URI is performed using the fetch_with_filter() method. The list of allowed filters for a collection is given by mycollection.filters()

projects = ProjectCollection().fetch()
print(projects.filters()) # None, user, software, ontology
# None indicates the collection can be fetched without any filter
# Get the list of projects of a particular user
id_user = 0
ProjectCollection().fetch_with_filter("user", id_user)
# Get the list of projects linked to a particular software
id_software = 0
ProjectCollection().fetch_with_filter("software", id_software)
# Get all projects that share the same ontology
id_ontology = 0
ProjectCollection().fetch_with_filter("ontology", id_ontology)

It will make the appropriate GET request, e.g. : GET /api/ontology/{id_ontology}/project.json

The behavior of collection requests can sometimes be modified with some query parameters. In the case of collections, these query parameters are the attributes of the Collection class. For example, we can obtain the list of online users with a query parameter:

# Get the list of online users
# => GET /api/user.json?online=true
id_project = 0
UserCollection(online=True).fetch_with_filter("project", id_project)
# Get the list of online users on a particular project
# => GET /api/project/{id_project}/user.json?online=true

Particular case: a collection of annotations

A list of annotations can be filtered with many filters (project, user, image, term, ...). The only way given by the API to filter a list of annotations is to use query parameters. 

id_project = 0
id_users = [1, 2]
annotations = AnnotationCollection(project=id_project, users=id_users, showWKT=True).fetch()
# => GET /api/annotation.json?showBasic=true&showMeta=true&showWKT=true&project=0&users=1,2

Multiple adds in one request

When you have a lot of new objects belonging to the same model to add, it may be interesting to send these multiple new objects in one request for all instead of one by one (default behavior). The multiple add is currently only supported for Annotation model. Instead of saving annotation one by one, append them into a collection and save the collection:

annotations = AnnotationCollection()
annotations.append(Annotation(location=point.wkt, id_image=id_image_instance, id_project=id_project))
annotations.append(Annotation(location=rectangle.wkt, id_image=id_image_instance, id_project=id_project))

It is your responsibility to choose which method to use. If you send to much requests (lot of annotations one by one), the server may flush some of your requests if too busy. On the other hand, if you send too much objects in one requests (ex: 100000 annotations in one request) there are many chances that the HTTP request is too heavy for the server.


A bunch of examples are provided with the Python client in the directory Cytomine-python-client/examples/ (see here)

These are ready-to-use scripts for common tasks.

Notes for users of deprecated Python client versions

Previous version were only available in Python 2.7 which was a high limitation. 

Most of code written with previous versions should be compatible with new one, but no guarantee is given.


This new version is a complete rewrite of the Python client and improves and adds a lot of features:

  • Compatibility Python 2.7 / 3+
  • Logging with verbosity levels (standard Python logger)
  • Use requests library to handle HTTP
  • Collections are iterable
  • Model's attributes are written in the code: code is self-documented and ease auto-completion
  • Cytomine class is a singleton and its no more necessary to pass it as parameter in every functions
  • Model and Collection are self managed
  • CytomineJob class extends Cytomine and is thus a singleton where the current user is a user-job.
  • No labels