# Solar Resource & PVWatts Yield Scorer — Batch Site Screening (`malonestar/nrel-pvwatts-solar-resource-scorer`) Actor

Batch solar resource assessment via NREL PVWatts v8. Lat/lon list in; annual/monthly kWh yield, capacity factor, irradiance, and a solar-worthiness class out. The resource-quality layer for solar, storage, and data-center siting.

- **URL**: https://apify.com/malonestar/nrel-pvwatts-solar-resource-scorer.md
- **Developed by:** [Kyle Maloney](https://apify.com/malonestar) (community)
- **Categories:** Real estate, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.40 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Solar Resource & PVWatts Yield Scorer — Batch Site Screening

Batch solar resource assessment API built on **NREL PVWatts v8** (`developer.nrel.gov`).
Give it a list of lat/lon sites and get back annual/monthly solar production, capacity
factor, and a plain-English **solar-worthiness class** (excellent / good / fair / poor)
for each one — a due-diligence layer, not a proximity check.

### Who this is for

- **Solar developers & EPCs** triaging a pipeline of parcels before spending engineering
  time on the ones with weak solar resource.
- **Data-center and industrial site selectors** who need "how much on-site solar could we
  generate here" as one input to a siting scorecard.
- **CRE / real estate due diligence** teams answering "is this parcel solar-worthy" for a
  rooftop or ground-mount lease deal.
- **Solar sales teams** pre-qualifying inbound leads by ZIP/address before a site visit.

This is the **resource-quality layer** — it complements proximity/siting screeners like
BLM solar-siting-area, USWTDB turbine-proximity, and IRA energy-community-bonus (which
answer "can I build here / do I get an incentive here"). This actor answers **"is the sun
worth it here"**.

### How it works

For each `{ lat, lon, label }` in `assets`, the actor calls the NREL PVWatts v8 API with
your chosen system assumptions (capacity, module type, array type, tilt, azimuth, losses)
and maps the response into one normalized output row. Two API hosts are tried in order
(`developer.nrel.gov`, then a fallback) so a single host DNS/network hiccup doesn't fail
the whole run.

### Example input

```json
{
  "assets": [
    { "lat": 33.45, "lon": -112.07, "label": "Phoenix AZ site" },
    { "lat": 47.61, "lon": -122.33, "label": "Seattle WA control" }
  ],
  "apiKey": "DEMO_KEY",
  "systemCapacityKw": 4,
  "moduleType": 0,
  "arrayType": 1,
  "tilt": 20,
  "azimuth": 180,
  "losses": 14
}
````

Get your own free, instant NREL API key at **https://developer.nrel.gov/signup/** — the
shared `DEMO_KEY` works for quick tests but is rate-limited (~30 requests/hour) across
all anonymous users. With your own key you can batch far larger site lists.

### Output fields (one row per site)

| Field | Description |
|---|---|
| `label` | Site label from input |
| `lat`, `lon` | Input coordinates |
| `host_used` | Which PVWatts API host served this result |
| `ac_annual_kwh` | Total predicted annual AC energy production (kWh) |
| `solrad_annual_kwh_m2_day` | Average daily solar irradiance on the array (kWh/m²/day) |
| `capacity_factor_pct` | Actual annual output vs. full nameplate output, as a % |
| `kwh_per_kw_year` | Annual production normalized per kW of capacity — the comparable metric across sites |
| `best_month` / `worst_month` | `{ name, ac_kwh }` for the highest/lowest production months |
| `monthly_ac_kwh` | 12-element array of monthly AC production |
| `monthly_solrad` | 12-element array of monthly solar irradiance |
| `station_city` / `station_state` | NSRDB weather station PVWatts used for the simulation |
| `station_distance_m` | Distance from your site to that weather station, in meters |
| `solar_class` | Verdict: see thresholds below |
| `errors` | Non-null if this site could not be scored (bad input, rate limit, API error) |

#### Solar-class thresholds (from `capacity_factor_pct`)

- **excellent** — capacity factor ≥ 20%
- **good** — ≥ 17%
- **fair** — ≥ 14%
- **poor** — < 14%

These bands reflect typical U.S. fixed-tilt rooftop/ground-mount PV performance; adjust
your interpretation for tracking arrays (`arrayType` 2-4), which run higher.

### Use as an MCP tool

This actor is discoverable and callable by AI agents (Claude, Cursor, etc.) via
**mcp.apify.com** — Pay-Per-Event pricing and clean, field-level output descriptions make
it a good chainable tool in an agent siting/due-diligence workflow (e.g. "screen these 10
candidate rooftops for solar resource before I visit them").

### FAQ

**How much solar energy could I generate at this address?**
Pass the address's lat/lon as one `assets` entry; `ac_annual_kwh` and `kwh_per_kw_year`
give you the annual yield for your assumed system size.

**Is there a PVWatts batch API?**
NREL's own PVWatts API is single-site per call; this actor batches any list of sites in
one run and normalizes the output into a comparable table.

**How do I compare solar capacity factor by location?**
Run all your candidate sites in one `assets` array — `capacity_factor_pct` and
`solar_class` are directly comparable across rows since they use the same system
assumptions.

**What if I hit the DEMO\_KEY rate limit?**
Get your own free key at https://developer.nrel.gov/signup/ (30 seconds, no cost). On a
rate limit the actor emits a warning row for the remaining sites instead of failing the
whole run.

### Pricing

$8 per 1,000 results (one billable Result event per scored site — pay-per-event,
automatic dataset-item billing, no custom charges).

### Categories

Real estate · Developer tools · Agents / MCP servers

# Actor input Schema

## `assets` (type: `array`):

List of sites to score, each { lat, lon, label }. lat/lon are decimal degrees (WGS84); label is a free-text name shown on the output row (e.g. a parcel address or project name). One PVWatts call per site.

## `apiKey` (type: `string`):

Your free NREL Developer Network key (register in 30 seconds at https://developer.nrel.gov/signup/). The prefilled shared DEMO\_KEY works for small runs (~30 req/hr) but is rate-limited across all anonymous users; on HTTP 429 / OVER\_RATE\_LIMIT the actor emits a partial-results row per remaining site instead of failing the run.

## `systemCapacityKw` (type: `integer`):

Nameplate DC system size in kW used for the PVWatts simulation. Output kwh\_per\_kw\_year normalizes annual production per kW so sites of different assumed capacity remain comparable.

## `moduleType` (type: `integer`):

PVWatts module type: 0 = Standard, 1 = Premium, 2 = Thin film. Allowed values: 0, 1, 2.

## `arrayType` (type: `integer`):

PVWatts array/mounting type: 0 = Fixed - Open Rack, 1 = Fixed - Roof Mounted, 2 = 1-Axis Tracking, 3 = 1-Axis Backtracking, 4 = 2-Axis Tracking. Allowed values: 0, 1, 2, 3, 4.

## `tilt` (type: `integer`):

Panel tilt angle from horizontal in degrees (0 = flat, 90 = vertical). 20 degrees is a common default roof pitch.

## `azimuth` (type: `integer`):

Panel azimuth in degrees from north, clockwise (180 = due south, the typical northern-hemisphere optimum).

## `losses` (type: `integer`):

Overall PVWatts system-loss percentage (soiling, shading, wiring, inverter, etc.). NREL's default assumption is 14%.

## Actor input object example

```json
{
  "assets": [
    {
      "lat": 33.45,
      "lon": -112.07,
      "label": "Phoenix AZ site"
    },
    {
      "lat": 47.61,
      "lon": -122.33,
      "label": "Seattle WA control"
    }
  ],
  "apiKey": "DEMO_KEY",
  "systemCapacityKw": 4,
  "moduleType": 0,
  "arrayType": 1,
  "tilt": 20,
  "azimuth": 180,
  "losses": 14
}
```

# Actor output Schema

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

The default dataset with one solar-resource score row per site.

# 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 = {
    "assets": [
        {
            "lat": 33.45,
            "lon": -112.07,
            "label": "Phoenix AZ site"
        },
        {
            "lat": 47.61,
            "lon": -122.33,
            "label": "Seattle WA control"
        }
    ],
    "apiKey": "DEMO_KEY"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/nrel-pvwatts-solar-resource-scorer").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 = {
    "assets": [
        {
            "lat": 33.45,
            "lon": -112.07,
            "label": "Phoenix AZ site",
        },
        {
            "lat": 47.61,
            "lon": -122.33,
            "label": "Seattle WA control",
        },
    ],
    "apiKey": "DEMO_KEY",
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/nrel-pvwatts-solar-resource-scorer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "assets": [
    {
      "lat": 33.45,
      "lon": -112.07,
      "label": "Phoenix AZ site"
    },
    {
      "lat": 47.61,
      "lon": -122.33,
      "label": "Seattle WA control"
    }
  ],
  "apiKey": "DEMO_KEY"
}' |
apify call malonestar/nrel-pvwatts-solar-resource-scorer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malonestar/nrel-pvwatts-solar-resource-scorer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Solar Resource & PVWatts Yield Scorer — Batch Site Screening",
        "description": "Batch solar resource assessment via NREL PVWatts v8. Lat/lon list in; annual/monthly kWh yield, capacity factor, irradiance, and a solar-worthiness class out. The resource-quality layer for solar, storage, and data-center siting.",
        "version": "1.0",
        "x-build-id": "rw1UXi4OAUTHVN7CA"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/malonestar~nrel-pvwatts-solar-resource-scorer/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-malonestar-nrel-pvwatts-solar-resource-scorer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/malonestar~nrel-pvwatts-solar-resource-scorer/runs": {
            "post": {
                "operationId": "runs-sync-malonestar-nrel-pvwatts-solar-resource-scorer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/malonestar~nrel-pvwatts-solar-resource-scorer/run-sync": {
            "post": {
                "operationId": "run-sync-malonestar-nrel-pvwatts-solar-resource-scorer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "assets"
                ],
                "properties": {
                    "assets": {
                        "title": "Sites",
                        "type": "array",
                        "description": "List of sites to score, each { lat, lon, label }. lat/lon are decimal degrees (WGS84); label is a free-text name shown on the output row (e.g. a parcel address or project name). One PVWatts call per site."
                    },
                    "apiKey": {
                        "title": "NREL developer.nrel.gov API key",
                        "type": "string",
                        "description": "Your free NREL Developer Network key (register in 30 seconds at https://developer.nrel.gov/signup/). The prefilled shared DEMO_KEY works for small runs (~30 req/hr) but is rate-limited across all anonymous users; on HTTP 429 / OVER_RATE_LIMIT the actor emits a partial-results row per remaining site instead of failing the run."
                    },
                    "systemCapacityKw": {
                        "title": "System capacity (kW DC)",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Nameplate DC system size in kW used for the PVWatts simulation. Output kwh_per_kw_year normalizes annual production per kW so sites of different assumed capacity remain comparable.",
                        "default": 4
                    },
                    "moduleType": {
                        "title": "Module type",
                        "minimum": 0,
                        "maximum": 2,
                        "type": "integer",
                        "description": "PVWatts module type: 0 = Standard, 1 = Premium, 2 = Thin film. Allowed values: 0, 1, 2.",
                        "default": 0
                    },
                    "arrayType": {
                        "title": "Array type",
                        "minimum": 0,
                        "maximum": 4,
                        "type": "integer",
                        "description": "PVWatts array/mounting type: 0 = Fixed - Open Rack, 1 = Fixed - Roof Mounted, 2 = 1-Axis Tracking, 3 = 1-Axis Backtracking, 4 = 2-Axis Tracking. Allowed values: 0, 1, 2, 3, 4.",
                        "default": 1
                    },
                    "tilt": {
                        "title": "Array tilt (degrees)",
                        "minimum": 0,
                        "maximum": 90,
                        "type": "integer",
                        "description": "Panel tilt angle from horizontal in degrees (0 = flat, 90 = vertical). 20 degrees is a common default roof pitch.",
                        "default": 20
                    },
                    "azimuth": {
                        "title": "Array azimuth (degrees)",
                        "minimum": 0,
                        "maximum": 359,
                        "type": "integer",
                        "description": "Panel azimuth in degrees from north, clockwise (180 = due south, the typical northern-hemisphere optimum).",
                        "default": 180
                    },
                    "losses": {
                        "title": "System losses (%)",
                        "minimum": 0,
                        "maximum": 99,
                        "type": "integer",
                        "description": "Overall PVWatts system-loss percentage (soiling, shading, wiring, inverter, etc.). NREL's default assumption is 14%.",
                        "default": 14
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
