# Power Outage Alerts by County & Site - US Utilities Data (`that_red_bird/power-outage-alerts`) Actor

Which of your sites are dark? Pulls live US county outages from the DOE/ORNL ODIN feed, matches your sites (lat/lng or county), flags new, worse and restored outages against the history it keeps. Covers participating utilities only, not all US customers.

- **URL**: https://apify.com/that_red_bird/power-outage-alerts.md
- **Developed by:** [mohamed alaya](https://apify.com/that_red_bird) (community)
- **Categories:** Automation, Business, Other
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 outage records

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

## Power Outage Alerts by County & Site - US Utilities Data

Pulls the live US county outage feed from the DOE / Oak Ridge National Laboratory ODIN program, tells you which of your sites sit in an affected county, and alerts you when an outage is new, getting worse, or restored, using history it keeps between runs.
For insurers, retail and restaurant chains, telecom and facilities teams, and anyone who wants outage data without scraping utility maps.

**Read this first - coverage:** ODIN contains only utilities that choose to publish to it (about 90 utilities, roughly 27 states in the feed today, reported at around a quarter of US customers - we have not verified that figure). A county missing from the feed is NOT proof the power is on. County totals count meters out across participating utilities in that county, not your building.

### Example inputs

**1. Default demo (no setup):** lists the 25 biggest current outages and checks two demo sites.

```json
{}
```

**2. Watch your sites by coordinates and county, alert only on changes, schedule every 15 minutes**

```json
{ "sites": [ {"name":"Store 12","lat":29.76,"lng":-95.37}, {"name":"DC East","state":"NY","county":"Dutchess"}, {"name":"HQ","fips":"06083"} ],
  "maxOutageRecords": 0, "siteAlertMinMeters": 500, "escalationPercent": 50, "onlyChanges": true, "webhookUrl": "https://example.com/hook" }
```

**3. State-level outage list for a report**

```json
{ "sites": [], "states": ["TX","CA"], "maxOutageRecords": 100 }
```

### Input guide

| Field | What it does |
|---|---|
| `sites` | JSON list. Each: `name` plus `lat`+`lng`, or `fips`, or `state`+`county`. |
| `maxOutageRecords` | County/utility outage rows to list, largest first (0 = site alerts only). |
| `states` | Limit the listed rows to these states (site matching still uses the whole feed). |
| `siteAlertMinMeters` | County total at which a site counts as affected. |
| `escalationPercent` | Growth (or crossing 1k / 10k / 50k meters) that triggers ESCALATED. |
| `onlyChanges` | Suppress repeat alerts for unchanged ongoing outages. |
| `webhookUrl` | POST each billed alert as JSON. Never fails the run. |
| `stateStoreName` | Named key-value store holding last totals and a rolling 600-point history per county. |

### Output

| Field | Meaning |
|---|---|
| `type` | `outage-record`, `site-alert` (billed), `site-status` (free), `error` (free) |
| `alert` | `NEW`, `ESCALATED`, `ONGOING`, `RESTORED`, `CLEAR` |
| `metersAffected`, `previousMetersAffected`, `changePct` | County total now vs the previous run |
| `severity` | minor (<1k), moderate, major (10k+), severe (50k+) |
| `utilities`, `earliestReportedStart`, `estimatedRestoration`, `cause` | Context from the feed |
| `matchedBy` | `point-in-county`, `state-county`, `fips`, or why nothing matched |
| `recentHistory[]` | Last readings kept in your store for that county |

Sample site alert: `{"type":"site-alert","site":"Dutchess pt","matchedBy":"point-in-county","county":"Dutchess","state":"New York","metersAffected":1598,"alert":"NEW","severity":"moderate","utilities":["CENTRAL HUDSON GAS & ELEC CORP"]}`

### Use it with

Google Maps scraper (store locations) or your CRM export -> `sites` -> this Actor on a 15-minute schedule -> webhook to Slack/PagerDuty/Zapier.

### FAQ

**Where does the data come from?** The ODIN public "Real-time Outages (County)" dataset on the ORNL Open Energy Hub (publisher: Oak Ridge National Laboratory / U.S. DOE Office of Electricity; county boundaries from the U.S. Census Bureau). The dataset metadata asserts no licence; we attribute it and use only the public, key-less feed.
**How fresh is it?** The feed updates about hourly; each utility's own cadence applies.
**Why no outages in my state?** Your utilities may not publish to ODIN. This Actor cannot see them.
**Can it tell if my building is dark?** No. It tells you the county is affected and how big the outage is. It is a trigger to check, not a meter.
**How does escalation work?** History is stored per site in your named store. Run it on a schedule: NEW when a site crosses your threshold, ESCALATED on growth or tier jumps, RESTORED when it drops back.

### Limits

County-level only (the authenticated ODIN API is finer but requires an account). Participating utilities only. First run has no history, so everything affected is NEW.

### Price

`outage-record` $0.002 per listed record, `site-alert` $0.01 per NEW / ESCALATED / RESTORED alert. Example: a 15-minute schedule on 40 sites with 3 alerts a day costs about $0.03/day. Status rows and errors are free.

# Actor input Schema

## `sites` (type: `array`):

JSON list of sites. Each needs a "name" and one of: "lat" and "lng" (point-in-county match), "fips" (5-digit county code), or "state" plus "county" (for example {"name":"Store 12","state":"TX","county":"Harris"}). State may be the full name or the 2-letter code.

## `maxOutageRecords` (type: `integer`):

How many county/utility outage records to output, largest first. Each is billed as one outage-record event. Set 0 to output only site alerts.

## `states` (type: `array`):

Limit the listed outage records to these states (full name or 2-letter code). Site matching always uses the full feed. Leave empty for all states.

## `siteAlertMinMeters` (type: `integer`):

A site counts as affected when the outages in its county add up to at least this many meters (customers) out. Counties are large, so this says the area is dark, not that your building is.

## `escalationPercent` (type: `integer`):

An already-affected site raises an ESCALATED alert when the county total grew by at least this percent since the last run, or crossed 1,000 / 10,000 / 50,000 meters.

## `onlyChanges` (type: `boolean`):

When on, a site that is still affected at about the same level is not re-alerted (and not billed) on later runs. NEW, ESCALATED and RESTORED always alert. Every site still gets a free status row.

## `webhookUrl` (type: `string`):

If set, every billed site alert is also POSTed here as JSON. A failing webhook never fails the run.

## `stateStoreName` (type: `string`):

Named key-value store that keeps the last county totals and a rolling history between runs. Use a different name per monitoring setup so schedules do not share history.

## Actor input object example

```json
{
  "sites": [
    {
      "name": "Demo site by coordinates (NYC)",
      "lat": 40.7128,
      "lng": -74.006
    },
    {
      "name": "Demo site by county (Santa Barbara CA)",
      "state": "CA",
      "county": "Santa Barbara"
    }
  ],
  "maxOutageRecords": 25,
  "states": [],
  "siteAlertMinMeters": 100,
  "escalationPercent": 50,
  "onlyChanges": true,
  "webhookUrl": "",
  "stateStoreName": "power-outage-alerts-state"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `downloadCsv` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `count` (type: `string`):

No description

# 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 = {
    "sites": [
        {
            "name": "Demo site by coordinates (NYC)",
            "lat": 40.7128,
            "lng": -74.006
        },
        {
            "name": "Demo site by county (Santa Barbara CA)",
            "state": "CA",
            "county": "Santa Barbara"
        }
    ],
    "maxOutageRecords": 25,
    "states": [],
    "siteAlertMinMeters": 100,
    "escalationPercent": 50,
    "onlyChanges": true,
    "webhookUrl": "",
    "stateStoreName": "power-outage-alerts-state"
};

// Run the Actor and wait for it to finish
const run = await client.actor("that_red_bird/power-outage-alerts").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 = {
    "sites": [
        {
            "name": "Demo site by coordinates (NYC)",
            "lat": 40.7128,
            "lng": -74.006,
        },
        {
            "name": "Demo site by county (Santa Barbara CA)",
            "state": "CA",
            "county": "Santa Barbara",
        },
    ],
    "maxOutageRecords": 25,
    "states": [],
    "siteAlertMinMeters": 100,
    "escalationPercent": 50,
    "onlyChanges": True,
    "webhookUrl": "",
    "stateStoreName": "power-outage-alerts-state",
}

# Run the Actor and wait for it to finish
run = client.actor("that_red_bird/power-outage-alerts").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 '{
  "sites": [
    {
      "name": "Demo site by coordinates (NYC)",
      "lat": 40.7128,
      "lng": -74.006
    },
    {
      "name": "Demo site by county (Santa Barbara CA)",
      "state": "CA",
      "county": "Santa Barbara"
    }
  ],
  "maxOutageRecords": 25,
  "states": [],
  "siteAlertMinMeters": 100,
  "escalationPercent": 50,
  "onlyChanges": true,
  "webhookUrl": "",
  "stateStoreName": "power-outage-alerts-state"
}' |
apify call that_red_bird/power-outage-alerts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,that_red_bird/power-outage-alerts"
        }
    }
}
```

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/gCvSQ7nx5S62ecT9v/builds/FPXdzX9uIQ0dk4D7U/openapi.json
