# Solar Installer Lead Finder & Contact Extractor (`nocodeninja_ng/enfsolar-installer-scraper`) Actor

Extract B2B leads from the top solar directory. Scrape installer details, phone numbers, brands, and certifications globally or by country. Features an optional enrichment engine that crawls company websites to uncover hidden email addresses and social media links

- **URL**: https://apify.com/nocodeninja\_ng/enfsolar-installer-scraper.md
- **Developed by:** [NoCodeNinja](https://apify.com/nocodeninja_ng) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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

## ENF Solar Installer Scraper ☀️

**ENF Solar Installer Scraper** is a high-performance Apify Actor designed to extract comprehensive business intelligence from the global ENF Solar directory.

Built on top of Crawlee's `CheerioCrawler`, this actor systematically maps the directory structure, handles pagination, and—when enabled—performs advanced deep-web footprinting by visiting installer websites to uncover hidden contact details and social links.

---

### 🌟 Features

* **Global or Targeted Crawling:** Scrape the entire directory globally or target specific countries (e.g., `Germany`, `United States`).
* **Deep Profile Extraction:** Look beyond the basic directory lists to pull granular info including corporate descriptions, battery storage capacities, installation sizes, certified brands, and year founded.
* **Deep Website Enrichment:** Goes past ENF's walled garden. It can directly visit the installer’s underlying website to discover hidden emails, communication routes, and social footprints.
* **Intelligent Anti-Bot Footprint:** Configurable execution delays and seamless Apify Proxy integration to easily bypass rigid `429 Too Many Requests` or IP rate limits.
* **Data Hygiene & Integrity:** Automated URL normalization, query/hash filtering, and cross-field deduplication ensure your dataset remains clean and unique.

---

### 🛑 Important Data Scope Note

> ⚠️ **Check Listing Volumes First:** Directory density varies drastically by region on ENF Solar. Some large countries feature thousands of records, while others host only a handful.
> Before launching massive resource crawls, it is highly recommended to manually inspect the target country on the [ENF Solar Directory](https://www.enfsolar.com/directory/installer) to understand expected yields and establish logical budget thresholds.

---

### 📥 Input Settings

Configure the scraper easily using the interactive console UI or pass a custom JSON object directly.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `countries` | `array` | `[]` | Explicit country names to target (e.g., `["Germany", "Nigeria"]`). Leave empty to crawl the **entire world**. |
| `maxPagesPerCountry` | `integer` | `0` | Upper pagination boundary per country. `0` = Scrape every page available. |
| `maxResults` | `integer` | `0` | Absolute item extraction ceiling. `0` = Run until queue exhaustion. |
| `scrapeProfiles` | `boolean` | `true` | When active, visits ENF profile pages to grab detailed attributes (brands, sizes, phone numbers). |
| `enrichContacts` | `boolean` | `false` | When true, safely exits ENF to crawl the target company's own website to scrape digital footprints. |
| `extractEmails` | `boolean` | `true` | Requires `enrichContacts`. Dynamically parses target corporate pages for contact email strings. |
| `extractSocials` | `boolean` | `true` | Requires `enrichContacts`. Scans for connected social ecosystems (LinkedIn, Facebook, etc.). |
| `maxWebsitePages` | `integer` | `5` | Maximum internal link depth to follow per company site during contact enrichment (Range: `1-20`). |
| `crawlSpeed` | `string` | `"Balanced"` | Dynamic rate limiter configuration. Choose between `Safe`, `Balanced`, or `Fast`. |
| `useApifyProxy` | `boolean` | `true` | Toggles Apify Datacenter/Residential proxy pools. **Highly recommended** to prevent blockades. |

#### Example Input Configuration

```json
{
  "countries": ["Germany", "United States"],
  "maxPagesPerCountry": 10,
  "maxResults": 250,
  "scrapeProfiles": true,
  "enrichContacts": true,
  "extractEmails": true,
  "extractSocials": true,
  "maxWebsitePages": 5,
  "crawlSpeed": "Balanced",
  "useApifyProxy": true
}

````

***

### 📤 Output Dataset Structure

Extracted business records are written directly to your Apify Dataset storage. Missing fields indicate data points not publicly exposed by ENF Solar or the target business website.

```json
{
  "companyId": "12345",
  "companyName": "Example Solar Ltd.",
  "profileUrl": "https://www.enfsolar.com/example-solar",
  "website": "https://example.com",
  "phone": "+1 555 123 4567",
  "address": "123 Solar Street, City, Country",
  "description": "Premium commercial solar installation provider specializing in grid-tied micro-inverter architectures.",
  "emails": ["info@examplesolar.com", "sales@examplesolar.com"],
  "linkedinUrls": ["https://linkedin.com/company/example-solar"],
  "facebookUrls": ["https://facebook.com/examplesolar"],
  "brands": ["Brand A", "Brand B"],
  "certifications": ["ISO 9001"],
  "yearFounded": "2012",
  "batteryStorage": "Yes",
  "installationSizes": ["1MWp+ Installations"],
  "operatingCountries": ["Germany"],
  "sourceCountry": "Germany",
  "scrapedAt": "2026-07-18T21:53:36.000Z"
}

```

***

### 💡 Pro Tips & Advanced Tuning

- **Mitigating 429 Bans:** ENF Solar aggressively monitors high-concurrency loops. If your logs begin filling with `429 Too Many Requests` or timeout retries, change your `crawlSpeed` parameter to `"Safe"` or manually step down your concurrency options.
- **Web Enrichment Speeds:** Enabling `enrichContacts` expands the scraper's target domain scope exponentially. While it produces significantly richer contact lists, it will increase overall execution runtime. Apply reasonable `maxWebsitePages` constraints to balance data generation against execution cost.

# Actor input Schema

## `countries` (type: `array`):

Country names to crawl (e.g. United States, Germany, Nigeria). Leave empty to crawl all countries.

## `maxPagesPerCountry` (type: `integer`):

Maximum listing pages to crawl for each country. Set to 0 to crawl all available pages.

## `maxResults` (type: `integer`):

Maximum number of installer records to save. Set to 0 to save all matching results.

## `scrapeProfiles` (type: `boolean`):

Visit each ENF company profile to extract website, phone number, description, address, brands, certifications and other company details.

## `enrichContacts` (type: `boolean`):

Visit each company's website to discover business emails, social media profiles and contact pages. This increases runtime.

## `extractEmails` (type: `boolean`):

Extract emails from company websites (mailto links, visible text and common email obfuscations). Only used when Website Contact Enrichment is enabled.

## `extractSocials` (type: `boolean`):

Extract LinkedIn, Facebook, Instagram, YouTube, X/Twitter and TikTok profile URLs. Only used when Website Contact Enrichment is enabled.

## `maxWebsitePages` (type: `integer`):

Maximum number of pages to crawl on each company website during enrichment. Homepage, Contact and About pages are prioritized.

## `crawlSpeed` (type: `string`):

Choose how aggressively the actor crawls ENF Solar. Balanced is recommended for most users.

## `useApifyProxy` (type: `boolean`):

Route requests through Apify Proxy. Strongly recommended for large crawls.

## Actor input object example

```json
{
  "countries": [],
  "maxPagesPerCountry": 0,
  "maxResults": 0,
  "scrapeProfiles": true,
  "enrichContacts": false,
  "extractEmails": true,
  "extractSocials": true,
  "maxWebsitePages": 5,
  "crawlSpeed": "Balanced",
  "useApifyProxy": true
}
```

# Actor output Schema

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

Default dataset containing installer records (see dataset\_schema.json for item schema).

# 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 = {
    "countries": [],
    "maxPagesPerCountry": 0,
    "maxResults": 0,
    "scrapeProfiles": true,
    "enrichContacts": false,
    "extractEmails": true,
    "extractSocials": true,
    "maxWebsitePages": 5,
    "crawlSpeed": "Balanced",
    "useApifyProxy": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("nocodeninja_ng/enfsolar-installer-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 = {
    "countries": [],
    "maxPagesPerCountry": 0,
    "maxResults": 0,
    "scrapeProfiles": True,
    "enrichContacts": False,
    "extractEmails": True,
    "extractSocials": True,
    "maxWebsitePages": 5,
    "crawlSpeed": "Balanced",
    "useApifyProxy": True,
}

# Run the Actor and wait for it to finish
run = client.actor("nocodeninja_ng/enfsolar-installer-scraper").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 '{
  "countries": [],
  "maxPagesPerCountry": 0,
  "maxResults": 0,
  "scrapeProfiles": true,
  "enrichContacts": false,
  "extractEmails": true,
  "extractSocials": true,
  "maxWebsitePages": 5,
  "crawlSpeed": "Balanced",
  "useApifyProxy": true
}' |
apify call nocodeninja_ng/enfsolar-installer-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nocodeninja_ng/enfsolar-installer-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Solar Installer Lead Finder & Contact Extractor",
        "description": "Extract B2B leads from the top solar directory. Scrape installer details, phone numbers, brands, and certifications globally or by country. Features an optional enrichment engine that crawls company websites to uncover hidden email addresses and social media links",
        "version": "1.0",
        "x-build-id": "CfrobJadDNIZMKIXz"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/nocodeninja_ng~enfsolar-installer-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-nocodeninja_ng-enfsolar-installer-scraper",
                "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/nocodeninja_ng~enfsolar-installer-scraper/runs": {
            "post": {
                "operationId": "runs-sync-nocodeninja_ng-enfsolar-installer-scraper",
                "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/nocodeninja_ng~enfsolar-installer-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-nocodeninja_ng-enfsolar-installer-scraper",
                "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": [
                    "scrapeProfiles",
                    "enrichContacts",
                    "crawlSpeed",
                    "useApifyProxy"
                ],
                "properties": {
                    "countries": {
                        "title": "Countries",
                        "type": "array",
                        "description": "Country names to crawl (e.g. United States, Germany, Nigeria). Leave empty to crawl all countries.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxPagesPerCountry": {
                        "title": "Maximum Pages Per Country",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum listing pages to crawl for each country. Set to 0 to crawl all available pages.",
                        "default": 0
                    },
                    "maxResults": {
                        "title": "Maximum Results",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum number of installer records to save. Set to 0 to save all matching results.",
                        "default": 0
                    },
                    "scrapeProfiles": {
                        "title": "Scrape Company Profiles",
                        "type": "boolean",
                        "description": "Visit each ENF company profile to extract website, phone number, description, address, brands, certifications and other company details.",
                        "default": true
                    },
                    "enrichContacts": {
                        "title": "Website Contact Enrichment",
                        "type": "boolean",
                        "description": "Visit each company's website to discover business emails, social media profiles and contact pages. This increases runtime.",
                        "default": false
                    },
                    "extractEmails": {
                        "title": "Extract Emails",
                        "type": "boolean",
                        "description": "Extract emails from company websites (mailto links, visible text and common email obfuscations). Only used when Website Contact Enrichment is enabled.",
                        "default": true
                    },
                    "extractSocials": {
                        "title": "Extract Social Media Profiles",
                        "type": "boolean",
                        "description": "Extract LinkedIn, Facebook, Instagram, YouTube, X/Twitter and TikTok profile URLs. Only used when Website Contact Enrichment is enabled.",
                        "default": true
                    },
                    "maxWebsitePages": {
                        "title": "Maximum Website Pages",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Maximum number of pages to crawl on each company website during enrichment. Homepage, Contact and About pages are prioritized.",
                        "default": 5
                    },
                    "crawlSpeed": {
                        "title": "Crawl Speed",
                        "enum": [
                            "Safe",
                            "Balanced",
                            "Fast"
                        ],
                        "type": "string",
                        "description": "Choose how aggressively the actor crawls ENF Solar. Balanced is recommended for most users.",
                        "default": "Balanced"
                    },
                    "useApifyProxy": {
                        "title": "Use Apify Proxy",
                        "type": "boolean",
                        "description": "Route requests through Apify Proxy. Strongly recommended for large crawls.",
                        "default": true
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
