# Recipe: Real-Time Lightning Monitoring

import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "zudoku/ui/Accordion";

export const StepHeader = ({ n, children }) => (
  <span style={{ display: "inline-flex", alignItems: "center", gap: "0.75rem" }}>
    <span style={{
      display: "inline-flex",
      alignItems: "center",
      justifyContent: "center",
      width: "1.75rem",
      height: "1.75rem",
      minWidth: "1.75rem",
      borderRadius: "9999px",
      backgroundColor: "#F05514",
      color: "#FFFFFF",
      fontSize: "0.875rem",
      fontWeight: 600,
      flexShrink: 0,
      lineHeight: 1,
    }}>
      {n}
    </span>
    <span>{children}</span>
  </span>
);

This recipe shows how to retrieve recent lightning strike data near a location.

:::note
**These recipes are teaching examples — not production code.**

- **Host:** examples use the development host **apidev.accuweather.com**. Switch to **api.accuweather.com** for production.
- **Production hardening:** GZIP compression, caching, retries with exponential backoff, and error handling are not included. See the [Best Practices](/developers/best-practices) guide.
:::

## Scenario

> "I want to show users all lightning strikes that occurred within 25 miles of their location in the last 30 minutes."

---

<Accordion type="multiple" defaultValue={["step-1"]} className="my-6">

<AccordionItem value="step-1">
  <AccordionTrigger><StepHeader n={1}>Make the request</StepHeader></AccordionTrigger>
  <AccordionContent>

Call the Lightning strikes by point and radius endpoint with a latitude/longitude and time interval.

**Endpoint:**
```
GET https://apidev.accuweather.com/lightning/v1/{timeInterval}min/geoposition/radius.geojson?apikey={YOUR_API_KEY}&q={latitude},{longitude}&distanceRadius={miles}
```

<CodeTabs syncKey="language">

```ts title="TypeScript"
const apiKey = "{YOUR_API_KEY}";
const lat = 41.708;
const lon = -74.733;
const minutes = 30;
const radius = 25;

const response = await fetch(
  `https://apidev.accuweather.com/lightning/v1/${minutes}min/geoposition/radius.geojson?apikey=${apiKey}&q=${lat},${lon}&distanceRadius=${radius}`
);
const data: Record<string, any> = await response.json();
console.log(`${data.features.length} strikes found`);
```

```python title="Python"
import requests

api_key = "{YOUR_API_KEY}"
lat, lon = 41.708, -74.733
minutes = 30
radius = 25

response = requests.get(
    f"https://apidev.accuweather.com/lightning/v1/{minutes}min/geoposition/radius.geojson",
    params={"apikey": api_key, "q": f"{lat},{lon}", "distanceRadius": radius},
)
data = response.json()
print(f"{len(data['features'])} strikes found")
```

```csharp title="C#"
using var client = new HttpClient();

var apiKey = "{YOUR_API_KEY}";
var lat = 41.708;
var lon = -74.733;
var minutes = 30;
var radius = 25;
var url = $"https://apidev.accuweather.com/lightning/v1/{minutes}min/geoposition/radius.geojson?apikey={apiKey}&q={lat},{lon}&distanceRadius={radius}";
var response = await client.GetAsync(url);
var data = await response.Content.ReadAsStringAsync();
```

```java title="Java"
HttpClient client = HttpClient.newHttpClient();
String apiKey = "{YOUR_API_KEY}";
double lat = 41.708, lon = -74.733;
int minutes = 30, radius = 25;
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://apidev.accuweather.com/lightning/v1/"
        + minutes + "min/geoposition/radius.geojson?apikey=" + apiKey
        + "&q=" + lat + "," + lon + "&distanceRadius=" + radius))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String data = response.body();
