GeoInsight API Docs Log in Get an API key

Light pollution API

Night-sky radiance and Bortle class for a point or a batch, from VIIRS satellite data.

GET /v1/light-pollution POST /v1/light-pollution

Base URL https://geoinsight.dev. Every request needs the X-API-Key header — see authentication, what this call costs and error codes.

GET /v1/light-pollution

Night-sky radiance and estimated Bortle scale at a point. Data source: Earth Observation Group, VIIRS VNL Annual. Useful for dark-sky planning, observatories, and astronomy sites.

Request

FieldTypeRequiredDefaultDescription
latfloatyesLatitude, −90..90.
lngfloatyesLongitude, −180..180.
interpolationstringnobilinearbilinear or nearest.

Examples

curl -H "X-API-Key: gi_live_..." \
  "https://geoinsight.dev/v1/light-pollution?lat=37.7749&lng=-122.4194"
import requests

r = requests.get(
"https://geoinsight.dev/v1/light-pollution",
params={"lat": 37.7749, "lng": -122.4194},
headers={"X-API-Key": "gi_live_..."},
)
print(r.json()["results"][0]["estimated_bortle"])
const res = await fetch(
  "https://geoinsight.dev/v1/light-pollution?lat=37.7749&lng=-122.4194",
  { headers: { "X-API-Key": "gi_live_..." } },
);
const data = await res.json();
console.log(data.results[0].estimated_bortle);

Response

{
  "results": [{
"lat": 37.7749,
"lng": -122.4194,
"radiance_nw_cm2_sr": 2.31,
"estimated_sky_brightness_mag_arcsec2": 19.78,
"estimated_bortle": 5
  }],
  "dataset": "viirs-vnl-v2-2024",
  "resolution_m": 463
}
Field Type Unit Description
results array One entry per requested point, in input order.
results[].lat number deg Latitude echoed back from the request.
results[].lng number deg Longitude echoed back from the request.
results[].radiance_nw_cm2_sr number nW/cm²/sr Measured upward night-time radiance — the only directly observed value here. null outside coverage.
results[].estimated_sky_brightness_mag_arcsec2 number mag/arcsec² Derived, not measured: sky brightness from the heuristic below. Higher is darker. null when radiance is null.
results[].estimated_bortle integer Bortle 1–9 Derived Bortle class read off the sky brightness. 1 = pristine dark sky, 9 = inner-city. null when radiance is null.
dataset string Source dataset identifier, including the annual composite year.
resolution_m integer m Ground sample distance of VIIRS (~463 m) — much coarser than the elevation data.

Heuristic: Radiance to Bortle scale

The estimated_sky_brightness_mag_arcsec2 is derived from VIIRS upward radiance in three steps:

  1. B_art = C × radiance — artificial sky brightness in mcd/m², where C is a calibration constant (default 0.5) converting VIIRS radiance to an artificial-glow contribution.
  2. total = B_art + 0.171168465 mcd/m² — add the natural night-sky background (0.171168465 mcd/m² corresponds to 22.00 mag/arcsec², a pristine sky).
  3. sky_brightness = log₁₀(total / 108000000) / −0.4 mag/arcsec².

Example: radiance 2.31 nW/cm²/sr with C = 0.5total = 0.5 × 2.31 + 0.171168465 ≈ 1.326 mcd/m² → sky_brightness ≈ 19.78 mag/arcsec² → Bortle 5. The estimated_bortle scale is then read off the resulting sky brightness:

BortleSky Brightness (mag/arcsec²)Description
1≥ 21.99Excellent dark-sky site
2≥ 21.89Typical truly dark site
3≥ 21.69Rural sky
4≥ 20.49Rural/suburban transition
5≥ 19.50Suburban sky
6≥ 18.94Bright suburban sky
7≥ 18.38Suburban/urban transition
8≥ 17.80City sky
9< 17.80Inner-city sky

Attribution & Data source

Data: Earth Observation Group, Payne Institute for Public Policy (Colorado School of Mines), VIIRS VNL Annual V2 — licensed under CC-BY-4.0. See EOG data portal for attribution, citations, and terms.

Caveat: Estimates, not observations

The estimated_sky_brightness_mag_arcsec2 and estimated_bortle fields are estimates derived from VIIRS upward radiance. VIIRS measures light traveling upward into space; the estimated sky brightness at an observer's eye on the ground may differ due to atmospheric scattering, local topography, and aerosol optical depth. Use these estimates for comparative dark-sky scouting, not for precise photometric work.

POST /v1/light-pollution

Night-sky radiance and estimated Bortle scale for up to 100 points in a single request. Results are returned in the same order as the input points. See the heuristic, attribution and caveat under GET /v1/light-pollution above.

Request (JSON body)

FieldTypeRequiredDefaultDescription
pointsarrayyes1–100 objects, each { "lat": …, "lng": … }.
points[].latfloatyesLatitude, −90..90.
points[].lngfloatyesLongitude, −180..180.
interpolationstringnobilinearbilinear or nearest.

Examples

curl -H "X-API-Key: gi_live_..." -X POST "https://geoinsight.dev/v1/light-pollution" \
  -H "Content-Type: application/json" \
  -d '{"points":[{"lat":37.7749,"lng":-122.4194},{"lat":36.6116,"lng":-116.8617}]}'
import requests

r = requests.post(
"https://geoinsight.dev/v1/light-pollution",
json={"points": [{"lat": 37.7749, "lng": -122.4194}, {"lat": 36.6116, "lng": -116.8617}]},
headers={"X-API-Key": "gi_live_..."},
)
print(r.json()["results"])
const res = await fetch("https://geoinsight.dev/v1/light-pollution", {
  method: "POST",
  headers: { "X-API-Key": "gi_live_...", "Content-Type": "application/json" },
  body: JSON.stringify({ points: [{ lat: 37.7749, lng: -122.4194 }, { lat: 36.6116, lng: -116.8617 }] }),
});
console.log((await res.json()).results);

Response

{
  "results": [
{ "lat": 37.7749, "lng": -122.4194, "radiance_nw_cm2_sr": 2.31, "estimated_sky_brightness_mag_arcsec2": 19.78, "estimated_bortle": 5 },
{ "lat": 36.6116, "lng": -116.8617, "radiance_nw_cm2_sr": 0.05, "estimated_sky_brightness_mag_arcsec2": 21.85, "estimated_bortle": 3 }
  ],
  "dataset": "viirs-vnl-v2-2024",
  "resolution_m": 463
}
Field Type Unit Description
results array One entry per input point, in the same order. Match by index.
results[].lat number deg Latitude echoed back from the request.
results[].lng number deg Longitude echoed back from the request.
results[].radiance_nw_cm2_sr number nW/cm²/sr Measured upward night-time radiance. null outside coverage.
results[].estimated_sky_brightness_mag_arcsec2 number mag/arcsec² Derived sky brightness; higher is darker. null when radiance is null.
results[].estimated_bortle integer Bortle 1–9 Derived Bortle class. null when radiance is null.
dataset string Source dataset identifier.
resolution_m integer m Ground sample distance of the VIIRS raster.