Human infrastructure (wind farms, power lines, buildings) causes significant bird mortality worldwide. This tool visualizes the overlap between bird habitats and wind energy infrastructure in Norway, enabling data driven pre-stage screening before new projects are planned.
By combining open biodiversity data with turbine locations and species flight altitudes, we can identify areas where endangered species are most at risk from rotor collisions, helping developers and regulators make informed decisions about site selection.
Norwegian Red List for Species 2021, published by Artsdatabanken. Categories follow the IUCN framework.
| CR | Critically endangered Extremely high risk of extinction. Fewer than 50 mature individuals or 80%+ population decline over 3 generations. |
| EN | Endangered Very high risk of extinction. 50 to 250 mature individuals or 50-80% population decline over 3 generations. |
| VU | Vulnerable High risk of extinction. 30-50% population decline or fewer than 10,000 mature individuals. |
| NT | Near threatened Close to qualifying for a threatened category. Declining trends that may worsen. |
Norwegian wind turbines have hub heights of 31 to 145m and rotor diameters of 27 to 150m. The rotor swept zone varies per park. In the conflict scoring, each park is evaluated against its own rotor zone from NVE data.
| ▲ | High overlap More than 50% of the species' typical flight altitude band falls within the rotor zone. Examples: white-tailed eagle (50-300m), buzzards (30-200m), gulls (10-150m). |
| ● | Partial overlap Some flight altitude overlaps with the rotor zone but less than 50%. Examples: barn swallows (5-100m), starlings (5-100m). |
| no icon | Low or no overlap Species typically flies below 30m or above 200m. Examples: small passerines (2-30m), high-migrating geese (50-800m in transit). |
Flight altitudes are approximate estimates based on general ornithological knowledge of each species' typical flight behavior. They are informed by published literature on collision risk and marine bird flight heights (see references below) but the specific [min, max] values were not directly extracted from those papers. Values represent typical local flight, not migration altitude.
The heatmap shows observation density from a 10,000 record sample. Brighter areas have more reported bird observations. This reflects where people observe birds, not necessarily where bird density is highest. Urban areas and popular birding sites are overrepresented.
Points view shows individual observations as colored circles. Each species gets a unique color. Click a point to see species details, red list status, flight altitude, rotor zone overlap and observation count in the current filtered view.
| Low to high observation density (inferno color scale) | |
| Wind turbine park (icon size = installed capacity in MW) |
Each wind park is color coded from green (low conflict) through yellow (moderate) to red (high conflict) based on a composite score of nearby bird observations.
Step 1. Find nearby observations
For each park, all bird observations within a 30 km radius are collected. Distance is computed using a flat-Earth approximation (sufficient at Norway's scale).
dx = (obs.lon - park.lon) × 111 × cos(park.lat) dy = (obs.lat - park.lat) × 111 distance = sqrt(dx² + dy²) // in km
111 km = one degree of latitude (Earth circumference 40 000 km / 360°). The cos(lat) term corrects longitude because meridians converge toward the poles. At 60°N (southern Norway) one degree of longitude is ~55 km, not 111. This flat earth shortcut gives the same result as the Haversine formula at distances under 30 km, while being simpler and faster to compute.
Step 2. Weight each observation
Each observation starts with a base weight of 1. Two multipliers are applied.
| Red list multiplier | |
| CR | × 8 |
| EN | × 5 |
| VU | × 3 |
| NT | × 1.5 |
| Not listed | × 1 (no change) |
| Rotor zone overlap multiplier | |
| High overlap | × 3 |
| Partial overlap | × 1.5 |
| Low / unknown | × 1 (no change) |
Red list weights reflect the relative severity of IUCN categories: CR species face imminent extinction, so each observation is weighted heavily (×8). The specific multipliers (8, 5, 3, 1.5) are author chosen, not from a published standard, but preserve the ordering of conservation priority. The 30 km search radius approximates a typical foraging and commuting range for medium to large birds. All observations within this radius are weighted equally (no distance decay).
weight = 1.0 if species in Red List: weight × red_list_multiplier if species rotor overlap: weight × rotor_multiplier score = sum of all weighted observations within 30 km
Step 3. Normalize and color
The raw score is normalized to a 0 to 1 range by dividing by 300 (empirical threshold based on our 10K sample), clamped at 1.0. The color is interpolated: green channel fades out above 0.5, red channel fades in below 0.5.
normalized = min(1, score / 300) Color mapping: 0.0 - 0.2 → green (low bird conflict) 0.2 - 0.5 → yellow (moderate bird conflict) 0.5 - 0.75 → orange (high bird conflict) 0.75 - 1.0 → red (very high bird conflict)
The normalization constant (300) is empirical, calibrated so that the 10K observation sample produces a spread of scores across all four risk levels. If the dataset grows significantly, this threshold should be recalibrated.
For each species with known flight altitude data, we calculate how much of its typical flight band overlaps with the park's specific rotor swept zone (derived from NVE hub height and rotor diameter data for each park).
rotor_zone = [park.rotor_min, park.rotor_max] // per-park, from NVE data bird_flight = [min_m, max_m] overlap = max(0, min(bird_max, rotor_max) - max(bird_min, rotor_min)) flight_range = bird_max - bird_min overlap_ratio = overlap / flight_range Risk classification: overlap = 0 → low (no icon) overlap_ratio > 50% → high (▲ red triangle) overlap_ratio ≤ 50% → medium (● yellow dot)
Example: white-tailed eagle flies at 50 to 300m. At Smøla (rotor zone 30-110m): overlap = min(300,110) - max(50,30) = 60m. Range = 250m. Ratio = 24% → medium. At Kjølberget (rotor zone 70-220m): overlap = min(300,220) - max(50,70) = 150m. Ratio = 60% → high.
When enabled, each of Norway's 357 municipalities (kommuner) is colored by observation count. This shows where our sample data is dense enough for meaningful analysis and where predictions should be treated with caution.
Method
Each bird observation is assigned to a kommune using point in polygon spatial join (ray-casting algorithm). The observation count per kommune determines the fill color.
| 0 observations — no data, lowest confidence | |
| 1 to 4 observations — very low confidence | |
| 5 to 14 observations — low confidence | |
| 15 to 29 observations — moderate confidence | |
| 30+ observations — good coverage (transparent) |
With a 10K sample across 357 kommuner, the average is ~28 observations per kommune. Inland mountain and northern municipalities typically have fewer observations due to lower population and fewer citizen-science contributors. Grey and red areas should not be used for risk assessment without additional data collection.
api.gbif.org/v1/occurrence/search | License: CC BY 4.0 / CC0 | No auth required
This is a screening tool, not a regulatory environmental impact assessment. Observation density reflects citizen-science reporting patterns, not true abundance. Flight altitudes are approximate estimates, not site-specific measurements. For actual wind farm planning, site-specific radar surveys and environmental assessments are required.
Built at Tekna Hackathon: Code your way to a greener world (Feb 27-28, 2026, Oslo).
| Almaz Ermilov |
| Michael Bitney |
| Dmitri Kuzkin |
| Marian Øverli |
GitHub repository · Live demo
All data from open sources. Code is open for hackathon purposes.