Introduction

Pl@ntNet API provides a computational access to the visual identification engine used in Pl@ntNet apps in the form of a RESTful Web service. The service allows you to submit simultaneously from 1 to 5 images of the same plant and to have in return the list of the most likely species as well as a confidence score for each of them. The identification engine is based on most advanced deep learning technologies and is regularly updated thanks to the contributions of the community and the integration of new expert databases.

General information

More detailed descriptions of the identification engine and collaborative review process are available in the following articles:

Identification performance varies from one species to another and depends mainly on the number of images illustrating them in the training database (see our species explorer). If you would like to improve the recognition performance of a particular species, you can contribute new images using any of the Pl@ntNet apps.

The second parameter that has the greatest impact on the quality of identification is the quality of the images provided at the service input. As with Pl@ntNet apps, it is important to ensure that the images are as informative and clear as possible (see Pl@ntNet tutorial).

Create your account

You should first create an account to use the Pl@ntNet API service.

Generate your private API Key

Go to your /settings/api-key page to generate your private API key (if not already done).

You can use your current API key for the rest of this guide:

Prepare your images

Get the paths of the images you want to identify. You can add up to 5 images in a single identification request.

For the following example, we will use these two images:

Image 1

Image 1
path: /data/media/image_1.jpeg
organ: flower

Image 2

Image 2
path: /data/media/image_2.jpeg
organ: leaf

Identify your images

Use the POST /v2/identify endpoint to identify species on your images. Don’t forget to pass your API key as a query parameter (not in body).

import fs from 'node:fs'
import FormData from 'form-data' // npm install form-data

const image1 = '/data/media/image_1.jpeg'
const image2 = '/data/media/image_2.jpeg'

const identify = () => {
  const form = new FormData()

  form.append('organs', 'flower');
  form.append('images', fs.createReadStream(image1));

  form.append('organs', 'leaf');
  form.append('images', fs.createReadStream(image2));

  const project = 'all'; // You can choose a more specific flora, see: /docs/newfloras

  try {
    const response = await fetch(`https://my-api.plantnet.org/v2/identify/${project}?api-key=YOUR-PRIVATE-API-KEY-HERE`,
      {
        method: 'post',
        body: form,
      }
    );

    console.log('status', response.status) // should be: 200

    const json = await response.json()
    console.log('json', json)
  } catch (error) {
    console.error('error', error);
  }
};

identify()
package test;

import java.io.File;
import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

public class Test {
    private static final String IMAGE1 = "/data/media/image_1.jpeg";
    private static final String IMAGE2 = "/data/media/image_2.jpeg";

    private static final String PROJECT = "all"; // You can choose a more specific flora, see: /docs/newfloras
    private static final String URL = "https://my-api.plantnet.org/v2/identify/" + PROJECT + "?api-key=YOUR-PRIVATE-API-KEY-HERE";

    public static void main(String[] args) {
        File file1 = new File(IMAGE1);
        File file2 = new File(IMAGE2);

        HttpEntity entity = MultipartEntityBuilder.create()
            .addPart("images", new FileBody(file1)).addTextBody("organs", "flower")
            .addPart("images", new FileBody(file2)).addTextBody("organs", "leaf")
            .build();

        HttpPost request = new HttpPost(URL);
        request.setEntity(entity);

        HttpClient client = HttpClientBuilder.create().build();
        HttpResponse response;

        try {
            response = client.execute(request);
            String jsonString = EntityUtils.toString(response.getEntity());
            System.out.println(jsonString);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
import requests
import json
from pprint import pprint

API_KEY = "YOUR-PRIVATE-API-KEY-HERE"   # Your API key here
PROJECT = "all"; # You can choose a more specific flora, see: /docs/newfloras
api_endpoint = f"https://my-api.plantnet.org/v2/identify/{PROJECT}?api-key={API_KEY}"

image_path_1 = "../data/image_1.jpeg"
image_data_1 = open(image_path_1, 'rb')

image_path_2 = "../data/image_2.jpeg"
image_data_2 = open(image_path_2, 'rb')

data = { 'organs': ['flower', 'leaf'] }

files = [
  ('images', (image_path_1, image_data_1)),
  ('images', (image_path_2, image_data_2))
]

req = requests.Request('POST', url=api_endpoint, files=files, data=data)
prepared = req.prepare()

s = requests.Session()
response = s.send(prepared)
json_result = json.loads(response.text)

pprint(response.status_code)
pprint(json_result)
API_URL <- "https://my-api.plantnet.org/v2/identify"

project <- "all" # You can choose a more specific flora, see: /docs/newfloras
key <- "YOUR-PRIVATE-API-KEY-HERE" # Your API key here
lang <- "fr"
includeRelatedImages <- FALSE # try TRUE

URL <- paste0(API_URL,
  "/", project, "?",
  "lang=", lang,
  "&include-related-images=", includeRelatedImages,
  "&api-key=", key)

image_1 <- "../data/image_1.jpeg"
image_2 <- "../data/image_2.jpeg"

data <- list(
  "images" = httr::upload_file(image_1),
  "images" = httr::upload_file(image_2),
  "organs" = "flower",
  "organs" = "leaf"
)

response <- httr::POST(URL, body=data, encode="multipart")

status <- response$status_code

message(status)

result <- httr::content(response, as="parsed")

message(result)

Explore your identification results

Get the list of probable species names sorted by score.

{
    "query": {
        "project": "all",
        "images": [
            "image_1",
            "image_2"
        ],
        "organs": [
            "flower",
            "leaf"
        ]
    },
    "language": "en",
    "preferedReferential": "k-southwestern-europe",
    "results": [
        {
            "score": 0.9952006530761719,
            "species": {
                "scientificNameWithoutAuthor": "Hibiscus rosa-sinensis",
                "scientificNameAuthorship": "L.",
                "genus": {
                    "scientificNameWithoutAuthor": "Hibiscus",
                    "scientificNameAuthorship": "L."
                },
                "family": {
                    "scientificNameWithoutAuthor": "Malvaceae",
                    "scientificNameAuthorship": "Juss."
                },
                "commonNames": [
                    "Chinese hibiscus",
                    "Hawaiian hibiscus",
                    "Hibiscus"
                ]
            }
        }
    ],
    "remainingIdentificationRequests": 1228
}

Detailed input parameters and output format

See detailed documentation for single-species identification.

Expose your API key

To enable usage of your API key in browser-side client apps, you need to explicitly authorize all domain names the service is accessed from.

Enable client access to your API key (CORS)

From your account From your account API key settings page, check "expose my API key".

You can now use your API key in a client-side browser application, ie. in a CORS-enabled environment.

Authorize domain(s)

Under "Authorized domains", add one domain per line. CORS requests will be rejected if domain present in Origin header is not in this list.

Authorize IP addresses (optional)

Once "expose my API key" is checked, any non-CORS request will be rejected if it does not come from a server with an IP address matching the "Authorized IPs" list. This prevents the exposed API key from being stolen and used server-side on a machine that isn't yours.

If you want to use your API key both client-side and server-side, you need to explicitly authorize IP addresses of your servers. Under "Authorized IPs", add one IPv4 or IPv4 range (CIDR format) per line.