# France Official Weather Station Data: Météo-France Daily Obs (`plainworktools/meteo-france-daily-observations`) Actor

Official Météo-France daily climatological station data (2025 onward): clean station-day rows with original quality codes, per-station degree days (DJU) and rain/frost/gust day counts, and a monitor feed of new and corrected station-days. Informational; not an official certificate.

- **URL**: https://apify.com/plainworktools/meteo-france-daily-observations.md
- **Developed by:** [Plainwork Tools](https://apify.com/plainworktools) (community)
- **Categories:** Business, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## France Official Weather Station Data: Météo-France Daily Obs, Degree Days & Weather-Day Counts

> **FR.** Données climatologiques quotidiennes officielles de Météo-France (stations du réseau, depuis le
> 1er janvier 2025 jusqu'au dernier jour publié) : lignes station-jour propres avec les codes qualité d'origine, degrés-jours
> (DJU, méthode Météo-France), jours de pluie / gel / rafales et taux de complétude par station, et un flux de suivi des
> journées nouvelles ou corrigées. Les fichiers bruts sont gratuits sur meteo.data.gouv.fr ; cet Actor les
> télécharge, les vérifie, les joint et les calcule pour vous. Valeurs informatives : ce n'est pas une attestation officielle.

This Actor reads Météo-France's official **daily climatological files** ("Données climatologiques de base quotidiennes")
for every station in a department, from 2025-01-01 to the newest published day, and returns:

- **observations**: one clean row per station and day, every published value with its original Météo-France quality
  code, the two file families (`RR-T-Vent` and `autres-parametres`) joined without dropping stations;
- **summary**: per-station monthly or whole-range summaries: heating/cooling degree days (DJU), rain, frost and gust day
  counts, totals, extremes and per-variable completeness, with the rules stated in every row;
- **monitor**: a scheduled change feed of new, corrected and removed station-days since your last run.

Select stations by department, by station number, or by the nearest stations to a point.

**The raw files are free.** They are published as open data on [meteo.data.gouv.fr](https://meteo.data.gouv.fr)
(dataset "Données climatologiques de base - quotidiennes"). You pay this Actor for the work around them: no
per-department gzip handling, station lookup by id or nearest point, the two families joined, degree days and
weather days computed with stated rules, completeness, and a change feed you can schedule.

**Data is fetched only from Météo-France's public file host** (`meteofrance.s3.sbg.io.cloud.ovh.net`, the files linked
from the dataset page). No login, no API key, no other site. The Actor checks that host's `robots.txt` on every run
(today it does not exist: HTTP 404) and stops if that changes.

**Not a certificate.** All values are informational. They are not an official Météo-France attestation or certificate,
and Météo-France does not endorse this Actor. For a legal weather certificate (e.g. a court case or an insurance
claim), order one from Météo-France.

### Who it is for

- BTP contractors and site managers documenting weather days (intempéries) for a site;
- energy managers and consultants who need DJU (décret tertiaire, CEE, energy bills);
- insurers and loss adjusters checking rain, frost or wind on a date;
- agronomists, researchers, data teams and LLM agents that need a dated official observation.

### Input

| Field | Default | Meaning |
| :--- | :--- | :--- |
| `mode` | `observations` | `observations`, `summary` or `monitor` |
| `departments` | `[]` | File codes `01`-`95` (Corsica is one file: **use `20`**, not 2A/2B), `971`-`975`, `984`-`988` |
| `stationIds` | `[]` | 8-digit Météo-France station numbers, e.g. `31069001` (Toulouse-Blagnac). Max 500 |
| `nearLatitude`, `nearLongitude` | none | Pick the nearest stations to this point (both or neither) |
| `nearestCount` | 3 | 1-10 nearest stations |
| `maxDistanceKm` | 50 | Stations farther than this are not selected; none within range = input error |
| `families` | `["RR-T-Vent"]` | `RR-T-Vent` (rain, temperature, wind) and/or `autres-parametres` (humidity, sunshine, snow, phenomena…). Summary mode always uses `RR-T-Vent` |
| `dateFrom` | `dateTo` − 30 days | `YYYY-MM-DD`, from 2025-01-01 |
| `dateTo` | newest date in the files | `YYYY-MM-DD`, not after today (UTC) |
| `summaryPeriod` | `month` | `month` (calendar months within the range) or `range` (one row for the whole range) |
| `heatingBaseC`, `coolingBaseC` | 18, 18 | Degree-day bases (°C) |
| `rainThresholdMm` | 1.0 | Rain day: `RR` ≥ threshold |
| `frostThresholdC` | 0.0 | Frost day: `TN` ≤ threshold |
| `gustThresholdMs` | 16.0 | Gust day: `FXI` ≥ threshold (instantaneous gust at 10 m) |
| `excludeUnvalidated` | false | Summaries: count only quality 0/1 (true) or 0/1/9 (false). Quality 2 is never used |
| `lookbackDays` | 45 | Monitor window (newest available day and the days before it) |
| `emitQualityOnlyChanges` | false | Monitor: also output days whose values are unchanged but whose quality codes changed |
| `snapshotKey` | derived from the query | Monitor: name of the stored snapshot |
| `maxRows` | 10,000 | Upper bound on charged rows |

The selection is the union of `departments`, `stationIds` and the near-point stations. Every input error stops the run
before any download, with a message naming the field.

### Output

**Observation row**: `stationId`, `stationName`, `department`, `latitude`, `longitude`, `altitudeM`, `distanceKm` (near-point
selections only), `date`, then every value and quality column of each requested family **under its original Météo-France
name** (`RR`, `QRR`, `TN`, `QTN`, `HTN`, …, `TMERMAX`, `QTMERMAX`, `STATUS_FXI3S`, `STATUS_DXI3S`), `hasRrTVent`,
`hasOtherParameters` (whether the day exists in each family's file; `null` if that family was not requested),
`sourceFiles`, `sourceLastModified`, `retrievedAt` and `credit`.

- An empty cell is `null`, **never 0**. Decimals stay as published (`13.3`). Quality and status codes are integers. Hour
  fields stay `hhmm` integers without leading zeros (`144` = 01:44).
- A quality code can be present without a value; it is kept.

**Summary row**: station fields, `periodStart`, `periodEnd`, `clippedToAvailable`, `daysInPeriod`, `daysWithRow`, `rrTotalMm`,
`rainDays`/`rainDaysObserved`, `frostDays`/`frostDaysObserved`, `gustDays`/`gustDaysObserved`, `tnMinC`, `txMaxC`, `hddSum`,
`cddSum`, `degreeDayDaysObserved`, `completeness` (`{RR, TN, TX, FXI}` = usable days / `daysInPeriod`), `doubtfulExcluded`,
`unvalidatedUsed`, `noData`, the thresholds and bases used, `method`, `sourceFiles`, `sourceLastModified`, `retrievedAt`,
`credit`.

**Change row** (monitor): the observation row plus `changeType` (`new`, `corrected`, `quality_only`, `removed`),
`previousHash` and `snapshotTakenAt`. A `removed` row carries only the station fields and `date`; all value columns are `null`.

**`OUTPUT` record** (key-value store): mode, resolved selection, requests made, files read (max date, `Last-Modified`,
sha256), `newestAvailableDate`, `requestedBeyondAvailable`, `staleFiles` (files ending more than 7 days before the run date),
`withheldStations`, `stationsWithoutRows`, rows pushed and charged, `truncated`, `baseline_created`, change counts and
warnings. Every request is listed in the `REQUEST_LOG` record.

### Calculation rules (summary)

- A value is **usable** when it is present and its quality code is allowed (0, 1, 9; or 0, 1 with
  `excludeUnvalidated`). Quality 2 (doubtful) is never usable. Unusable and missing values are skipped, **never imputed and
  never counted as 0**.
- `rainDays` = usable days with `RR` ≥ threshold; `rainDaysObserved` = usable `RR` days. Frost (`TN` ≤ threshold) and gust
  (`FXI` ≥ threshold) work the same way.
- Degree days use the Météo-France method: `Tavg = (TN + TX) / 2` on days where both are usable;
  `HDD = max(0, heatingBase − Tavg)`, `CDD = max(0, Tavg − coolingBase)`. Sums are exact and rounded to 0.1 (half up) only
  at the end. `degreeDayDaysObserved` counts those days. `rrTotalMm` is the sum of usable `RR`; `hddSum`, `cddSum`,
  `rrTotalMm`, `tnMinC` and `txMaxC` are `null` when nothing usable exists.
- The period is clipped to the last date of the station's file (`clippedToAvailable: true`); `daysInPeriod` counts the
  clipped calendar days. A month that lies entirely after the file's last date gives `daysInPeriod: 0`, `noData: true`
  and a `periodEnd` before `periodStart` (the file's last date).
- `noData: true` when no usable `RR`, `TN`, `TX` or `FXI` exists. Such rows are output **free of charge**.
- Every row carries the `method` text, e.g. "DJU méthode Météo-France (TN+TX)/2, base 18 °C; quality codes used: 0, 1, 9;
  quality 2 excluded; missing values not imputed; informational, not an official certificate."

### Monitor mode

Schedule the Actor (e.g. every Monday at 06:00 UTC) with `mode: monitor` and a fixed `snapshotKey`. Each run computes the
station-days of the window (newest available day back `lookbackDays` days) and compares them with the snapshot stored in
the named key-value store `meteofrance-daily-snapshots`:

- first run: stores a baseline, outputs nothing, charges only the start;
- `new`: a station-day not in the snapshot; `corrected`: a value changed; `quality_only`: only quality codes changed
  (counted in `OUTPUT`, output only with `emitQualityOnlyChanges`); `removed`: a day inside both windows that disappeared
  (output free of charge). Days that slide out of the window are dropped silently;
- the snapshot is replaced only after a fully successful run. If the change set exceeds `maxRows` or your max charge,
  the run fails before outputting anything ("raise maxRows / max charge") and the snapshot stays unchanged;
- a `snapshotKey` used with a different selection, families or `lookbackDays` is an input error (the snapshot's
  `queryHash` differs). The default key is derived from those settings;
- a station withheld by the catalog guard (see Limitations) is not a deletion: it outputs no change rows and its
  snapshot state is kept (sliding with the window). When it returns, only what really changed since it was last
  compared is output (`new`, `corrected`, `removed` as usual), so unchanged days are never output or charged again.
  A station already withheld at the first run is listed in `OUTPUT.changes.untrackedStations`; when it returns, its
  state is taken silently like a baseline (`stationsBaselined`, no rows, no charge).

### Examples

The four outputs below come from running this Actor on the live files of 2026-10-09 (values are Météo-France's;
long rows are shortened with `…`).

#### 1. Toulouse-Blagnac wind on 9 Jan 2026 (insurer / loss adjuster)

Input:

```json
{
  "stationIds": [
    "31069001"
  ],
  "dateFrom": "2026-01-09",
  "dateTo": "2026-01-09"
}
```

Output (1 row, 1 `station-day` = USD 0.0005 + start):

```json
{
  "stationId": "31069001",
  "stationName": "TOULOUSE-BLAGNAC",
  "department": "31",
  "latitude": 43.621,
  "longitude": 1.378833,
  "altitudeM": 151,
  "distanceKm": null,
  "date": "2026-01-09",
  "RR": 16.7,
  "QRR": 1,
  "TN": 4.8,
  "QTN": 1,
  "TX": 9.2,
  "QTX": 1,
  "FFM": 8.7,
  "QFFM": 1,
  "FXY": 14.0,
  "QFXY": 1,
  "DXY": 270,
  "HXY": 1338,
  "FXI": 22.3,
  "QFXI": 1,
  "DXI": 250,
  "QDXI": 1,
  "HXI": 1024,
  "QHXI": 9,
  "FXI3S": 21.5,
  "QFXI3S": 1,
  "STATUS_FXI3S": 0,
  "STATUS_DXI3S": 1,
  "…": "…",
  "hasRrTVent": true,
  "hasOtherParameters": null,
  "sourceFiles": [
    "https://meteofrance.s3.sbg.io.cloud.ovh.net/data/synchro_ftp/BASE/QUOT/Q_31_latest-2025-2026_RR-T-Vent.csv.gz"
  ],
  "sourceLastModified": {
    "https://meteofrance.s3.sbg.io.cloud.ovh.net/data/synchro_ftp/BASE/QUOT/Q_31_latest-2025-2026_RR-T-Vent.csv.gz": "2026-10-08T08:51:04Z"
  },
  "credit": "Source : Météo-France (Données climatologiques de base quotidiennes, Licence Ouverte 2.0), file updated 2026-10-08T08:51:04Z. Reformatted by this Actor; not an official Météo-France publication or certificate."
}
```

`FXI` 22.3 m/s (80 km/h) is the day's maximum instantaneous gust at 10 m, from 250° (`DXI`), at `HXI` 1024 (10:24); `RR` 16.7 mm
fell between 06 UTC on the 9th and 06 UTC on the 10th. Quality 1 = validated.

#### 2. Colmar stations for 2026 (agronomy / research)

Input (Colmar-INRAE, Colmar-Meyenheim and Bergheim-INRAE, 1 January 2026 to the newest day):

```json
{
  "stationIds": [
    "68066001",
    "68205001",
    "68028001"
  ],
  "dateFrom": "2026-01-01",
  "families": [
    "RR-T-Vent"
  ],
  "maxRows": 5000
}
```

Output: 837 rows (68028001: 279, 68066001: 279, 68205001: 279), `dateTo` resolved to
2026-10-06, the newest day in the file. One of them:

```json
{
  "stationId": "68066001",
  "stationName": "COLMAR-INRAE",
  "date": "2026-02-25",
  "RR": 0.0,
  "QRR": 1,
  "TN": 5.7,
  "QTN": 1,
  "TX": 12.2,
  "QTX": 1,
  "TM": 8.3,
  "QTM": 1,
  "FXI": null,
  "QFXI": null,
  "…": "…"
}
```

Add `"families": ["RR-T-Vent", "autres-parametres"]` for humidity, sunshine, ETP and snow, or switch to `mode: summary`
for monthly totals.

#### 3. BTP monthly weather-day summary for 3 sites

Input (September 2026; rain day ≥ 1 mm, frost day TN ≤ 0 °C, gust day FXI ≥ 16 m/s):

```json
{
  "mode": "summary",
  "stationIds": [
    "75106001",
    "69029001",
    "13054001"
  ],
  "dateFrom": "2026-09-01",
  "dateTo": "2026-09-30",
  "summaryPeriod": "month",
  "rainThresholdMm": 1,
  "frostThresholdC": 0,
  "gustThresholdMs": 16
}
```

Output: 3 summaries (3 × `station-summary` = USD 0.06 + start). Lyon-Bron:

```json
{
  "stationId": "69029001",
  "stationName": "LYON-BRON",
  "periodStart": "2026-09-01",
  "periodEnd": "2026-09-30",
  "clippedToAvailable": false,
  "daysInPeriod": 30,
  "daysWithRow": 30,
  "rrTotalMm": 10.1,
  "rainDays": 2,
  "rainDaysObserved": 30,
  "frostDays": 0,
  "frostDaysObserved": 30,
  "gustDays": 2,
  "gustDaysObserved": 30,
  "tnMinC": 8.8,
  "txMaxC": 35.8,
  "hddSum": 3.0,
  "cddSum": 93.0,
  "degreeDayDaysObserved": 30,
  "completeness": {
    "RR": 1.0,
    "TN": 1.0,
    "TX": 1.0,
    "FXI": 1.0
  },
  "doubtfulExcluded": {
    "RR": 0,
    "TN": 0,
    "TX": 0,
    "FXI": 0
  },
  "unvalidatedUsed": {
    "RR": 0,
    "TN": 0,
    "TX": 0,
    "FXI": 0
  },
  "noData": false,
  "method": "DJU méthode Météo-France (TN+TX)/2, base 18 °C; quality codes used: 0, 1, 9; quality 2 excluded; missing values not imputed; informational, not an official certificate.",
  "…": "…"
}
```

The other two sites: MARIGNANE: 2 rain days, 4 gust days (30 observed), HDD 0.0, CDD 162.6; LUXEMBOURG: 2 rain days, 0 gust days (0 observed), HDD 0.7, CDD 96.2.
Luxembourg (Paris) publishes no `FXI` value for September 2026, so `gustDaysObserved` is 0 and `completeness.FXI` is 0.0:
the gust count is unknown, not zero.

#### 4. Weekly monitor schedule for one department

Create a saved task with this input and an Apify schedule such as `0 6 * * 1` (Mondays 06:00 UTC):

```json
{
  "mode": "monitor",
  "departments": [
    "31"
  ],
  "lookbackDays": 45,
  "snapshotKey": "toulouse-weekly"
}
```

First run: `OUTPUT.baseline_created` is true, 831 station-days of 2026-08-24 to
2026-10-07 are stored, nothing is output and only the start is charged. Later runs output only what changed
since the previous run. A correction looks like this (from the acceptance tests, where a stored entry was altered to
simulate a corrected value):

```json
{
  "changeType": "corrected",
  "stationId": "31374001",
  "stationName": "MONTESQUIEU-LAURAGAIS",
  "department": "31",
  "date": "2026-09-12",
  "RR": 0.0,
  "QRR": 1,
  "TN": 11.8,
  "QTN": 1,
  "TX": 29.7,
  "QTX": 1,
  "…": "…",
  "previousHash": "23867c3c43831f1c",
  "snapshotTakenAt": "2026-10-09T08:24:03.019451+00:00"
}
```

### Pricing (pay per event)

| Event | Price (USD) | Charged when |
| :--- | ---: | :--- |
| Actor start | 0.005 | once per run |
| `station-day` | 0.0005 | each observation row; each `new`, `corrected` or emitted `quality_only` change row |
| `station-summary` | 0.02 | each summary row with at least one usable value |

Never charged: withheld stations, `noData` summaries, `removed` rows, monitor baselines, and anything in a failed run.
Observations and summaries stop cleanly at `maxRows` or your maximum charge (`truncated: true` in `OUTPUT`).

Typical costs: one station for one month = 30 rows ≈ USD 0.02; a monthly weather-day summary for 5 sites = USD 0.105
including the start; a year of monthly DJU for 20 sites = 240 summaries = USD 4.81; one department, 30 days, both families
≈ 600 rows ≈ USD 0.31.

### Credit and licence

Every row carries the credit line:

> Source : Météo-France (Données climatologiques de base quotidiennes, Licence Ouverte 2.0), file updated
> \<Last-Modified>. Reformatted by this Actor; not an official Météo-France publication or certificate.

The data is published by Météo-France under the [Licence Ouverte 2.0](https://www.etalab.gouv.fr/licence-ouverte-open-licence/),
which allows commercial reuse with attribution ("Source : Météo-France" and the update date). Keep the credit when you
republish the data.

### Data lag and conventions

- **Lag**: a day typically appears J+1 to J+3. Values can be corrected later: stations of type 3/4 are expert-validated up to
  M+21 days, and quality codes move from 9 (filtered) to 1 (validated) or 0 (protected). The publisher's files have stalled
  for days at times (June 2026). `OUTPUT.staleFiles` lists files ending more than 7 days before the run date.
- **RR and HNEIGEF** cover 06 UTC day J to 06 UTC day J+1 and are filed under day J (the value read on J+1 belongs to J).
- Times (`HTN`, `HTX`, `HXI`, …) are `hhmm` integers as published. Météo-France's field file gives their format but
  not their time zone; only some definitions (`RR`, `HNEIGEF`, `NEIGETOTX`) state UTC ("FU").

#### Quality codes (Météo-France)

| Code | Meaning |
| :--- | :--- |
| 9 | filtered: the value passed the first-level checks |
| 0 | protected: definitively validated by the climatologist |
| 1 | validated: by automatic check or by the climatologist |
| 2 | doubtful: flagged by an automatic check, being verified |
| (empty) | no quality code |

Every value column `X` has a quality column `QX`. `STATUS_FXI3S` (0 not computed, 1 transfer function) and `STATUS_DXI3S`
(0 measured, 1 taken from DXI) have no quality column.

### Field dictionary

Built from Météo-France's two field description files (`Q_descriptif_champs_RR-T-Vent.csv`,
`Q_descriptif_champs_autres-parametres.csv`). Each value field `X` is followed in the output by its quality code `QX`.

| Field | File family | Meaning (EN) | Météo-France definition (FR, verbatim) |
| :--- | :--- | :--- | :--- |
| `NUM_POSTE` | both | station number (8 digits) -> stationId | numéro Météo-France du poste sur 8 chiffres |
| `NOM_USUEL` | both | station name -> stationName | nom usuel du poste |
| `LAT` | both | latitude, decimal degrees -> latitude | latitude, négative au sud (en degrés et millionièmes de degré) |
| `LON` | both | longitude, decimal degrees -> longitude | longitude, négative à l’ouest de GREENWICH (en degrés et millionièmes de degré) |
| `ALTI` | both | altitude of the shelter or rain gauge, m -> altitudeM | altitude du pied de l'abri ou du pluviomètre si pas d'abri (en m) |
| `AAAAMMJJ` | both | date YYYYMMDD -> date (YYYY-MM-DD) | date de la mesure (année mois jour) |
| `RR` | RR-T-Vent | precipitation over 24 h, 06 UTC day J to 06 UTC J+1, filed under day J (mm) | quantité de précipitation tombée en 24 heures (de 06h FU le jour J à 06h FU le jour J+1). La valeur relevée à J+1 est affectée au jour J (en mm et 1/10) |
| `TN` | RR-T-Vent | minimum temperature under shelter (°C) | température minimale sous abri (en °C et 1/10) |
| `HTN` | RR-T-Vent | time of TN (hhmm) | heure de TN (hhmm) |
| `TX` | RR-T-Vent | maximum temperature under shelter (°C) | température maximale sous abri (en °C et 1/10) |
| `HTX` | RR-T-Vent | time of TX (hhmm) | heure de TX (hhmm) |
| `TM` | RR-T-Vent | daily mean of hourly temperatures (°C) | moyenne quotidienne des températures horaires sous abri (en °C et 1/10) |
| `TNTXM` | RR-T-Vent | daily mean (TN+TX)/2 (°C) | moyenne quotidienne (TN+TX)/2 (en °C et 1/10) |
| `TAMPLI` | RR-T-Vent | daily temperature range TX-TN (°C) | amplitude thermique quotidienne : écart entre TX et TN quotidiens (TX-TN) (en °C et 1/10) |
| `TNSOL` | RR-T-Vent | minimum temperature 10 cm above ground (°C) | température quotidienne minimale à 10 cm au-dessus du sol (en °C et 1/10) |
| `TN50` | RR-T-Vent | minimum temperature 50 cm above ground (°C) | température quotidienne minimale à 50 cm au-dessus du sol (en °C et 1/10) |
| `DG` | RR-T-Vent | frost duration under shelter, T ≤ 0 °C (min) | durée de gel sous abri (T ≤ 0°C) (en mn) |
| `FFM` | RR-T-Vent | mean 10-min wind speed at 10 m (m/s) | moyenne quotidienne de la force du vent moyenné sur 10 mn, à 10 m (en m/s et 1/10) |
| `FF2M` | RR-T-Vent | mean 10-min wind speed at 2 m (m/s) | moyenne quotidienne de la force du vent moyenné sur 10 mn, à 2 m (en m/s et 1/10) |
| `FXY` | RR-T-Vent | max hourly 10-min mean wind at 10 m (m/s) | maximum quotidien de la force maximale horaire du vent moyenné sur 10 mn, à 10 m (en m/s et 1/10) |
| `DXY` | RR-T-Vent | direction of FXY (degrees) | direction de FXY (en rose de 360) |
| `HXY` | RR-T-Vent | time of FXY (hhmm) | heure de FXY (hhmm) |
| `FXI` | RR-T-Vent | max instantaneous gust at 10 m (m/s) | maximum quotidien de la force maximale horaire du vent instantané, à 10 m (en m/s et 1/10) |
| `DXI` | RR-T-Vent | direction of FXI (degrees) | direction de FXI (en rose de 360) |
| `HXI` | RR-T-Vent | time of FXI (hhmm) | heure de FXI (hhmm) |
| `FXI2` | RR-T-Vent | max instantaneous gust at 2 m (m/s) | maximum quotidien de la force maximale horaire du vent instantané, à 2 m (en m/s et 1/10) |
| `DXI2` | RR-T-Vent | direction of FXI2 (degrees) | direction de FXI2 (en rose de 360) |
| `HXI2` | RR-T-Vent | time of FXI2 (hhmm) | heure de FXI2 (hhmm) |
| `FXI3S` | RR-T-Vent | max 3-second mean wind at 10 m (m/s) | maximum quotidien de la force maximale horaire du vent moyenné sur 3 s, à 10 m (en m/s et 1/10) |
| `DXI3S` | RR-T-Vent | direction of FXI3S (degrees) | direction de FXI3S (en rose de 360) |
| `HXI3S` | RR-T-Vent | time of FXI3S (hhmm) | heure de FXI3S (hhmm) |
| `DRR` | RR-T-Vent | precipitation duration (min) | durée des précipitations (en mn) |
| `STATUS_FXI3S` | RR-T-Vent | how FXI3S was obtained: 0 not computed, 1 transfer function | code indiquant le mode d'obtention du FXI3S (0: non calculé, 1: calculé à partir d'une fonction de transfert) |
| `STATUS_DXI3S` | RR-T-Vent | how DXI3S was obtained: 0 measured, 1 taken from DXI | code indiquant le mode d'obtention du DXI3S (0: mesuré, 1: assimilé à DXI) |
| `DHUMEC` | autres-parametres | leaf wetness duration (min) | durée d’humectation (en mn) |
| `PMERM` | autres-parametres | mean sea-level pressure (hPa) | moyenne quotidienne des pressions mer horaires (en hPa et 1/10) |
| `PMERMIN` | autres-parametres | minimum sea-level pressure (hPa) | minimum quotidien des pressions mer minimales horaires (en hPa et 1/10) |
| `INST` | autres-parametres | sunshine duration (min) | durée d’insolation quotidienne (en mn) |
| `GLOT` | autres-parametres | global radiation (J/cm²) | rayonnement global quotidien (en J/cm2) |
| `DIFT` | autres-parametres | diffuse radiation (J/cm²) | rayonnement diffus quotidien (en J/cm2) |
| `DIRT` | autres-parametres | direct radiation (J/cm²) | rayonnement direct quotidien (en J/cm2) |
| `INFRART` | autres-parametres | sum of hourly infrared radiation (J/cm²) | somme des rayonnements infra-rouge horaires (en J/cm2) |
| `UV` | autres-parametres | daily UV radiation (J/cm²) | cumul quotidien de rayonnement ultra-violet (en J/cm2) |
| `UV_INDICEX` | autres-parametres | maximum hourly UV index | maximum des indices UV horaires |
| `SIGMA` | autres-parametres | sunshine fraction of day length (%) | fraction d’insolation par rapport à la durée du jour (en %) |
| `UN` | autres-parametres | minimum relative humidity (%) | minimum quotidien des humidités relatives minimales horaires (en %) |
| `HUN` | autres-parametres | time of UN (hhmm) | heure de UN (hhmm) |
| `UX` | autres-parametres | maximum relative humidity (%) | maximum quotidien des humidités relatives maximales horaires (en %) |
| `HUX` | autres-parametres | time of UX (hhmm) | heure de UX (hhmm) |
| `UM` | autres-parametres | mean relative humidity (%) | moyenne quotidienne des humidités relatives horaires (en %) |
| `DHUMI40` | autres-parametres | duration with U ≤ 40 % (min) | durée humidité avec U ≤ 40 % (en mn) |
| `DHUMI80` | autres-parametres | duration with U ≥ 80 % (min) | durée humidité U ≥ 80 % (en mn) |
| `TSVM` | autres-parametres | mean vapour pressure (hPa) | tension de vapeur moyenne (en hPa et 1/10) |
| `ETPMON` | autres-parametres | Penman-Monteith potential evapotranspiration (mm) | ETP Penman-Monteith quotidienne (en mm et 1/10) |
| `ETPGRILLE` | autres-parametres | Penman-Monteith ETP at the nearest grid point (mm) | ETP Penman-Monteith calculée au point de grille le plus proche (en mm et 1/10) |
| `ECOULEMENTM` | autres-parametres | unused field | champ inutilisé |
| `HNEIGEF` | autres-parametres | fresh snow over 24 h, 06 UTC J to 06 UTC J+1, still on the ground at 06 UTC (cm) | hauteur de neige fraîche tombée en 24 heures (de 06h FU le jour J à 06h FU le jour J+1) qui reste au sol à 06h FU. La valeur relevée à J+1 est affectée au jour J (en cm) |
| `NEIGETOTX` | autres-parametres | maximum daily snow depth (cm) | épaisseur maximale de neige quotidienne (entre 01h et 24h FU) (en cm) |
| `NEIGETOT06` | autres-parametres | snow depth measured at 6 h (cm) | épaisseur totale de neige au sol mesurée à 6h (NEIGETOT de 6h) (en cm) |
| `NEIG` | autres-parametres | snow occurrence (0/1) | occurrence de neige (0 s’il n’a pas neigé, 1 s’il a neigé) |
| `BROU` | autres-parametres | fog occurrence (0/1) | occurrence de brouillard (0 ou 1 si phéno.) |
| `ORAG` | autres-parametres | thunderstorm occurrence (0/1) | occurrence d’orage (0 ou 1 si phéno.) |
| `GRESIL` | autres-parametres | sleet/graupel occurrence (0/1) | occurrence de grésil (0 ou 1 si phéno.) |
| `GRELE` | autres-parametres | hail occurrence (0/1) | occurrence de grêle (0 ou 1 si phéno.) |
| `ROSEE` | autres-parametres | dew occurrence (0/1) | occurrence de rosée (0 ou 1 si phéno.) |
| `VERGLAS` | autres-parametres | glaze ice occurrence (0/1) | occurrence de verglas (0 ou 1 si phéno.) |
| `SOLNEIGE` | autres-parametres | snow-covered ground (0/1) | occurrence de sol couvert de neige (0 ou 1 si phéno.) |
| `GELEE` | autres-parametres | hoar frost occurrence (0/1) | occurrence de gelée blanche (0 ou 1 si phéno.) |
| `FUMEE` | autres-parametres | smoke occurrence (0/1) | occurrence de fumée (0 ou 1 si phéno.) |
| `BRUME` | autres-parametres | mist occurrence (0/1) | occurrence de brume (0 ou 1 si phéno.) |
| `ECLAIR` | autres-parametres | lightning occurrence (0/1) | occurrence d’éclair (0 ou 1 si phéno) |
| `NB300` | autres-parametres | max cloud cover > 4/8 with base < 300 m (octa) | nébulosité maximale > 4/8 et couche < 300 m (en octa) |
| `BA300` | autres-parametres | minimum base height of NB300 (m) | hauteur minimale de NB300 (en m) |
| `TMERMIN` | autres-parametres | minimum sea water temperature (°C) | température minimale quotidienne de l’eau de mer (en °C et 1/10) |
| `TMERMAX` | autres-parametres | maximum sea water temperature (°C) | température maximale quotidienne de l’eau de mer (en °C et 1/10) |

### Limitations

- **Data from 2025-01-01 only** (the `latest-2025-2026` files). Older years are in separate archives this Actor does not read.
- **Year rollover**: when Météo-France starts the next file span, the current files disappear and the run fails with
  "source file missing … (possible year rollover; Actor update required)". The Actor never guesses a new file name; an
  update follows after review.
- **Nearest station ≠ your exact site.** Weather can differ over a few kilometres; check `distanceKm` and `altitudeM`.
- **Not a certificate** (see above).
- **No Mayotte (976)**: Météo-France publishes no file for it. Corsica is department file `20`.
- Stations are limited to a reviewed catalog of 2,408 stations. A station that is new, renamed or moved to another
  department file is **withheld** (not output, not charged, listed by number in `OUTPUT.withheldStations`) until the
  catalog is reviewed in an Actor update. A station that leaves its department file for a file your query does not
  download cannot be told apart from a deletion: in monitor mode its days in both windows are output as `removed` (free).
- The whole run fails, with nothing charged beyond the start, if any downloaded file is malformed in any row (not only
  your stations or dates). Partial or guessed data is never output.

# Actor input Schema

## `mode` (type: `string`):

observations = one row per station and day; summary = per-station period summaries from RR-T-Vent; monitor = change feed against a stored snapshot (schedule it).

## `departments` (type: `array`):

Department file codes: 01-95 (Corsica is one file: use 20, not 2A/2B), 971, 972, 973, 974, 975, 984, 985, 986, 987, 988. Mayotte (976) has no file. Selects every reviewed station in those files.

## `stationIds` (type: `array`):

8-digit Météo-France station numbers (NUM_POSTE) from the reviewed catalog, e.g. 31069001 (Toulouse-Blagnac). Max 500.

## `nearLatitude` (type: `number`):

Select the nearest stations to this point (give it with Near longitude).

## `nearLongitude` (type: `number`):

Longitude of the point (negative west of Greenwich).

## `nearestCount` (type: `integer`):

How many nearest stations to select (used only with the near point).

## `maxDistanceKm` (type: `number`):

Stations farther than this from the near point are not selected. If none is within range, the run fails before any request.

## `families` (type: `array`):

Which daily files to read and join. Summary mode always uses RR-T-Vent only.

## `dateFrom` (type: `string`):

YYYY-MM-DD, on or after 2025-01-01. Default: dateTo minus 30 days. Ignored in monitor mode.

## `dateTo` (type: `string`):

YYYY-MM-DD, not after today (UTC). Default: the newest date in the fetched files. Ignored in monitor mode.

## `summaryPeriod` (type: `string`):

Summary mode: one row per station per calendar month (intersected with the range), or one row for the whole range.

## `heatingBaseC` (type: `number`):

HDD = max(0, base - (TN+TX)/2).

## `coolingBaseC` (type: `number`):

CDD = max(0, (TN+TX)/2 - base).

## `rainThresholdMm` (type: `number`):

Rain day: RR >= threshold.

## `frostThresholdC` (type: `number`):

Frost day: TN <= threshold.

## `gustThresholdMs` (type: `number`):

Gust day: FXI (instantaneous gust at 10 m) >= threshold.

## `excludeUnvalidated` (type: `boolean`):

Summaries: when on, only quality codes 0/1 count as usable; when off, 0/1/9. Quality 2 (doubtful) is never used.

## `lookbackDays` (type: `integer`):

Monitor window: the newest available date and the days before it.

## `emitQualityOnlyChanges` (type: `boolean`):

Monitor: also output station-days whose values are unchanged but whose quality codes changed (charged as station-day).

## `snapshotKey` (type: `string`):

Monitor: name of the stored snapshot (named key-value store meteofrance-daily-snapshots). Default: derived from the query.

## `maxRows` (type: `integer`):

Upper bound on charged rows. Observations/summary stop cleanly (truncated); monitor fails before pushing if the change set is larger.

## Actor input object example

```json
{
  "mode": "observations",
  "departments": [
    "31"
  ],
  "stationIds": [],
  "nearestCount": 3,
  "maxDistanceKm": 50,
  "families": [
    "RR-T-Vent"
  ],
  "summaryPeriod": "month",
  "heatingBaseC": 18,
  "coolingBaseC": 18,
  "rainThresholdMm": 1,
  "frostThresholdC": 0,
  "gustThresholdMs": 16,
  "excludeUnvalidated": false,
  "lookbackDays": 45,
  "emitQualityOnlyChanges": false,
  "maxRows": 10000
}
```

# Actor output Schema

## `observations` (type: `string`):

Station-day rows with the original Météo-France quality codes (mode: observations).

## `summaries` (type: `string`):

Per-station degree days (DJU) and rain, frost and gust day counts (mode: summaries).

## `changes` (type: `string`):

New and corrected station-days since the previous run (mode: changes).

## `runSummary` (type: `string`):

The OUTPUT record: counts, charged events, withheld stations and warnings.

# 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 = {
    "departments": [
        "31"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("plainworktools/meteo-france-daily-observations").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 = { "departments": ["31"] }

# Run the Actor and wait for it to finish
run = client.actor("plainworktools/meteo-france-daily-observations").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 '{
  "departments": [
    "31"
  ]
}' |
apify call plainworktools/meteo-france-daily-observations --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,plainworktools/meteo-france-daily-observations"
        }
    }
}
```

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/7a5ThMbExGoZUkneS/builds/2hrrokYcbpipcsjDO/openapi.json
