Introduction
General information
More detailed descriptions of the identification engine and collaborative review process are available in the following articles:
- Cooperative learning of Pl@ntNet's Artificial Intelligence algorithm: How does it work and how can we improve it?, Lefort, T., Affouard, A., Charlier, B., Lombardo, J-C., Chouet, M., Goëau, H., Salmon, J., Bonnet, P., Joly, A., 2025.
- DINOv2: Learning Robust Visual Features without Supervision, Oquab, M. et al., 2024
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
path: /data/media/image_1.jpeg
organ: flower
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.