```

```bash title="bash"
curl "https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson?apikey={YOUR_API_KEY}&q=41.708,-74.733&distanceRadius=25"
```

</CodeTabs>

  </AccordionContent>
</AccordionItem>

<AccordionItem value="step-2">
  <AccordionTrigger><StepHeader n={2}>Inspect the response</StepHeader></AccordionTrigger>
  <AccordionContent>

The response is a GeoJSON `FeatureCollection`. Each feature represents a single lightning strike.

```json
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-74.44090, 41.79958]
      },
      "properties": {
        "id": "592110c6-dfe0-5d55-b00f-ffef87993263",
        "date": "2025-07-31T15:45:36",
        "sourceId": 84,
        "strikeType": "",
        "peakCurrent": null
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-74.72598, 41.71068]
      },
      "properties": {
        "id": "121b839f-0848-5eb7-acab-fa1b8d49d34d",
        "date": "2025-07-31T15:46:04",
        "sourceId": 86,
        "strikeType": "cg",
        "peakCurrent": 32800
      }
    }
  ]
}
```

:::tip
The response is standard GeoJSON — you can pass it directly to mapping libraries like Leaflet, Mapbox GL, or Google Maps.
:::

  </AccordionContent>
</AccordionItem>

<AccordionItem value="step-3">
  <AccordionTrigger><StepHeader n={3}>Parse the strikes</StepHeader></AccordionTrigger>
  <AccordionContent>

<CodeTabs syncKey="language">

```ts title="TypeScript"
for (const feature of data.features) {
  const [lon, lat] = feature.geometry.coordinates;
  const { date, sourceId, strikeType, peakCurrent } = feature.properties;

  const source: Record<number, string> = { 84: "GOES East GLM", 85: "GOES West GLM", 86: "AccuWeather Lightning Network" };
  const type = strikeType === "cg" ? "Cloud-to-Ground"
            : strikeType === "ic" ? "Intra-Cloud"
            : "Unknown";

  console.log(`Strike at ${lat}, ${lon}`);
  console.log(`  Time: ${date} UTC`);
  console.log(`  Type: ${type} | Source: ${source[sourceId]}`);
  if (peakCurrent !== null) {
    console.log(`  Peak Current: ${peakCurrent > 0 ? "+" : ""}${peakCurrent}A (${peakCurrent > 0 ? "positive" : "negative"})`);
  }
}
```

```python title="Python"
sources = {84: "GOES East GLM", 85: "GOES West GLM", 86: "AccuWeather Lightning Network"}
types = {"cg": "Cloud-to-Ground", "ic": "Intra-Cloud", "": "Unknown"}

for feature in data["features"]:
    lon, lat = feature["geometry"]["coordinates"]
    props = feature["properties"]

    print(f"Strike at {lat}, {lon}")
    print(f"  Time: {props['date']} UTC")
    print(f"  Type: {types.get(props['strikeType'], 'Unknown')} | Source: {sources.get(props['sourceId'], 'Unknown')}")
    if props["peakCurrent"] is not None:
        polarity = "positive" if props["peakCurrent"] > 0 else "negative"
        print(f"  Peak Current: {props['peakCurrent']}A ({polarity})")
```

```csharp title="C#"
using System.Text.Json;

var doc = JsonDocument.Parse(data);
var sources = new Dictionary<int, string> { {84, "GOES East GLM"}, {85, "GOES West GLM"}, {86, "AccuWeather Lightning Network"} };

foreach (var feature in doc.RootElement.GetProperty("features").EnumerateArray())
{
    var coords = feature.GetProperty("geometry").GetProperty("coordinates");
    var fLon = coords[0].GetDouble();
    var fLat = coords[1].GetDouble();
    var props = feature.GetProperty("properties");
    var date = props.GetProperty("date").GetString();
    var sourceId = props.GetProperty("sourceId").GetInt32();
    var strikeType = props.GetProperty("strikeType").GetString();
    var type = strikeType == "cg" ? "Cloud-to-Ground"
             : strikeType == "ic" ? "Intra-Cloud" : "Unknown";

    Console.WriteLine($"Strike at {fLat}, {fLon}");
    Console.WriteLine($"  Time: {date} UTC");
    Console.WriteLine($"  Type: {type} | Source: {(sources.TryGetValue(sourceId, out var src) ? src : "Unknown")}");
    if (props.GetProperty("peakCurrent").ValueKind != JsonValueKind.Null)
    {
        var peakCurrent = props.GetProperty("peakCurrent").GetInt64();
        Console.WriteLine($"  Peak Current: {(peakCurrent > 0 ? "+" : "")}{peakCurrent}A ({(peakCurrent > 0 ? "positive" : "negative")})");
    }
}
```

```java title="Java"
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.Map;

var doc = new JSONObject(data);
var features = doc.getJSONArray("features");
var sources = Map.of(84, "GOES East GLM", 85, "GOES West GLM", 86, "AccuWeather Lightning Network");

