# Marktstammdatenregister (MaStR) Scraper — German Energy Units (`haketa/marktstammdatenregister-scraper`) Actor

Extract solar, wind, biomass, hydro & storage units from Germany's official MaStR energy registry. Filter by energy source, state, postal code, operator & status. Get operator names, capacity (kW), commissioning date & location for B2B leads and market research.

- **URL**: https://apify.com/haketa/marktstammdatenregister-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Lead generation, Business
- **Features:** Limited permissions
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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/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

## Marktstammdatenregister Scraper — German Energy Units (Solar, Wind, Biomass, Storage & Operators)

> **Extract structured data on Germany's energy generation and consumption units from the [Marktstammdatenregister (MaStR)](https://www.marktstammdatenregister.de/MaStR)** — the official German market master data register for electricity and gas operated by the Federal Network Agency (Bundesnetzagentur). This **Marktstammdatenregister scraper** turns the official register into clean, structured datasets of commercial solar parks, rooftop photovoltaic systems, onshore and offshore wind turbines, biomass plants, hydropower, battery storage systems (BESS), and conventional generators, each with its **operator name, MaStR numbers, gross and net capacity in kW, operational status, commissioning dates, and exact geographic coordinates**. No login, no coding, and no complex manual queries.

Export to **JSON, CSV, Excel, or API** — or connect directly into PostgreSQL, Snowflake, Airtable, HubSpot, Google Sheets, Make, Zapier, and n8n.

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue)](https://apify.com/haketa/marktstammdatenregister-scraper)
[![Data Source](https://img.shields.io/badge/Data%20Source-Bundesnetzagentur%20MaStR-success)]()
[![Deep Pagination](https://img.shields.io/badge/Pagination-1%2C000%2B%20Unlocked-brightgreen)]()
[![Technologies](https://img.shields.io/badge/Energy%20Sources-Solar%20%7C%20Wind%20%7C%20Storage%20%7C%20Biomass-purple)]()
[![Coverage](https://img.shields.io/badge/Coverage-All%2016%20German%20States-red)]()
[![Output Formats](https://img.shields.io/badge/Format-JSON%20%7C%20CSV%20%7C%20Excel-orange)]()

> **Built for:** renewable energy sales reps, solar installers, wind farm operators, battery storage developers, energy traders, infrastructure fund managers, ESG analysts, and consultants mapping Germany's energy transition (*Energiewende*).

***

### ⚡ At a glance

| Feature | Details |
|---|---|
| **Data Source** | Bundesnetzagentur Marktstammdatenregister (MaStR) — Official German Energy Registry |
| **Geographic Scope** | All 16 German federal states (*Bundesländer*): Bayern, Baden-Württemberg, NRW, Niedersachsen, etc. |
| **Energy Sources** | Solar (PV), Wind (Onshore/Offshore), Biomass, Hydro, Battery Storage, Hydrogen, Geothermal, Gas, Coal |
| **Registry Scope** | Over 6.6 million electricity-generation units and millions of energy storage and consumption systems |
| **Key Output Fields** | Unit ID, MaStR #, unit name, energy source, status, operator name, operator MaStR #, gross/net kW, dates, location |
| **Commercial Filtering** | Filter by named commercial organizations (`isCommercial: true`) vs anonymized private residential systems |
| **Location Enrichment** | Optional deep enrichment adding city (*Ort*), postal code (*PLZ*), municipality, parcel, and WGS84 GPS coordinates |
| **Export Formats** | JSON, CSV, Excel (XLSX), XML, HTML table, webhook & REST API |
| **Max Capacity** | Scalable from 100 sample records to 1,000+ or multi-state deep extractions |
| **Execution Speed** | Up to 250 records per request batch; fast prefill runs finish in under 30 seconds |

***

### 🔎 Why scrape the Marktstammdatenregister (MaStR)?

The **Marktstammdatenregister (MaStR)** is the central statutory registry in Germany for all electricity and gas market participants and generation units. Managed by the Bundesnetzagentur, it documents every connected energy asset across Germany — from a 5 kW residential rooftop solar array in Bavaria to multi-megawatt commercial wind parks in Lower Saxony and industrial gas turbines in North Rhine-Westphalia.

While the data is legally public, navigating the government portal manually or relying on massive static file dumps creates serious operational bottlenecks:

- **B2B lead generation for solar & wind services:** Identify commercial operating companies (GmbH, AG, KG, eG) operating commercial-scale photovoltaic installations and wind turbines for operations and maintenance (O\&M), repowering, inverter replacement, and panel cleaning contracts.
- **Battery storage (BESS) co-location prospecting:** Pinpoint medium and large-scale solar farms commissioned without battery storage, creating high-intent lead lists for utility-scale battery integration and peak shaving systems.
- **Renewable energy market sizing & competitor intelligence:** Track which EPC contractors, municipal utilities (*Stadtwerke*), and independent power producers (IPPs) are building capacity across specific federal states or postal codes.
- **Power purchase agreement (PPA) origination:** Corporate energy buyers and green power traders can discover unsubsidized or post-EEG renewable assets approaching expiration of feed-in tariffs.
- **Site selection & grid infrastructure planning:** Map installed generation capacity by district and municipality to identify areas with high feed-in saturation or grid connection opportunities.

***

### 🗂️ Covered Technologies & Energy Sources

This scraper extracts units across all official MaStR technology classifications:

1. **Solar Photovoltaics (`solar`):** Ground-mounted solar parks (*Freiflächenanlagen*), commercial rooftop arrays, agrivoltaics, and floating solar systems. Includes module counts and gross kilowatt peak ratings.
2. **Wind Energy (`wind`):** Onshore wind turbines (*Windkraftanlagen an Land*) and offshore installations across the North Sea and Baltic Sea. Captures rotor hub heights and turbine capacities.
3. **Biomass & Biogas (`biomass`):** Solid biomass power plants, agricultural biogas facilities, and biomethane cogeneration (CHP) units.
4. **Hydropower (`hydro`):** Run-of-river stations, storage power plants, and pumped-storage hydroelectric facilities (*Wasserkraft*).
5. **Battery & Energy Storage (`storage`):** Utility-scale battery storage facilities, commercial storage systems (*Gewerbespeicher*), and grid-scale storage assets (*Speicheranlagen*).
6. **Hydrogen & Power-to-X (`hydrogen`):** Electrolyzers and hydrogen generation installations (*Wasserstofferzeuger*).
7. **Geothermal Energy (`geothermal`):** Deep geothermal power and combined heat and power plants (*Geothermie*).
8. **Conventional & Gas Generation:** Natural gas (*Erdgas*), mine gas (*Grubengas*), sewage gas (*Klärgas*), and thermal backup plants.

***

### ✨ Key Features & Capabilities

- ✅ **Official MaStR Registry Ingestion:** Fetches real-time structured data directly from the official register with full parameter support.
- ✅ **B2B Commercial Operator Focus:** Instantly isolate commercial corporate entities (`onlyCommercial: true`) such as GmbH, AG, KG, or energy cooperatives (*Bürgerenergiegenossenschaften*), filtering out anonymized residential records.
- ✅ **Deep 1,000+ Record Pagination:** Unlocked pagination engine allows collecting thousands of units across multiple states and energy types without arbitrary caps.
- ✅ **Precise Capacity Filtering:** Filter by minimum and maximum gross capacity (`minCapacityKw` / `maxCapacityKw`) to focus exclusively on commercial, industrial, or utility-scale facilities.
- ✅ **Geographic Targeting:** Filter by federal state (*Bundesland*), major city preset, specific municipality name, or 5-digit German postal code (*PLZ*).
- ✅ **Optional Location Enrichment:** Toggle `includeLocation: true` to enrich records with full municipal details, cadastral parcels (*Flurstück*), and WGS84 GPS latitude/longitude.
- ✅ **Automatic Deduplication:** Built-in hashing prevents duplicate entries when combining multiple energy types, states, and search queries.

***

### 📊 Extracted Data Fields

The scraper normalizes official register fields into an intuitive, developer-ready schema:

#### ⚡ Unit Identification & Technical Specs

| Field | Coverage | Description |
|---|---|---|
| `unitId` | 🟢 High (100%) | Internal MaStR registry unit identifier (e.g., `SEE918273645`) |
| `mastrNr` | 🟢 High (100%) | Official public MaStR registration number (e.g., `EEG901234567890`) |
| `unitName` | 🟢 High (100%) | Official registered unit name (e.g., `Solarpark Altötting II`) |
| `category` | 🟢 High (100%) | Primary registry category (e.g., `Stromerzeugung`) |
| `energySource` | 🟢 High (100%) | Normalized energy source (Solar, Wind, Biomass, Storage, etc.) |
| `grossPowerKw` | 🟢 High (100%) | Gross rated power capacity in kilowatts (*Bruttoleistung*) |
| `netPowerKw` | 🟢 High (98%) | Net nominal capacity fed into the grid (*Nettonennleistung*) |
| `solarModuleCount` | 🟡 Conditional | Number of installed solar modules (photovoltaic units only) |
| `detailUrl` | 🟢 High (100%) | Direct link to the unit's public page on Marktstammdatenregister |

#### 🏢 Operator & Commercial Information

| Field | Coverage | Description |
|---|---|---|
| `operatorName` | 🟢 High (100%) | Legal business entity name (anonymized for private individuals) |
| `operatorMastrNr` | 🟢 High (99%) | Operator's unique MaStR market partner number (e.g., `ABR987654321`) |
| `isCommercial` | 🟢 High (100%) | Boolean flag: `true` for commercial businesses/organizations, `false` for private individuals |

#### 📍 Geographic & Location Fields *(Enriched when `includeLocation: true`)*

| Field | Coverage | Description |
|---|---|---|
| `city` | 🟢 High (98%) | Municipality or city name (*Ort / Gemeinde*) |
| `postalCode` | 🟢 High (98%) | Official 5-digit German postal code (*Postleitzahl / PLZ*) |
| `state` | 🟢 High (99%) | Federal state (*Bundesland*, e.g., `Bayern`, `Nordrhein-Westfalen`) |
| `district` | 🟢 High (95%) | Administrative district (*Landkreis / kreisfreie Stadt*) |
| `municipality` | 🟢 High (95%) | Local administrative municipality (*Gemeinde*) |
| `latitude` | 🟡 Conditional (75-85%) | WGS84 GPS latitude for GIS mapping and spatial analysis |
| `longitude` | 🟡 Conditional (75-85%) | WGS84 GPS longitude for GIS mapping and spatial analysis |
| `parcel` | 🟡 Conditional | Cadastral land parcel identifier (*Flurstück / Gemarkung*) |

#### 📅 Operational Timestamps & Status

| Field | Coverage | Description |
|---|---|---|
| `status` | 🟢 High (100%) | Operational status (`In Betrieb`, `In Planung`, `Stillgelegt`) |
| `commissioningDate` | 🟢 High (97%) | Date unit commenced operation (*Inbetriebnahmedatum*, `YYYY-MM-DD`) |
| `reportedDate` | 🟢 High (99%) | Date unit was originally registered (*EinheitMeldedatum*, `YYYY-MM-DD`) |
| `lastUpdated` | 🟢 High (99%) | Date of last registry modification (*DatumLetzteAktualisierung*, `YYYY-MM-DD`) |
| `scrapedAt` | 🟢 High (100%) | UTC timestamp when record was extracted by the scraper |

***

### ⚙️ Input Parameters

Configure your extraction via the Apify Console or pass JSON parameters directly:

```json
{
  "unitCategory": "electricity-generation",
  "energyTypes": ["solar", "wind"],
  "states": ["bayern", "niedersachsen"],
  "operationalStatus": ["in-operation"],
  "onlyCommercial": true,
  "minCapacityKw": 100,
  "includeLocation": true,
  "maxItems": 500,
  "sortBy": "capacity-desc"
}
```

| Parameter | Type | Default | Description |
|---|---|---|---|
| `unitCategory` | `string` | `"electricity-generation"` | Registry category: `electricity-generation`, `electricity-consumption`, `gas-generation`, `gas-consumption`. |
| `energyTypes` | `array` | `[]` (all) | Filter by energy source: `solar`, `wind`, `biomass`, `hydro`, `storage`, `nuclear`, `hydrogen`, etc. |
| `states` | `array` | `[]` (all) | Filter by one or more German federal states (`bayern`, `nordrhein-westfalen`, `brandenburg`, etc.). |
| `operationalStatus` | `array` | `["in-operation"]` | Filter by operational status: `in-operation`, `in-planning`, `temporarily-shut-down`, `permanently-shut-down`. |
| `cityPreset` | `string` | `""` | Quick dropdown selector for major German cities (Berlin, Hamburg, München, Köln, Frankfurt, etc.). |
| `postalCode` | `string` | `""` | Filter by a specific 5-digit German postal code (PLZ). |
| `operatorName` | `string` | `""` | Search for specific operator or holding company names (e.g., `EnBW`, `RWE`, `Stadtwerke`). |
| `onlyCommercial` | `boolean` | `false` | Keep only named commercial organizations (`isCommercial: true`), omitting anonymized residential entries. |
| `minCapacityKw` | `integer` | `null` | Minimum gross capacity in kW. Set to `100`, `500`, or `1000` to target commercial installations. |
| `maxCapacityKw` | `integer` | `null` | Maximum gross capacity in kW. Useful for segmenting specific market tiers. |
| `includeLocation` | `boolean` | `false` | When enabled, fetches municipal location, PLZ, district, and GPS coordinates from detail records. |
| `sortBy` | `string` | `"newest"` | Result ordering: `newest`, `oldest`, `capacity-desc`, `commissioning-desc`. |
| `maxItems` | `integer` | `100` (prefill), `0` (default) | Maximum records to extract across all combinations. Set `0` for unlimited extraction. |
| `proxyConfiguration` | `object` | `{"useApifyProxy": true}` | Proxy configuration. Datacenter proxies ensure consistent throughput. |

***

### 📦 Sample Output

Every extracted unit is structured as normalized JSON:

```json
{
  "unitId": "SEE912847561923",
  "mastrNr": "EEG948172635412",
  "unitName": "Solarpark Mainfranken GmbH & Co. KG - Teilanlage 1",
  "category": "electricity-generation",
  "energySource": "Solar",
  "status": "In Betrieb",
  "operatorName": "Mainfranken Solar Asset Management GmbH",
  "operatorMastrNr": "ABR901827364512",
  "isCommercial": true,
  "grossPowerKw": 749.5,
  "netPowerKw": 720.0,
  "solarModuleCount": 1820,
  "commissioningDate": "2023-08-15",
  "reportedDate": "2023-08-20",
  "lastUpdated": "2024-02-10",
  "city": "Würzburg",
  "postalCode": "97076",
  "state": "Bayern",
  "district": "Würzburg",
  "municipality": "Würzburg",
  "latitude": 49.7913,
  "longitude": 9.9534,
  "parcel": "Flur 4, Flurstück 128/3",
  "detailUrl": "https://www.marktstammdatenregister.de/MaStR/Einheit/Detail/IndexOeffentlich/SEE912847561923",
  "scrapedAt": "2026-11-10T12:00:00.000Z"
}
```

***

### 💡 Practical B2B & Energy Use Cases

#### 1. Solar & Wind Repowering / O\&M Lead Generation

Filter for commercial solar or wind installations commissioned between 2000 and 2012 (`commissioningDate`) with capacities exceeding 500 kW (`minCapacityKw: 500`). As these facilities transition out of the initial 20-year EEG feed-in tariff guarantee, operators are prime candidates for repowering, modern inverters, PPA advisory, and comprehensive O\&M agreements.

#### 2. Large-Scale Battery Storage (BESS) Co-Location

Target commercial ground-mounted solar plants without registered co-located storage units. BESS developers can extract solar assets above 1 MW (`grossPowerKw >= 1000`) across Bavaria and Brandenburg to pitch revenue-stacking battery solutions (frequency regulation, arbitrage, and curtailment mitigation).

#### 3. Energy Asset Investment & Portfolio Due Diligence

Infrastructure funds, renewable IPPs, and private equity firms conducting market research can map regional asset concentration, operating company structures, and total megawatt capacity across specific federal states or grid distribution zones.

#### 4. Municipal Utilities (*Stadtwerke*) Benchmarking

Regional utilities can monitor newly registered photovoltaic installations and heat pumps across their concession areas (*Netzgebiet*) to forecast distribution grid load, transformer upgrades, and local renewable generation density.

***

### 🚀 How to Run via Apify API

Integrate MaStR data extraction directly into your automated pipelines:

#### Node.js (Apify Client)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('haketa/marktstammdatenregister-scraper').call({
    energyTypes: ['solar', 'storage'],
    states: ['bayern'],
    onlyCommercial: true,
    minCapacityKw: 250,
    includeLocation: true,
    maxItems: 500,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Retrieved ${items.length} commercial energy units from MaStR.`);
```

#### Python (Apify Client)

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.getenv('APIFY_TOKEN'))

run = client.actor('haketa/marktstammdatenregister-scraper').call(run_input={
    'energyTypes': ['wind'],
    'states': ['niedersachsen', 'schleswig-holstein'],
    'onlyCommercial': True,
    'minCapacityKw': 1000,
    'includeLocation': True,
    'maxItems': 1000,
})

dataset_items = client.dataset(run['defaultDatasetId']).list_items().items
print(f'Retrieved {len(dataset_items)} commercial wind units from MaStR.')
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/haketa~marktstammdatenregister-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "energyTypes": ["solar"],
    "states": ["nordrhein-westfalen"],
    "onlyCommercial": true,
    "maxItems": 250
  }'
```

***

### ❓ Frequently Asked Questions

**Why are some operator names listed as "(natürliche Person)"?**
Under German privacy law (BDSG/GDPR), private individuals who operate small residential rooftop solar systems or balcony power plants (*Balkonkraftwerke*) are anonymized in the public register. To focus exclusively on named businesses and commercial operators, turn on `onlyCommercial: true`.

**How does location enrichment work?**
The main register search index provides core unit metadata and operator names. When `includeLocation: true` is enabled, the scraper concurrently inspects each unit's public detail page to extract exact postal codes, city names, districts, municipalities, cadastral parcel IDs, and GPS coordinates.

**Can I extract 1,000+ units across multiple states?**
Yes. You can select multiple federal states (e.g., Bayern, Baden-Württemberg, and NRW) and multiple energy types. The actor automatically paginates in batches of 250 units and scales seamlessly up to your specified `maxItems` or 0 for unlimited.

**What is the difference between gross power and net power?**
Gross power (*Bruttoleistung*) is the peak generator nameplate capacity (e.g., total DC solar module capacity or maximum turbine rating). Net power (*Nettonennleistung*) is the maximum continuous active power that can actually be fed into the public electricity grid after internal station consumption and inverter losses.

**How fresh is the data in the register?**
Data is queried live from the official Marktstammdatenregister. Newly registered energy units, capacity adjustments, and commissioning reports are reflected in the registry in real time.

***

**Can I export data directly to GIS tools like QGIS or ArcGIS?**
Yes. When `includeLocation: true` is enabled, every record with geographic data includes `latitude` and `longitude` fields formatted in standard WGS84 coordinates. You can export the Apify dataset as CSV or GeoJSON and import it directly into QGIS, ArcGIS, Mapbox, or Google Earth.

**Can I search for a specific municipal utility or energy developer?**
Yes. Use the `operatorName` field to search for specific corporate entities, such as `Stadtwerke`, `EnBW`, `RWE`, `Vattenfall`, `LEAG`, or local citizen energy cooperatives (*Bürgerenergie*). The search performs substring matching across the official organization name.

**What happens if I leave all filters empty?**
A run with no filters returns a fast, diverse mixed sample of the newest ~100 units across Germany. This allows you to verify the dataset format and fields in seconds before launching targeted large-scale extractions.

**How do I schedule regular updates to track newly commissioned plants?**
You can set up an Apify Schedule (e.g., daily or weekly) with `sortBy: "commissioning-desc"` or `sortBy: "newest"` and your target federal states. New installations reported to the registry will appear at the top of each scheduled dataset run.

**Does the scraper handle grid connection status?**
Yes. Units report their operational status, including `In Betrieb` (currently operational and grid-connected), `In Planung` (permitted or under development), `Vorübergehend stillgelegt` (temporarily mothballed), and `Endgültig stillgelegt` (decommissioned).

**Can I filter by postal code prefixes?**
Yes. You can supply a specific 5-digit postal code (e.g., `80331` for central Munich) or enter postal codes through the API to pull localized clusters of energy generation.

### 🔗 Related Energy & Business Directory Scrapers

Complement your European energy market intelligence with these scrapers:

- [Bien'ici Real Estate Scraper](https://apify.com/haketa/bienici-scraper) — French residential & commercial property market intelligence
- [Hitta.se Swedish Business Directory Scraper](https://apify.com/haketa/hitta-se-business-scraper) — Swedish B2B firmographics and contacts
- [Arbeitsagentur Jobs Scraper](https://apify.com/haketa/arbeitsagentur-scraper) — German job board and talent intelligence

***

***

### 🗺️ German Federal State Coverage & Regional Energy Profiles

Germany displays distinct geographic specializations across its 16 federal states (*Bundesländer*):

- **Northern Wind Hubs (Niedersachsen, Schleswig-Holstein, Mecklenburg-Vorpommern):** Host Germany largest concentration of onshore and offshore wind parks, alongside growing green hydrogen electrolyzer projects and coastal battery storage installations.
- **Southern Solar Corridors (Bayern, Baden-Württemberg):** Lead the nation in ground-mounted photovoltaic farms (*Solarparks*), agrivoltaics, and commercial rooftop solar systems, driven by high global solar irradiance.
- **Western Industrial Belts (Nordrhein-Westfalen, Hessen, Rheinland-Pfalz):** Feature high densities of industrial combined heat and power (CHP), commercial battery peak-shaving systems, and industrial self-consumption installations.
- **Eastern Expansion Corridors (Brandenburg, Sachsen-Anhalt, Sachsen, Thüringen):** Major regions for gigawatt-scale hybrid solar-wind parks developed on former lignite surface mining areas and agricultural land.

***

### 📏 Capacity Tiers & B2B Market Segmentation

When configuring `minCapacityKw` and `maxCapacityKw`, consider these key statutory thresholds under the German Renewable Energy Sources Act (EEG):

- **Small Commercial & Farm Systems (30 kW – 100 kW):** Typical agricultural barns, commercial workshops, and SME rooftop PV installations with high self-consumption shares.
- **Mid-Sized Commercial Rooftops (100 kW – 750 kW):** Supermarket logistics hubs, factory roofs, and commercial office buildings. Installations up to 750 kW often participate in direct marketing (*Direktvermarktung*) without mandatory public tenders.
- **Utility-Scale Ground Mounts (750 kW – 100+ MW):** Large-scale solar parks and utility wind farms subject to Federal Network Agency EEG auctions or constructed under merchant corporate PPAs.
- **Commercial Battery Storage (50 kW – 10+ MW):** Grid-scale BESS assets installed next to sub-stations or co-located with solar parks for frequency response and day-ahead market trading.

### 📋 Changelog

#### Version 1.2 (2026-11)

- **Unlocked 1,000+ Deep Pagination:** Removed pagination bottlenecks, allowing multi-state and multi-technology runs to scale past 1,000 records seamlessly.
- **Fast Prefill Execution:** Optimized default run parameters to deliver a rich 100-record mixed German energy sample in <30 seconds.
- **Enhanced Location Parsing:** Improved coordinate normalization and district extraction across all 16 German federal states.
- **Improved Filter Combination Logic:** Enhanced deduplication when querying Cartesian product combinations of energy types and states.

#### Version 1.1 (2026-07)

- Added support for gas generation and consumption registry units.
- Integrated `onlyCommercial` boolean filter to cleanly segment B2B commercial entities from residential systems.
- Added sorting capabilities by capacity and commissioning dates.

#### Version 1.0 (2026-04)

- Initial release covering official MaStR electricity generation units (Solar, Wind, Biomass, Storage, Hydro).
- Support for municipal location enrichment, capacity filtering, and multi-format exports.

# Changelog

This Actor's version history is a separate document: https://apify.com/haketa/marktstammdatenregister-scraper/changelog.md

# Actor input Schema

## `unitCategory` (type: `string`):

Which part of the registry to scrape. Electricity generation covers solar, wind, biomass, hydro, storage and conventional power plants.

## `energyTypes` (type: `array`):

Filter by energy source (electricity-generation only). Leave empty for all sources. Each selected source is fetched separately and merged.

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

Filter by German federal state. Leave empty for all of Germany. Each state is fetched separately and merged.

## `operationalStatus` (type: `array`):

Filter by status. Defaults to units that are currently in operation. Each status is fetched separately and merged.

## `cityPreset` (type: `string`):

Pick a German city / municipality to focus on. Leave empty to search all of Germany.

## `city` (type: `string`):

Optional: type an exact city / municipality name not in the dropdown above, e.g. "Freiburg im Breisgau". Overrides the dropdown when set. Leave empty to use the dropdown.

## `postalCode` (type: `string`):

Filter by exact German postal code, e.g. "10115".

## `operatorName` (type: `string`):

Filter by operator name (organisations only), e.g. "GmbH", "Solarpark", "Energie". Great for finding commercial operators for B2B leads.

## `onlyCommercial` (type: `boolean`):

Keep only units with a named (non-anonymised) operator — i.e. companies and organisations. Private individuals are anonymised by the registry.

## `includeLocation` (type: `boolean`):

Fetch each unit's public detail page to add its exact location: city (Ort), postal code (PLZ), federal state, district (Landkreis), municipality (Gemeinde), parcel and WGS84 coordinates. Slower (one extra request per unit) but gives you full geography for mapping and territory planning. Off by default for fast, lightweight runs.

## `minCapacityKw` (type: `integer`):

Keep only units with gross power (Bruttoleistung) at or above this value in kW.

## `maxCapacityKw` (type: `integer`):

Keep only units with gross power (Bruttoleistung) at or below this value in kW.

## `sortBy` (type: `string`):

Order in which units are fetched from the registry.

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

Maximum number of units to return across all filters. Set 0 for no limit. Tip: a run with no filters returns a fast mixed sample of the newest ~150 units — add filters and raise this to go deeper.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. A proxy is optional but recommended for large runs to keep them fast and reliable.

## Actor input object example

```json
{
  "unitCategory": "electricity-generation",
  "operationalStatus": [
    "in-operation"
  ],
  "cityPreset": "",
  "onlyCommercial": false,
  "includeLocation": false,
  "sortBy": "newest",
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `unitId` (type: `string`):

Internal registry unit ID

## `mastrNr` (type: `string`):

Official MaStR unit number

## `unitName` (type: `string`):

Display name of the unit

## `category` (type: `string`):

Registry category (electricity/gas generation/consumption)

## `energySource` (type: `string`):

Energy source (Solar, Wind, Biomass, ...)

## `status` (type: `string`):

Operational status

## `operatorName` (type: `string`):

Operator name (organisations; private individuals anonymised)

## `operatorMastrNr` (type: `string`):

Operator's MaStR number

## `isCommercial` (type: `string`):

True if the operator is a named organisation

## `grossPowerKw` (type: `string`):

Gross capacity in kW (Bruttoleistung)

## `netPowerKw` (type: `string`):

Net nominal capacity in kW (Nettonennleistung)

## `solarModuleCount` (type: `string`):

Number of solar modules (solar units)

## `commissioningDate` (type: `string`):

Date the unit went into operation

## `reportedDate` (type: `string`):

Date the unit was reported to the registry

## `lastUpdated` (type: `string`):

Last update date in the registry

## `city` (type: `string`):

City / municipality (Ort) — filled when Include location is on

## `postalCode` (type: `string`):

Postal code (PLZ) — filled when Include location is on

## `state` (type: `string`):

Federal state (Bundesland) — filled when Include location is on

## `district` (type: `string`):

District (Landkreis) — filled when Include location is on

## `municipality` (type: `string`):

Municipality (Gemeinde) — filled when Include location is on

## `latitude` (type: `string`):

WGS84 latitude — filled when Include location is on

## `longitude` (type: `string`):

WGS84 longitude — filled when Include location is on

## `parcel` (type: `string`):

Cadastral parcel (Flurstück) — filled when Include location is on

## `detailUrl` (type: `string`):

Public MaStR detail page URL

## `scrapedAt` (type: `string`):

Extraction timestamp

# 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 = {
    "operationalStatus": [
        "in-operation"
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/marktstammdatenregister-scraper").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 = {
    "operationalStatus": ["in-operation"],
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/marktstammdatenregister-scraper").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 '{
  "operationalStatus": [
    "in-operation"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call haketa/marktstammdatenregister-scraper --silent --output-dataset

```

## MCP server setup

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

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/59q1rdFjVXFHNRAuo/builds/7pMLJ1muh5eDGgjOg/openapi.json
