# EnergySage Solar Data Scraper (`maximedupre/energysage`) Actor

Choose one public EnergySage view per run: state solar costs, solar panel rankings, solar news, or installer profiles. Get structured fields and source links for solar research, cost comparisons, and installer lists.

- **URL**: https://apify.com/maximedupre/energysage.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Business, Lead generation, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.70 / 1,000 solar costs

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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

### ☀️ EnergySage solar data for every run

For solar analysts, installers, market researchers, and developers, this Actor collects one selected public EnergySage view per run. It returns structured state solar costs, solar panel rankings, solar news articles, or installer profiles with source links and retrieval times. Use the data to compare panel prices, review state costs, follow solar news, or build installer lists.

- Find **[Solar Installers California](https://apify.com/maximedupre/energysage/examples/solar-installers-california)** with public installer names, contacts, services, and locations.
- Build a state-aware installer list with **[Solar Installers](https://apify.com/maximedupre/energysage/examples/solar-installers)** from the EnergySage directory.
- Collect EnergySage source articles with **[Solar News](https://apify.com/maximedupre/energysage/examples/solar-news)** and their links and categories.
- Compare state-level solar costs with **[Solar Panel Cost](https://apify.com/maximedupre/energysage/examples/solar-panel-cost)** using installed cost, savings, and payback values.
- Compare panel prices with **[Solar Panel Prices](https://apify.com/maximedupre/energysage/examples/solar-panel-prices)** using price-per-watt and warranty data.
- Review top choices with **[Best Solar Panels](https://apify.com/maximedupre/energysage/examples/best-solar-panels)** from the selected best-overall category.
- Compare brands and models with **[Solar Panel Rankings](https://apify.com/maximedupre/energysage/examples/solar-panel-rankings)** across EnergySage categories.

#### 📦 Four EnergySage data views

**What this Actor returns**

Choose one view for each run. Rows include a `recordType` value so you can tell which view produced them. Source links and retrieval times are included; source update times are included when EnergySage publishes them.

**State solar costs**

Returns state, installed cost per watt, system size, total cost, estimated savings, estimated payback period, currency, source URL, and retrieval time.

**Solar panel rankings**

Returns brand, model, rank, efficiency, price per watt, warranty, power, panel type, category, currency, source URL, and retrieval time.

**Solar news articles**

Returns article title, article URL, categories, and retrieval time.

**Installer profiles**

Returns the EnergySage marketplace link, update and retrieval times, and the listed installer name, website, contact, location, description, services, service areas, equipment brands, financing partners, and qualification details.

#### ▶️ Run one public view at a time

**How a run works**

1. Choose one `target`: State solar costs, Solar panel rankings, Solar news, or Installer directory.
2. Set the options that apply to that view. Fields for other views are ignored.
3. Set `Maximum results` if you want a bound. Leave it empty to return all available results until the selected source is exhausted.
4. Run the Actor and open the dataset link in the output.

Each run reads supported public EnergySage pages. It does not request quotes, create personalized solar proposals, or use private account data.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `target` | string | Required. Select one public EnergySage view: `stateSolarCosts`, `solarPanelRankings`, `solarNews`, or `installerDirectory`. |
| `panelCategory` | string | For Solar panel rankings, choose `all`, `bestOverall`, `bestValue`, `mostEfficient`, or `bestWarranty`. Ignored for other views. |
| `serviceType` | string | Optional. For Installer directory, enter one service type to filter profiles. Ignored for other views. |
| `approvedOnly` | boolean | For Installer directory, keep only profiles marked EnergySage Approved. Ignored for other views. |
| `states` | array of strings | Optional. For State solar costs, choose one or more supported state codes, or leave empty for all 49 supported states except Nebraska. For Installer directory, choose one or more supported state codes. Ignored for Solar panel rankings and Solar news. |
| `maxItems` | integer | Optional. Stop after this many results. Leave it empty to return all available results until the selected source is exhausted. |

Nebraska (`NE`) is not a supported state-cost choice because EnergySage does not publish the required state-cost fields for it.

**Example input**

This is a smallest common input from a successful current-beta run:

```json
{
  "target": "solarPanelRankings",
  "maxItems": 1,
  "panelCategory": "all",
  "serviceType": "",
  "approvedOnly": false,
  "states": []
}
```

#### 🧾 Output

**Output link**

| Field | Type | What it does |
| --- | --- | --- |
| `results` | string (URL) | Links to the rows in the default dataset overview. |

**State solar cost**

| Field | Type | What it does |
| --- | --- | --- |
| `recordType` | string | Identifies this row as `stateSolarCost`. |
| `state` | string | State code for the solar cost data. |
| `installedCostPerWatt` | number | Installed solar cost for one watt of system capacity. |
| `systemSizeKw` | number | Solar system size in kilowatts. |
| `totalCost` | number | Total installed cost of the system. |
| `savings` | number | Estimated savings for the system. |
| `paybackPeriodYears` | number | Estimated years to pay back the system cost. |
| `currency` | string | Currency used for cost and savings values. |
| `sourceUrl` | string (URL) | EnergySage page for this state cost. |
| `retrievedAt` | string (date-time) | Time when the Actor retrieved the row. |
| `sourceUpdatedAt` | string (date-time) | Time shown by EnergySage for the source data, when published. |

One genuine row from a successful current-beta run:

```json
{
  "recordType": "stateSolarCost",
  "state": "AL",
  "installedCostPerWatt": 3.8080396475770937,
  "systemSizeKw": 14.11214757709251,
  "totalCost": 19040,
  "savings": 25359.893392070484,
  "paybackPeriodYears": 19.647797356828196,
  "currency": "USD",
  "sourceUrl": "https://www.energysage.com/local-data/solar-panel-cost/al/",
  "retrievedAt": "2026-08-09T00:12:34.102Z",
  "sourceUpdatedAt": "2026-07-31T00:00:00.000Z"
}
```

**Solar panel ranking**

| Field | Type | What it does |
| --- | --- | --- |
| `recordType` | string | Identifies this row as `solarPanelRanking`. |
| `brand` | string | Panel brand. |
| `model` | string | Panel model. |
| `rank` | integer | Panel rank in the selected category. |
| `efficiencyPercent` | number | Panel efficiency as a percent. |
| `pricePerWatt` | number | Panel price for one watt of rated power. |
| `warranty` | string | Warranty terms shown by EnergySage. |
| `wattageWatts` | number | Panel power in watts. |
| `panelType` | string | Panel type. |
| `category` | string | Ranking category used for the panel. |
| `currency` | string | Currency used for the price per watt. |
| `sourceUrl` | string (URL) | EnergySage page for this panel ranking. |
| `retrievedAt` | string (date-time) | Time when the Actor retrieved the row. |
| `sourceUpdatedAt` | string (date-time) | Time shown by EnergySage for the ranking data, when published. |

One genuine row from a successful current-beta run:

```json
{
  "recordType": "solarPanelRanking",
  "brand": "REC",
  "model": "Alpha Pure-RX",
  "rank": 1,
  "efficiencyPercent": 22.1,
  "pricePerWatt": 2.45,
  "warranty": "Product 25 years; performance 25 years",
  "wattageWatts": 460,
  "panelType": "Bifacial duo",
  "category": "all",
  "currency": "USD",
  "sourceUrl": "https://www.energysage.com/solar/best-solar-panels-complete-ranking/",
  "retrievedAt": "2026-08-09T00:00:31.867Z",
  "sourceUpdatedAt": "2026-07-01T00:00:00.000Z"
}
```

**Solar news article**

| Field | Type | What it does |
| --- | --- | --- |
| `recordType` | string | Identifies this row as `solarNewsArticle`. |
| `title` | string | Article title. |
| `articleUrl` | string (URL) | Link to the article. |
| `categories` | array of strings | Categories assigned to the article. |
| `retrievedAt` | string (date-time) | Time when the Actor retrieved the article. |

One genuine row from a successful current-beta run:

```json
{
  "recordType": "solarNewsArticle",
  "title": "Solar panels can boost home values by up to $79,000",
  "articleUrl": "https://www.energysage.com/news/solar-power-as-a-home-improvement-strategy/",
  "categories": [
    "Home solar"
  ],
  "retrievedAt": "2026-08-08T23:55:21.999Z"
}
```

**Installer profile**

The `installer` object keeps profile details nested. Fields that EnergySage does not publish for a profile may be absent.

| Field | Type | What it does |
| --- | --- | --- |
| `recordType` | string | Identifies this row as `installerProfile`. |
| `marketplaceUrl` | string (URL) | Link to the installer in the EnergySage marketplace. |
| `retrievedAt` | string (date-time) | Time when the Actor retrieved the profile. |
| `profileUpdatedAt` | string (date-time) | Time when the profile was last updated on EnergySage, when published. |
| `installer` | object | Installer details shown by EnergySage. |
| `installer.name` | string | Installer name. |
| `installer.websiteUrl` | string (URL) | Installer website link. |
| `installer.contact` | object | Listed contact details. |
| `installer.contact.phone` | string | Installer phone number, when listed. |
| `installer.contact.email` | string | Installer email address, when listed. |
| `installer.location` | object | Listed installer location. |
| `installer.location.address` | string | Street address, when listed. |
| `installer.location.city` | string | City, when listed. |
| `installer.location.state` | string | State, when listed. |
| `installer.location.postalCode` | string | Postal code, when listed. |
| `installer.location.country` | string | Country, when listed. |
| `installer.description` | string | Installer description, when listed. |
| `installer.foundedYear` | integer | Year the installer was founded, when listed. |
| `installer.services` | array of strings | Services listed for the installer. |
| `installer.serviceAreas` | array of strings | Areas where the installer offers service. |
| `installer.equipmentBrands` | array of strings | Equipment brands supported by the installer. |
| `installer.financingPartners` | array of strings | Financing partners listed for the installer. |
| `installer.qualification` | object | Approval and qualification details. |
| `installer.qualification.energySageApproved` | boolean | Whether EnergySage marks the installer as Approved. |
| `installer.qualification.licenses` | array of strings | Licenses listed for the installer. |
| `installer.qualification.workmanshipWarranty` | string | Workmanship warranty listed for the installer. |
| `installer.qualification.insurance` | string | Insurance information listed for the installer. |

One genuine row from a successful current-beta run:

```json
{
  "recordType": "installerProfile",
  "marketplaceUrl": "https://www.energysage.com/supplier/29287/roi-solar-inc/",
  "retrievedAt": "2026-08-09T00:05:09.961Z",
  "profileUpdatedAt": "2026-08-07T00:00:00.000Z",
  "installer": {
    "name": "R.O.I. Solar Inc.",
    "websiteUrl": "https://roisolarpower.com/",
    "contact": {
      "phone": "(209) 600-4433",
      "email": "marvin.w@roisolarpower.com"
    },
    "location": {
      "address": "2000 W Turner Rd",
      "city": "Lodi",
      "state": "CA",
      "postalCode": "95242",
      "country": "United States"
    },
    "description": "R.O.I. Solar Inc. is a licensed solar, battery storage, and roofing contractor serving California&#x27;s Central Valley and greater Sacramento region, including Lodi, Stockton, Modesto, Atwater, Sacramento, and Fairfield. As a licensed roofing contractor as well as a solar installer, we can address the whole roof — not just the panels on top of it. That means when a roof needs work before solar, we handle both under one roof, on one timeline, with one point of accountability. We install across PG&amp;E, SMUD, and community-choice territories and offer multiple ways to go solar: power purchase agreements, cash purchase, and financing. Our goal is straightforward — a system sized to your actual usage, installed to code, that does what we said it would do.",
    "services": [
      "Installation",
      "Financing",
      "Energy Auditing",
      "Construction",
      "Roofing",
      "Electrical Contracting",
      "General Contracting",
      "Solar Repair & Maintenance",
      "Commercial Solar"
    ],
    "serviceAreas": [
      "CA"
    ],
    "qualification": {
      "energySageApproved": true,
      "licenses": [
        "CSLB #1082435 — California solar and roofing contractor"
      ],
      "workmanshipWarranty": "10-year workmanship guarantee and 25 year product warranty"
    }
  }
}
```

#### 💳 Pricing

**How charging works**

The Actor charges per successfully saved public row. The selected view determines which buyer-facing event is used.

| Buyer-facing event | FREE | BRONZE | SILVER | GOLD | DIAMOND | PLATINUM |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| Solar cost | $0.0045 | $0.00385 | $0.0033 | $0.0027 | $0.0027 | $0.0027 |
| Panel ranking | $0.0045 | $0.00385 | $0.0033 | $0.0027 | $0.0027 | $0.0027 |
| News article | $0.0045 | $0.00385 | $0.0033 | $0.0027 | $0.0027 | $0.0027 |
| Installer profile | $0.0009 fixed | $0.0009 fixed | $0.0009 fixed | $0.0009 fixed | $0.0009 fixed | $0.0009 fixed |

#### 🔌 Integrations

**Apify dataset**

The output link opens the default Apify dataset view. You can use the dataset link with Apify's dataset tools or API.

**Video guide**

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can one run collect all four EnergySage views?

No. Choose one target for each run, then start another run for a different view.

##### How do I collect all available state costs or installer profiles?

Leave `maxItems` empty to return all available results until the selected source is exhausted. For State solar costs, also leave `states` empty to use all 49 supported states except Nebraska.

##### Why is Nebraska not in the state list?

EnergySage does not publish the required state-cost fields for Nebraska, so this Actor does not offer `NE` for the State solar costs view.

##### Can I narrow the installer directory?

Yes. For Installer directory, you can choose one or more states, enter one service type, and turn on EnergySage Approved only. These options apply to Installer directory; fields for other views are ignored.

##### What does the panel category change?

It selects the ranking view for Solar panel rankings: all panels, best overall, best value, most efficient, or best warranty.

##### Does this Actor return quotes or private EnergySage data?

No. It collects supported data from public EnergySage pages. It does not request quotes, create personalized proposals, or use account-only data.

##### Do I need an EnergySage account to run it?

No. The Actor reads supported public EnergySage pages and does not require buyer login or private account access.

### 📝 Changelog

**0.0: Initial release**

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~energysage/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- **[Solar Installer Directory Scraper - EnergySage Suppliers](https://apify.com/jungle_synthesizer/solar-installer-directory-scraper)** — Use it for an EnergySage directory-only crawl of installers, financiers, and equipment partners.
- **[EnergySage Solar Data Scraper](https://apify.com/crawlergang/energysage-scraper)** — Compare another EnergySage-focused option for panel rankings, state solar costs, news, and directory data.
- **[EnergySage Solar Data Scraper](https://apify.com/crawlerbros/energysage-scraper)** — Use a second EnergySage data option when you need the same public source views.
- **[Solar Industry - Installers, Reviews, Incentives & AI Analysis](https://apify.com/buseta/solar-industry-scraper)** — Add SolarReviews and DSIRE incentive data to broader solar market research.
- **[Solar Installer Lead Scraper - Verified Emails](https://apify.com/samstorm/solar-lead-scraper)** — Find solar installer contacts from Google Maps for a separate outreach list.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `target` (type: `string`):

Choose one public EnergySage view to collect. Each run uses one view.

## `panelCategory` (type: `string`):

For Solar panel rankings, choose a ranking category. This field is ignored for the other views.

## `serviceType` (type: `string`):

Optional. For Installer directory, enter one service type to filter profiles. This field is ignored for the other views.

## `approvedOnly` (type: `boolean`):

For Installer directory, keep only installers marked EnergySage Approved. This field is ignored for the other views.

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

Optional. For State solar costs, leave this empty to use all 49 supported states except Nebraska, or choose one or more listed states. Nebraska (NE) is not supported because EnergySage does not publish its required state-cost fields. For Installer directory, choose one or more listed states. This field is ignored for Solar panel rankings and Solar news.

## `maxItems` (type: `integer`):

Optional. Stop after this many results. Leave it empty to return all available results until the selected source is exhausted.

## Actor input object example

```json
{
  "target": "solarPanelRankings",
  "panelCategory": "all",
  "serviceType": "",
  "approvedOnly": false,
  "states": [],
  "maxItems": 10
}
```

# Actor output Schema

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

Link to the rows in the default dataset.

# 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 = {
    "target": "solarPanelRankings",
    "panelCategory": "all",
    "states": [],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/energysage").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 = {
    "target": "solarPanelRankings",
    "panelCategory": "all",
    "states": [],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/energysage").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 '{
  "target": "solarPanelRankings",
  "panelCategory": "all",
  "states": [],
  "maxItems": 10
}' |
apify call maximedupre/energysage --silent --output-dataset

```

## MCP server setup

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

```

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/9FuB9SZGF5EdjwDHI/builds/b8Zp5nA9XQe6ZFgNr/openapi.json