for (int i = 0; i < features.length(); i++) {
    var feature = features.getJSONObject(i);
    var coords = feature.getJSONObject("geometry").getJSONArray("coordinates");
    var fLon = coords.getDouble(0);
    var fLat = coords.getDouble(1);
    var props = feature.getJSONObject("properties");
    var date = props.getString("date");
    var sourceId = props.getInt("sourceId");
    var strikeType = props.getString("strikeType");
    var type = strikeType.equals("cg") ? "Cloud-to-Ground"
             : strikeType.equals("ic") ? "Intra-Cloud" : "Unknown";

    System.out.println("Strike at " + fLat + ", " + fLon);
    System.out.println("  Time: " + date + " UTC");
    System.out.println("  Type: " + type + " | Source: " + sources.getOrDefault(sourceId, "Unknown"));
    if (!props.isNull("peakCurrent")) {
        var peakCurrent = props.getLong("peakCurrent");
        System.out.println("  Peak Current: " + (peakCurrent > 0 ? "+" : "") + peakCurrent + "A ("
            + (peakCurrent > 0 ? "positive" : "negative") + ")");
    }
}
```

```bash title="bash"
echo "$DATA" | jq -r '.features[] |
  "Strike at \(.geometry.coordinates[1]), \(.geometry.coordinates[0])\n" +
  "  Time: \(.properties.date) UTC\n" +
  "  Type: \(if .properties.strikeType == "cg" then "Cloud-to-Ground"
             elif .properties.strikeType == "ic" then "Intra-Cloud"
             else "Unknown" end) | " +
  "Source: \(if .properties.sourceId == 84 then "GOES East GLM"
             elif .properties.sourceId == 85 then "GOES West GLM"
             elif .properties.sourceId == 86 then "AccuWeather Lightning Network"
             else "Unknown" end)" +
  (if .properties.peakCurrent != null then
    "\n  Peak Current: \(.properties.peakCurrent)A (\(if .properties.peakCurrent > 0 then "positive" else "negative" end))"
   else "" end)'
```

</CodeTabs>

  </AccordionContent>
</AccordionItem>

</Accordion>

---

## Bounding box alternative

If you need strikes across a rectangular area (for example, a map viewport), call the bounding box endpoint instead of point-and-radius:

```bash
curl "https://apidev.accuweather.com/lightning/v1/30min/geoposition/points.geojson?apikey={YOUR_API_KEY}&upperLeft=42.0,-75.0&lowerRight=41.0,-74.0"
```

---

## Pagination

Results are returned in sets of 5,000. Use the `offset` parameter as a **page index** (`0` = first set, `1` = second set, etc.) to fetch additional sets:

```ts
let allStrikes: any[] = [];
let page = 0;

while (true) {
  const res = await fetch(
    `https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson?apikey=${apiKey}&q=${lat},${lon}&distanceRadius=${radius}&offset=${page}`
  );
  const data = await res.json();
  allStrikes.push(...data.features);

  if (data.features.length < 5000) break; // last page
  page++;
}
```

---

## Key response fields

| Field | Type | Description |
|-------|------|-------------|
| `geometry.coordinates` | Array | `[longitude, latitude]` of the strike |
| `properties.id` | String | Unique strike identifier |
| `properties.date` | String | Strike time in UTC |
| `properties.sourceId` | Integer | Data source: `84` (GOES East GLM), `85` (GOES West GLM), `86` (AccuWeather Lightning Network) |
| `properties.strikeType` | String | `"cg"` (cloud-to-ground), `"ic"` (intra-cloud), or `""` (unknown) |
| `properties.peakCurrent` | Integer | Strike amperage. Positive = positive polarity (more energetic). Negative = negative polarity (most common). `null` if unavailable. |
lysis for lightning forecast recipe 
---
lysis for lightning forecast recipe 
## Available time intervals

| Value | Description |
|-------|-------------|
| `5` | Last 5 minutes |
| `15` | Last 15 minutes |
| `30` | Last 30 minutes |
| `60` | Last 1 hour |
| `120` | Last 2 hours |

---

## Complete code sample

Copy a full, runnable example that fetches recent lightning strikes and prints a summary of each.

<CodeTabs syncKey="language">

```ts title="TypeScript"
const API_KEY = "{YOUR_API_KEY}";
const lat = 41.708;
const lon = -74.733;
const radius = 25;

// Step 1: Fetch recent strikes (last 30 minutes, within 25 miles)
const res = await fetch(
  `https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson?apikey=${API_KEY}&q=${lat},${lon}&distanceRadius=${radius}`
);
const data: Record<string, any> = await res.json();

