France's PV Atlas

EarthPV CalibrationSilverAbove 400 m² only.
Locally calibrated.
Add local training data →
France PV capacity, by 0.1° cell
11 km × 11 km cells · log scale
MWp / cell
hand-mapped OpenStreetMap capacity (ring grows with MWp)
hand-checked calibration area (hover for detail)
0MWp
Best estimate, the highest defensible figure
0
Training data hand-mapped in OpenStreetMap, ≥400 m²
0
Training data hand-mapped in OpenStreetMap, <400 m²
0
of 0.1° cells have density-matched sub-400 m² calibration
Capacity
The same Sentinel-2-detectable total, by installation size
Capacity per size bin, rooftop vs ground-mount
linear scale · MWp
rooftop
ground-mount
rooftop, extrapolated beyond calibration
The same total photovoltaic capacity detectable with Sentinel-2, re-cut by installation size instead of geography: rooftop bars stack across every bin, while ground-mount only shows up at ≥400 m² -- the two detectors split the total by placement and size, not size alone.
Capacity
The same total, by method
Total Capacity
0 MWp
0 MWp
TerraMind segmentation supplies 60% of Best; direct OSM mapping the remaining 40%.
Panel orientation
Fitted tilt & azimuth, from Sentinel-2 glint
Tilt (radius) × Azimuth (angle) 0 measured
rooftop generator ground plant unreachable by this sensor's fixed overpass time
0%
of ≥ 1,000 m² installations get a pose in this plot at all -- the rest never produce two self-consistent spikes, so there's nothing to fit
≥1 spike, no fittable pose; 0%
no glint signal at all 0%
azimuth range observed
tilt IQR observed

What is PV glint and how is it detected?

PV Glint is a brief, brighter-than-diffuse flash where a panel's specular reflection lines up with the sun and Sentinel-2's fixed overpass geometry on one date -- see the method page for the full derivation and an annotated image gallery. A single spike can't be checked for self-consistency -- 0% of installations glint once (or on dates that disagree on a panel geometry) and so are correctly detected as "PV is probably here" but carry no orientation information.

Why the plot only fills part of the circle

Sentinel-2 crosses this latitude at a fixed ~10:30 local time, so across two full years of imagery the sun's azimuth at the moment of every overpass never once swings west of due south -- a panel facing southwest, west, or north cannot glint into this sensor no matter how long you wait. That's a sensor limit, not a property of rooftops here: the shaded wedge (0° wide) marks orientations this survey cannot observe at all, not orientations known to be empty. Nothing is plotted there, because nothing was measured there.

Data: . Validated = a single (tilt, azimuth) explains ≥ 2 independent spike dates via the specular reflection condition, tolerance 3°. Point size ∝ √(installation area). Full derivation of the glint signal this pose fit is built on: the method page. Annotated Sentinel-2 / high-res examples of what a validated spike actually looks like in the source imagery: the image gallery.

Background
How to read these numbers
How confident should you be in this? preliminary results, sampling caveats, independent corroboration+

Best estimate: 13,369 MWp, with a 90% range of 11,478–17,762 MWp. That range covers two specific, measured sources of uncertainty -- but not everything that could move this number. Below: what's inside the range, what isn't, how many ground-truth areas it rests on, and how it compares to unrelated data sources.

What's inside the range:

  • The two "panel area to power" conversion numbers. One converts rooftop panel area to kWp, the other converts open-ground solar-farm land to kWp. Both are measured against real, confirmed power plants rather than assumed, but each carries its own uncertainty.
  • How well the detection model finds panels of different sizes. Its measured precision and recall were checked installation-size by installation-size, and that check itself has a margin of error.

What's outside the range -- and can't be added back in with more arithmetic:

  • The ground-truth areas were hand-picked, not randomly sampled, so this isn't a formal statistical margin of error. A figure from purposively chosen areas can be checked, argued with and improved, but it cannot be given a design-based confidence interval the way a random sample of the country's buildings could.
  • Ground-truth "complete" means complete as of when that area was mapped, not as of the satellite image used for detection. That cuts both ways, but in the same direction: it makes the model's measured accuracy look slightly worse than it is (recent real installations get scored as false alarms) and its measured miss rate look slightly better than it is (installations built after mapping can't be missed if they were never counted as ground truth to begin with). Both effects point the same way -- this page's figure is more likely an undercount than an overcount.
  • This page is a precision floor, not a recall-corrected estimate. France has no glint sample, so the chance that an unmapped detection is real is set to zero and the model's credit collapses to the share of its detections that OpenStreetMap already confirms. The recall correction that roughly doubles comparable Pakistani figures was deliberately not applied: the only French ground truth available to measure it against is a sub-400 m² population, and a correction fitted there would have been manufactured rather than measured.

Treat this as an early-stage estimate from an active research pipeline, not a finished census. What's genuinely new here -- a reproducible way to estimate distributed solar from free satellite imagery and open-source AI, in places where official statistics are sparse or absent -- holds regardless of whether any single number on this page turns out exactly right. Expect these figures to keep moving as the evidence behind them grows.

Fourteen French communes were mapped panel by panel, and what they measured is the limit of the instrument rather than a correction to it. Across 3,335 hand-drawn features on sub-metre imagery, the median installation is 20 m² against a Sentinel-2 pixel of 100 m². Detection recall climbs with array size across those communes (Spearman +0.83) while an independent model reading the same installations from sub-metre imagery is flat, which places the gradient in the sensor and not in the annotator. That is why this page has no small-panel half at all: the per-building classifier that supplies most of Pakistan's estimate scores 0.710 here against 0.857 there, and at a usable precision it flags 16 buildings out of 44,314. The communes are drawn on the map above; they set the floor, they do not raise the total.

France's own register says this page is missing most of the fleet, which is the expected result. The ODRE register puts French PV at roughly 34.6 GWp, several times the figure above, and 92.0% of French installations by count sit below this pipeline's 400 m² detection floor. Per commune, the detection estimators correlate with the register at Spearman 0.45 after retraining in domain, against 0.29 zero-shot -- the retrained model got the geography substantially better while recovering about a third of the capacity. Read the map for where French PV is, not for how much there is.

Data
Download the data behind this atlas
Download the underlying data capacity parquets, calibration boundaries, pose survey, raw detections, model checkpoint+
Live OSM PV, not this snapshot -- Overpass query
[out:json][timeout:180]; area ["boundary"="administrative"] ["admin_level"="2"] ["ISO3166-1"="FR"] ->.searchArea; ( nwr["power"="generator"]["generator:source"="solar"](area.searchArea); nwr["power"="plant"]["plant:source"="solar"](area.searchArea); ); out geom;
Paste into overpass-turbo.eu for an interactive map and GeoJSON export, or POST it as the data parameter to https://overpass-api.de/api/interpreter from a script. The raw-detections download above predates this page and will go stale as mappers keep editing; this query always reflects live OSM state.
Raw data

The capacity per grid cell shown on the map, as CSV. One row per 0.1° cell, generated in your browser from the data this page is drawing, so it is exactly the numbers above. lon0/lat0 are the south-west corner of the cell. The GeoParquet carries the cell polygon in EPSG:4326, so it opens directly in QGIS or GeoPandas.

Download GeoParquet