# Plant identification API (`hugo_gresse/plantnet`) Actor

Identify plant from a photo, return potential species, diseases or pathogens
Up to 85000 species

- **URL**: https://apify.com/hugo\_gresse/plantnet.md
- **Developed by:** [Hugo Gresse](https://apify.com/hugo_gresse) (community)
- **Categories:** AI, Developer tools
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 plant identification / diseases / varieties / = gpus

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Pl@ntNet Plant Identification API

Identify **plants, diseases and cultivated varieties from photos**, and browse the botanical reference data behind them — powered by [Pl@ntNet](https://my.plantnet.org/), the citizen-science identification engine used by millions of botanists, farmers and gardeners.

**No Pl@ntNet account, no API key, no quota to manage.** Send an image, get ranked species back with scientific names, common names, family, genus and GBIF/POWO identifiers.

- 🌿 **84,600 species** in the world flora, across 77 regional floras (Western Europe, Canada, useful plants, weeds…)
- 🦠 **Diseases and pests** identified from the same kind of photo
- 🍇 **Cultivated varieties** for crops and ornamentals
- 📚 **Taxonomy data**: floras, species lists and 52 languages for localized common names
- ⚡ Use it as a **classic Actor run** or as a **live HTTP API** (Standby mode)

***

### Why Pl@ntNet

Pl@ntNet isn't a general image classifier with a plant label on it. It has been built since 2009 by four French public research institutes — **Cirad, Inria, IRD and INRAE** — and is trained on an observation base that a global community keeps growing and experts keep revising.

- **Over a billion identifications** served; 100,000–700,000 active users a day, peaking at 1.5 million identifications
- Observations published to **GBIF** and cited in **1,000+ scientific publications**
- The same engine behind the Pl@ntNet app and its Pro API (10,000+ developers)
- Models and referentials are updated continuously — the response carries the model `version` it used

***

### Quick start

Run the Actor with this input:

```json
{
  "endpoint": "identify",
  "imageUrls": ["https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Bellis_perennis_white_%28aka%29.jpg/960px-Bellis_perennis_white_%28aka%29.jpg"],
  "lang": "en",
  "nbResults": 3
}
```

You get back the Pl@ntNet response, ranked by confidence:

```json
{
  "results": [
    {
      "score": 0.59113,
      "species": {
        "scientificName": "Bellis perennis L.",
        "scientificNameWithoutAuthor": "Bellis perennis",
        "genus": { "scientificName": "Bellis" },
        "family": { "scientificName": "Asteraceae" },
        "commonNames": ["Daisy", "English daisy", "Common daisy"]
      },
      "gbif": { "id": "3117424" },
      "powo": { "id": "184409-1" }
    }
  ],
  "version": "2026-03-20 (7.5)"
}
```

`organs` is optional — Pl@ntNet detects the organ on its own, and you can name it (`leaf`, `flower`, `fruit`, `bark`) when you want to be explicit.

The full response lands in the **dataset** (one item per call) and in the key-value store record **`OUTPUT`**.

#### From your code

```bash
curl -X POST "https://api.apify.com/v2/acts/hugo_gresse~plantnet/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{"endpoint":"identify","imageUrls":["https://example.com/leaf.jpg"],"lang":"en"}'
```

***

### Use it as a live HTTP API (Standby mode)

Instead of starting a run per request, call the Actor like any REST API. The routes, paths and query parameters are **identical to the official Pl@ntNet API** — just without `api-key`, which is injected for you.

```bash
## Identify a plant from local files (up to 5 images of the same individual)
curl -X POST "https://hugo-gresse--plantnet.apify.actor/v2/identify/all?lang=en&nb-results=3" \
  -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
  -F images=@leaf.jpg -F organs=leaf \
  -F images=@flower.jpg -F organs=flower

## Diseases and pests
curl -X POST "https://hugo-gresse--plantnet.apify.actor/v2/diseases/identify?lang=en" \
  -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
  -F image=@sick-leaf.jpg

## Reference data
curl "https://hugo-gresse--plantnet.apify.actor/v2/projects?lang=en&token=<YOUR_APIFY_TOKEN>"
curl "https://hugo-gresse--plantnet.apify.actor/v2/species?prefix=quercus&token=<YOUR_APIFY_TOKEN>"
curl "https://hugo-gresse--plantnet.apify.actor/v2/languages?token=<YOUR_APIFY_TOKEN>"
```

`GET /` returns a usage summary, and the **Endpoints** tab documents every route (OpenAPI).

***

### Input reference

| Field | Type | Description |
|---|---|---|
| `endpoint` | string | What to call: `identify`, `diseases`, `projects`, `species`, `projectSpecies`, `languages`. |
| `imageUrls` | array | 1–5 public JPG/PNG URLs of **the same plant**. Required for `identify` and `diseases`. |
| `organs` | array | Optional. One organ per image, same order: `leaf`, `flower`, `fruit` or `bark`. Left empty, Pl@ntNet detects it. |
| `project` | string | Flora to search: `all` (default), `k-world-flora`, `weurope`, `useful`, `weeds`… see the `projects` endpoint. |
| `lang` | string | Language for common names, e.g. `en`, `fr`, `es` (52 available). |
| `nbResults` | integer | Maximum number of results returned. |
| `includeRelatedImages` | boolean | Return reference images for each candidate species. |
| `noReject` | boolean | Return results even when the photo may not be a plant. |
| `extraParams` | object | Extra query parameters passed through as-is, e.g. `{"prefix": "quercus", "pageSize": 50, "page": 1}` or `{"lat": 48.85, "lon": 2.35}`. |

Parameters are only forwarded to routes that accept them, so you can leave defaults in place without triggering Pl@ntNet validation errors.

#### Endpoints

| `endpoint` | Pl@ntNet route | What it returns |
|---|---|---|
| `identify` | `POST /v2/identify/{project}` | Ranked species with scores, names, family, GBIF/POWO ids |
| `diseases` | `POST /v2/diseases/identify` | Ranked diseases and pests |
| `projects` | `GET /v2/projects` | The 77 floras, with species counts (add `lat`/`lon` to sort by proximity) |
| `species` | `GET /v2/species` | Species list, filter with `prefix`, paginate with `pageSize`/`page` |
| `projectSpecies` | `GET /v2/projects/{project}/species` | Species of one flora |
| `languages` | `GET /v2/languages` | Supported language codes |

***

### Output

Each call produces one dataset item:

```json
{
  "endpoint": "identify",
  "status": 200,
  "ok": true,
  "request": { "path": "/v2/identify/all", "method": "POST" },
  "data": { "results": [ "…the Pl@ntNet response…" ] }
}
```

The raw Pl@ntNet JSON is also stored as the `OUTPUT` record, and the run's Output tab links to both.

***

### Pricing

Pay per event — you are charged for what you actually call, and **only when Pl@ntNet answers successfully**:

| Event | Price | When |
|---|---|---|
| Plant / disease / variety identification | $0.008 | Per identification request (this is the GPU inference call) |
| Any other call | $0.0005 | Taxonomy, species lists, languages |
| Actor start | $0.00005 | Once per run |

Identifying 1,000 plants costs about **$8**. The Actor respects the *maximum cost per run* you set: once the limit is reached it stops before calling Pl@ntNet, so you are never billed past your cap.

***

### Tips for good results

- **Up to 5 photos of the same individual** in one identification — a leaf, a flower and a fruit together beat a single blurry shot.
- **Tag the organ** (`leaf`, `flower`, `fruit`, `bark`) rather than relying on `auto` when you know it.
- **Narrow the flora** with `project` (for example `weurope`) when you know where the photo was taken; accuracy goes up.
- Photograph **one plant**, close, in focus, against an uncluttered background.
- `score` is a confidence between 0 and 1 — treat anything low as a suggestion, not an answer.
- Image URLs must be publicly reachable. Some hosts block server-side fetching; if a URL fails, post the file directly through the Standby API.

### FAQ

**Do I need a Pl@ntNet API key?** No. Identification requests are covered by this Actor's pricing.

**Which regions are covered?** 77 floras, from `k-world-flora` (84,600 species) to regional ones like `weurope`, plus themed sets such as useful plants and weeds. Call the `projects` endpoint for the full list.

**Can I use it without writing code?** Yes — fill in the input form, run it, and export the dataset to JSON, CSV or Excel. It also connects to Make, Zapier and n8n through Apify integrations.

**Is it good for bulk work?** Yes; run the Actor per image, or keep the Standby endpoint warm and post images to it in a loop.

***

### About this Actor

**This is not an official Pl@ntNet product.** It is an independent Actor that calls the public [Pl@ntNet API](https://my.plantnet.org/) — I do work on the Pl@ntNet team, which is why it stays close to the real API, but Pl@ntNet neither publishes nor supports this Actor, and nothing here should be read as an official statement from the project.

**Need another route, another output shape, or a feature that isn't here?** Open a thread in the **Issues tab** of this Actor — that's the direct line to me, and I read everything posted there.

Identification results, taxonomy and imagery come from the [Pl@ntNet API](https://my.plantnet.org/). Pl@ntNet is a joint initiative of Cirad, INRAE, Inria and IRD. Species coverage and model versions evolve as the project's data grows.

# Actor input Schema

## `endpoint` (type: `string`):

Which PlantNet endpoint to call.

## `imageUrls` (type: `array`):

Public JPG/PNG image URLs (1 to 5). Used by 'identify' and 'diseases'.

## `organs` (type: `array`):

Optional. One organ per image, in the same order: leaf, flower, fruit or bark. Left empty, Pl@ntNet detects the organ itself.

## `project` (type: `string`):

Flora/referential to query, e.g. 'all', 'weurope', 'k-world-flora'. See the 'projects' endpoint for the full list.

## `lang` (type: `string`):

Language code for localized results (e.g. 'fr', 'en').

## `nbResults` (type: `integer`):

Limit the number of returned species/diseases.

## `includeRelatedImages` (type: `boolean`):

Return similar images for each result.

## `noReject` (type: `boolean`):

Never reject the image even if it does not look like a plant.

## `extraParams` (type: `object`):

Any additional query parameters passed as-is, e.g. {"prefix": "quercus", "pageSize": 50, "page": 1} or {"lat": 48.85, "lon": 2.35}.

## Actor input object example

```json
{
  "endpoint": "identify",
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Bellis_perennis_white_%28aka%29.jpg/960px-Bellis_perennis_white_%28aka%29.jpg"
  ],
  "project": "all",
  "lang": "fr",
  "includeRelatedImages": false,
  "noReject": false
}
```

# Actor output Schema

## `response` (type: `string`):

The raw PlantNet response returned by this run.

## `results` (type: `string`):

One item per PlantNet call, with the request that produced it.

## `apiEndpoint` (type: `string`):

Base URL of the PlantNet proxy while the Actor runs in Standby mode.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "imageUrls": [
        "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Bellis_perennis_white_%28aka%29.jpg/960px-Bellis_perennis_white_%28aka%29.jpg"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hugo_gresse/plantnet").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "imageUrls": ["https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Bellis_perennis_white_%28aka%29.jpg/960px-Bellis_perennis_white_%28aka%29.jpg"] }

# Run the Actor and wait for it to finish
run = client.actor("hugo_gresse/plantnet").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "imageUrls": [
    "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Bellis_perennis_white_%28aka%29.jpg/960px-Bellis_perennis_white_%28aka%29.jpg"
  ]
}' |
apify call hugo_gresse/plantnet --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hugo_gresse/plantnet"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZOdWzRy5YTx7ygZ4h/builds/DjJNGlA60eSSqxraI/openapi.json