console.log(`\n⚡ ${data.features.length} lightning strike(s) found in the last 30 minutes`);
console.log("━".repeat(42) + "\n");

// Step 2: Parse and print each strike
const sources: Record<number, string> = { 84: "GOES East GLM", 85: "GOES West GLM", 86: "AccuWeather Lightning Network" };

for (const feature of data.features) {
  const [fLon, fLat] = feature.geometry.coordinates;
  const { date, sourceId, strikeType, peakCurrent } = feature.properties;

  const type = strikeType === "cg" ? "Cloud-to-Ground"
            : strikeType === "ic" ? "Intra-Cloud"
            : "Unknown";

  console.log(`Strike at ${fLat}, ${fLon}`);
  console.log(`  Time: ${date} UTC`);
  console.log(`  Type: ${type} | Source: ${sources[sourceId] ?? "Unknown"}`);
  if (peakCurrent !== null) {
    const polarity = peakCurrent > 0 ? "positive" : "negative";
    console.log(`  Peak Current: ${peakCurrent > 0 ? "+" : ""}${peakCurrent}A (${polarity})`);
  }
}
```

```python title="Python"
import requests

API_KEY = "{YOUR_API_KEY}"
lat, lon = 41.708, -74.733
radius = 25

# Step 1: Fetch recent strikes (last 30 minutes, within 25 miles)
resp = requests.get(
    "https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson",
    params={"apikey": API_KEY, "q": f"{lat},{lon}", "distanceRadius": radius},
)
data = resp.json()

print(f"\n⚡ {len(data['features'])} lightning strike(s) found in the last 30 minutes")
print("━" * 42 + "\n")

# Step 2: Parse and print each strike
sources = {84: "GOES East GLM", 85: "GOES West GLM", 86: "AccuWeather Lightning Network"}
types = {"cg": "Cloud-to-Ground", "ic": "Intra-Cloud"}

for feature in data["features"]:
    f_lon, f_lat = feature["geometry"]["coordinates"]
    props = feature["properties"]

    strike_type = types.get(props["strikeType"], "Unknown")
    source = sources.get(props["sourceId"], "Unknown")

    print(f"Strike at {f_lat}, {f_lon}")
    print(f"  Time: {props['date']} UTC")
    print(f"  Type: {strike_type} | Source: {source}")
    if props["peakCurrent"] is not None:
        polarity = "positive" if props["peakCurrent"] > 0 else "negative"
        sign = "+" if props["peakCurrent"] > 0 else ""
        print(f"  Peak Current: {sign}{props['peakCurrent']}A ({polarity})")
```

```csharp title="C#"
using System.Text.Json;

var apiKey = "{YOUR_API_KEY}";
var lat = 41.708;
var lon = -74.733;
var radius = 25;

// Step 1: Fetch recent strikes (last 30 minutes, within 25 miles)
using var client = new HttpClient();
var response = await client.GetStringAsync(
    $"https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson?apikey={apiKey}&q={lat},{lon}&distanceRadius={radius}");

using var doc = JsonDocument.Parse(response);
var features = doc.RootElement.GetProperty("features");

Console.WriteLine($"\n⚡ {features.GetArrayLength()} lightning strike(s) found in the last 30 minutes");
Console.WriteLine(new string('━', 42) + "\n");

// Step 2: Parse and print each strike
var sources = new Dictionary<int, string> { {84, "GOES East GLM"}, {85, "GOES West GLM"}, {86, "AccuWeather Lightning Network"} };

foreach (var feature in features.EnumerateArray())
{
    var coords = feature.GetProperty("geometry").GetProperty("coordinates");
    var fLon = coords[0].GetDouble();
    var fLat = coords[1].GetDouble();
    var props = feature.GetProperty("properties");
    var date = props.GetProperty("date").GetString();
    var sourceId = props.GetProperty("sourceId").GetInt32();
    var strikeType = props.GetProperty("strikeType").GetString();

    var type = strikeType == "cg" ? "Cloud-to-Ground"
             : strikeType == "ic" ? "Intra-Cloud" : "Unknown";
    var source = sources.TryGetValue(sourceId, out var s) ? s : "Unknown";

    Console.WriteLine($"Strike at {fLat}, {fLon}");
    Console.WriteLine($"  Time: {date} UTC");
    Console.WriteLine($"  Type: {type} | Source: {source}");
    if (props.GetProperty("peakCurrent").ValueKind != JsonValueKind.Null)
    {
        var peakCurrent = props.GetProperty("peakCurrent").GetInt64();
        var polarity = peakCurrent > 0 ? "positive" : "negative";
        var sign = peakCurrent > 0 ? "+" : "";
        Console.WriteLine($"  Peak Current: {sign}{peakCurrent}A ({polarity})");
    }
}
```

```java title="Java"
import org.json.JSONObject;
import java.net.URI;
import java.net.http.*;
import java.util.Map;

