# EU Grassland Condition Records — Grassland Watch (`nexgensignal/eu-grassland-condition-records`) Actor

Keyless, pay-per-record EU Grassland Watch data. One row per site/month/variable observation — site code, unit, year, month, variable, value, units. Partition required (country, MONSTER per country); CC BY 4.0; no person data.

- **URL**: https://apify.com/nexgensignal/eu-grassland-condition-records.md
- **Developed by:** [NexGen Signal](https://apify.com/nexgensignal) (community)
- **Categories:** Business, Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $33.50 / 1,000 observation records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## EU Grassland Condition Records — Grassland Watch

**Keyless. Pay per record. Europe's satellite-monitored grassland condition, site by site, month by month.**

This actor turns the **European Commission EU Grassland Watch** into clean, per-observation records — the satellite-derived monitoring of grassland condition across the EU's Natura 2000 network. Each run reads the Commission's keyless data-query API for the country you choose and delivers one row per site / month / variable observation: the site code, the land-cover unit, the year and month, the measured variable and its value, and the units. Site / unit / month / variable observation grain, structured for engineering use, under the Creative Commons Attribution 4.0 licence, with no personal data of any kind.

### What this is, in one paragraph

EU Grassland Watch monitors the condition of protected grasslands using satellite data, and the European Commission publishes the observations. This actor reads that dataset and flattens each observation into a single analysis-ready record: the site code (a protected-area identifier), the land-cover unit id, the year and month of observation, the monitored variable, the observed value, and the units. Values are carried **verbatim** — the measurement is exactly as published, including zero values. It is the grassland-condition monitoring layer of Europe's protected-area network. You are billed only for records actually delivered.

### Who buys this and for what job

- **Environmental-monitoring, conservation, and land-use teams** tracking grassland condition across protected sites over time.
- **Agri-environment and CAP-compliance products** studying grassland-condition indicators by site and season.
- **Remote-sensing and ESG-analytics teams** joining grassland observations to protected-area and habitat datasets.
- **Data engineers** who want the Grassland Watch observations as clean rows without paging a per-country API by hand.

### Creative Commons Attribution 4.0 — free commercial reuse

One licence rider travels on every record. European Commission EU Grassland Watch data is available for reuse under the **Creative Commons Attribution 4.0 International (CC BY 4.0)** licence per the Commission's legal notice — free to reuse, including commercially, with attribution to the European Commission. That attribution travels on every record. One honest caveat rides too: these are satellite-derived monitoring observations, not a compliance or land-management determination.

### Observation grain — no person data

The unit of every record is a site / month / variable observation — a measurement, never a person. The dataset carries no natural-person fields, and this actor emits none, with a person-key guard as a pure backstop. Site codes, unit ids, variables, values, and units are the entire payload.

### A required partition — this is a multi-million-row dataset per country

EU Grassland Watch is published as **one observation table per country**, and each is a MONSTER — **Germany alone is over 3.7 million rows**. This actor therefore **requires a partition**: every run must set a `countryCode` (one of the 27 EU Grassland Watch countries). The country selects its own table; there is no unbounded all-EU pull — it is structurally impossible in code. Optional `variable` and `year` filters narrow further, and `maxRecords` is the hard ceiling.

### Pricing

| Event | Free plan | Bronze | Silver | Gold / Platinum / Diamond |
|-------|-----------|--------|--------|---------------------------|
| `observation_record` | $0.05 | $0.045 | $0.04 | $0.0335 |

Delivered before charged. Blocked runs and empty results cost nothing.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `countryCode` | string | — | **Required** 2-letter country code (one of the 27 EU Grassland Watch countries, e.g. DE, FR, ES). |
| `variable` | string | — | Optional. Keep only observations of this variable code (e.g. LWC). |
| `year` | integer | — | Optional observation year to filter (e.g. 2016). |
| `maxRecords` | integer | 500 | Ceiling on records delivered and billed. |

### Output

One JSON object per observation. Real example (values as published):

```json
{
  "record_id": "DE1420301:COP4N2K_2012_3473819:2016:5:LWC",
  "object_id": "618520",
  "site_code": "DE1420301",
  "uid_lcu": "COP4N2K_2012_3473819",
  "country_code": "DE",
  "year": 2016,
  "month": 5,
  "variable": "LWC",
  "value": 0.0,
  "units": "cm*100000",
  "source": "European Commission EU Grassland Watch",
  "licence": "European Commission EU Grassland Watch ... Creative Commons Attribution 4.0 ...",
  "disclaimer": "EU Grassland Watch satellite-derived condition observation records ... carried VERBATIM ...",
  "observed_at": "2026-08-22T00:00:00Z"
}
```

An unbilled `RUN_RECEIPT` records the robots check, the country, variable, and year, rows seen and delivered, and whether charged equals delivered.

### Field reference

Each record is one observation. Identity: `record_id` (site + unit + year + month + variable), `object_id`, `site_code`, `uid_lcu`, and `country_code`. Time: `year` and `month`. Measurement: `variable`, `value`, and `units`. Provenance: `source`, `source_url`, `licence`, `attribution`, `disclaimer`, and `observed_at`.

### How a run works

A run first re-reads the source host's robots posture from your runtime — the Commission's environmental data-query host — and stops at the door if a Disallow ever covers it. It then pages your country's Grassland Watch observation table, applies your optional `variable` and `year` filters, and flattens each observation to one record — carrying the value **verbatim**, never anything person-shaped — delivered **before** it is charged, so a blocked or empty run costs you nothing. The actor stops at your `maxRecords` ceiling and records `charge_equals_delivered` in the receipt.

### Coverage and scope

The dataset spans **27 EU countries**, each a separate multi-million-row observation table (Germany alone exceeds 3.7 million rows). A partition is required because of that scale: one country selects its table, and a `variable` or `year` narrows to a manageable slice. Because each record carries the `site_code`, `year`, `month`, and `variable`, a site's condition time series reconstructs by a simple sorted filter.

### Working with the observations

The observations are a time series waiting to be assembled, and the identifiers make that mechanical. Every record carries the `site_code`, `uid_lcu`, `year`, `month`, and `variable`, so a single filtered pull sorted by year and month reconstructs a site's condition trajectory for a given variable without any cross-table work. The `variable` field is the lever for comparing indicators — pull one variable across a country to map its spatial pattern, or several variables for one site to profile its condition — and the `units` travel on every row so a downstream consumer never has to guess a scale. Because the data is published per country and the country is the required partition, a run is always bounded to one national table; combine that with a `variable` and `year` and even a MONSTER country becomes a targeted, affordable slice rather than an accidental multi-million-row pull.

### Cost guidance

One `observation_record` per delivered observation: cost = rows delivered × your plan's per-record price. Always scope with `countryCode` and narrow with `variable`, `year`, and `maxRecords`. 1,000 observations is **$50** (Free) / **$33.50** (Gold). These are very large per-country tables, so filter and cap deliberately.

### Honest limitations

- **Monitoring data, not a verdict.** These are satellite-derived observations, not a compliance or land-management determination.
- **Partition required.** Every run must set a `countryCode`; there is no unbounded all-EU pull.
- **As published.** Values and units are carried verbatim; this actor reformats, it does not recompute.
- **Acknowledge the Commission.** The attribution travels on every record.
- **No person data** of any kind.

### Differentiation

This is a **net-new** category for the NexGenData fleet — no existing fleet actor covers EU grassland-condition monitoring. It is distinct from the fleet's protected-site register (Natura 2000 designations, not condition observations) and from any emissions or water cell. Its specific job is the **EU Grassland Watch observation series** — satellite-monitored grassland condition, site by site, month by month.

### The NexGen Signal family

Part of the NexGen Signal family of pay-per-record data products:

- [EU Natura 2000 Site Records — EEA Protected Sites](https://apify.com/nexgensignal/eu-natura2000-site-records)
- [EU Waterbody Quality Records — EEA WISE Waterbase](https://apify.com/nexgensignal/eu-waterbody-quality-records)
- [EU Industrial Emissions Records — EEA IED Facilities](https://apify.com/nexgensignal/eu-industrial-emissions-records)
- [EU Bathing Water Quality Records — EEA BWD](https://apify.com/nexgensignal/eu-bathing-water-quality-records)
- [EU Nitrate Monitoring Records — EEA WISE Nitrates](https://apify.com/nexgensignal/eu-nitrate-monitoring-records)

*Source: European Commission, EU Grassland Watch (apps.data.env.service.ec.europa.eu). Reused under the Creative Commons Attribution 4.0 International (CC BY 4.0) licence per the Commission's legal notice — free to reuse, including commercially, with attribution to the European Commission. Satellite-derived monitoring observations, not a compliance determination; values carried verbatim. Observation grain; no person data of any kind.*

# Actor input Schema

## `countryCode` (type: `string`):

REQUIRED 2-letter country code (one of the 27 EU Grassland Watch countries, e.g. DE, FR, ES). Each country is a separate MONSTER table; there is no unbounded all-EU pull.

## `variable` (type: `string`):

Optional. Keep only observations of this variable code (e.g. LWC).

## `year` (type: `integer`):

Optional observation year to filter (e.g. 2016).

## `maxRecords` (type: `integer`):

Maximum records delivered and billed. Bounds this MONSTER dataset.

## Actor input object example

```json
{
  "countryCode": "DE",
  "maxRecords": 500
}
```

# Actor output Schema

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

Delivered records.

# 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 = {
    "countryCode": "DE",
    "maxRecords": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgensignal/eu-grassland-condition-records").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 = {
    "countryCode": "DE",
    "maxRecords": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("nexgensignal/eu-grassland-condition-records").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 '{
  "countryCode": "DE",
  "maxRecords": 500
}' |
apify call nexgensignal/eu-grassland-condition-records --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexgensignal/eu-grassland-condition-records"
        }
    }
}

```

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/vjxviJ5sCmoPIVczW/builds/u0ePPyoumn3zLJlwv/openapi.json