public class LightningRealtime {
    public static void main(String[] args) throws Exception {
        String apiKey = "{YOUR_API_KEY}";
        double lat = 41.708, lon = -74.733;
        int radius = 25;

        // Step 1: Fetch recent strikes (last 30 minutes, within 25 miles)
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(
                "https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson?apikey="
                + apiKey + "&q=" + lat + "," + lon + "&distanceRadius=" + radius))
            .build();

        HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());

        var doc = new JSONObject(response.body());
        var features = doc.getJSONArray("features");

        System.out.println("\n⚡ " + features.length() + " lightning strike(s) found in the last 30 minutes");
        System.out.println("━".repeat(42) + "\n");

        // Step 2: Parse and print each strike
        var sources = Map.of(84, "GOES East GLM", 85, "GOES West GLM", 86, "AccuWeather Lightning Network");

        for (int i = 0; i < features.length(); i++) {
            var feature = features.getJSONObject(i);
            var coords = feature.getJSONObject("geometry").getJSONArray("coordinates");
            double fLon = coords.getDouble(0);
            double fLat = coords.getDouble(1);
            var props = feature.getJSONObject("properties");
            var date = props.getString("date");
            var sourceId = props.getInt("sourceId");
            var strikeType = props.getString("strikeType");

            var type = strikeType.equals("cg") ? "Cloud-to-Ground"
                     : strikeType.equals("ic") ? "Intra-Cloud" : "Unknown";
            var source = sources.getOrDefault(sourceId, "Unknown");

            System.out.println("Strike at " + fLat + ", " + fLon);
            System.out.println("  Time: " + date + " UTC");
            System.out.println("  Type: " + type + " | Source: " + source);
            if (!props.isNull("peakCurrent")) {
                long peakCurrent = props.getLong("peakCurrent");
                var polarity = peakCurrent > 0 ? "positive" : "negative";
                var sign = peakCurrent > 0 ? "+" : "";
                System.out.println("  Peak Current: " + sign + peakCurrent + "A (" + polarity + ")");
            }
        }
    }
}
```

```bash title="bash"
#!/bin/bash
API_KEY="{YOUR_API_KEY}"
LAT=41.708
LON=-74.733
RADIUS=25

# Step 1: Fetch recent strikes (last 30 minutes, within 25 miles)
DATA=$(curl -s "https://apidev.accuweather.com/lightning/v1/30min/geoposition/radius.geojson?apikey=${API_KEY}&q=${LAT},${LON}&distanceRadius=${RADIUS}")

COUNT=$(echo "$DATA" | jq '.features | length')
echo ""
echo "⚡ ${COUNT} lightning strike(s) found in the last 30 minutes"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""

# Step 2: Parse and print each strike
echo "$DATA" | jq -r '.features[] |
  "Strike at \(.geometry.coordinates[1]), \(.geometry.coordinates[0])\n" +
  "  Time: \(.properties.date) UTC\n" +
  "  Type: \(if .properties.strikeType == "cg" then "Cloud-to-Ground"
             elif .properties.strikeType == "ic" then "Intra-Cloud"
             else "Unknown" end) | " +
  "Source: \(if .properties.sourceId == 84 then "GOES East GLM"
             elif .properties.sourceId == 85 then "GOES West GLM"
             elif .properties.sourceId == 86 then "AccuWeather Lightning Network"
             else "Unknown" end)" +
  (if .properties.peakCurrent != null then
    "\n  Peak Current: \(.properties.peakCurrent)A (\(if .properties.peakCurrent > 0 then "positive" else "negative" end))"
   else "" end)'
```

</CodeTabs>

---

## Next steps

- [Lightning Forecast](/recipes/lightning-forecast) — check lightning probability for the next 2 hours
- [Historical Lightning](/recipes/lightning-historical) — analyze past lightning activity for a specific date
- [Lightning Parameters](/developers/lightning/parameters) — full API reference
